diff --git a/.gitignore b/.gitignore index 438ff5a1ffad836b6d630aa7265d0216a2c4b8ee..8990b55075c8da9298adc7de0937acf290a15f02 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ bt5/bt5list product/ERP5/bootstrap/bt5list TAGS tags +bt5list diff --git a/product/ERP5/Document/BusinessCommit.py b/product/ERP5/Document/BusinessCommit.py new file mode 100644 index 0000000000000000000000000000000000000000..7b535336799e9d11c16ae8c1af8611843eb79563 --- /dev/null +++ b/product/ERP5/Document/BusinessCommit.py @@ -0,0 +1,186 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SARL and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import gc +import os +import posixpath +import transaction +import imghdr +import tarfile +import time +import hashlib +import fnmatch +import re +import threading +import pprint + +from copy import deepcopy +from collections import defaultdict +from cStringIO import StringIO +from OFS.Image import Pdata +from lxml.etree import parse +from urllib import quote, unquote +from OFS import SimpleItem, XMLExportImport +from datetime import datetime +from itertools import chain +from operator import attrgetter +from persistent.list import PersistentList +from AccessControl import ClassSecurityInfo, Unauthorized, getSecurityManager +from Acquisition import Implicit, aq_base, aq_inner, aq_parent +from zLOG import LOG, INFO, WARNING + +from Products.ERP5Type.XMLObject import XMLObject +from Products.ERP5Type.Core.Folder import Folder +from Products.CMFCore.utils import getToolByName +from Products.PythonScripts.PythonScript import PythonScript +from Products.ERP5Type.dynamic.lazy_class import ERP5BaseBroken +from Products.ERP5Type.Globals import Persistent, PersistentMapping +from Products.ERP5Type import Permissions, PropertySheet, interfaces +from Products.ERP5Type.Globals import InitializeClass +from Products.ERP5Type.TransactionalVariable import getTransactionalVariable +from Products.ERP5Type.patches.ppml import importXML +from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter + +class BusinessCommit(Folder): + + meta_type = 'ERP5 Business Commit' + portal_type = 'Business Commit' + add_permission = Permissions.AddPortalContent + allowed_types = ('Business Item',) + + id_generator = '_generateUniversalUniqueId' + + template_format_version = 3 + + # Factory Type Information + factory_type_information = \ + { 'id' : portal_type + , 'meta_type' : meta_type + , 'icon' : 'file_icon.gif' + , 'product' : 'ERP5Type' + , 'factory' : '' + , 'type_class' : 'BusinessCommit' + , 'immediate_view' : 'BusinessCommit_view' + , 'allow_discussion' : 1 + , 'allowed_content_types': ('Business Item',) + , 'filter_content_types' : 1 + } + + # Declarative security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + # Declarative properties + property_sheets = ( + PropertySheet.Base, + PropertySheet.XMLObject, + PropertySheet.SimpleItem, + PropertySheet.CategoryCore, + PropertySheet.Version, + ) + + def createEquivalentSnapshot(self): + """ + This function uses the current commit to create a new snapshot + """ + site = self.getPortalObject() + portal_commits = self.aq_parent + + # Create empty snapshot + snapshot = portal_commits.newContent(portal_type='Business Snapshot') + # Add the current commit as predecessor. This way we can have the BI + # BPI in that commit to the Business Snapshot also. + snapshot.setSimilarValue(self) + self.setSimilarValue(snapshot) + + # Build the snapshot + if snapshot not in [None, self]: + if site.portal_workflow.isTransitionPossible( + snapshot, 'build'): + snapshot.build() + + return snapshot + + def install(self): + """ + Installation: + - Check if the status is committed (Done by constraint of Business Commit + portal_type) + - Check if there are installed Business Template V2(s) because they will be + required in building new Business Snapshot. Raise if there are None. + - Create an equivalent snapshot (using items of this commit and predecessors + belonging to installed Business Template V2s) + - TODO: Compare the snapshot with the last snapshot + - Install the snapshot + """ + site = self.getPortalObject() + portal_templates = site.portal_templates + installed_bt_list = portal_templates.getInstalledBusinessTemplateV2List() + + # Should raise if there is no installed BM in ZODB. Should install BM via + # portal_templates first. + # XXX: Maybe instead of raising, we can provide an option to install BM + # here only. So that a new user don't get confused ? + if not installed_bt_list: + raise ValueError('There is no installed BT to create snapshot') + + successor_list = self.getPredecessorRelatedValueList() + + # Check if the successor list has a snapshot in it + try: + eqv_snapshot = [l for l + in successor_list + if l.getPortalType() == 'Business Snapshot'][0] + except IndexError: + # Create a new equivalent snapshot + eqv_snapshot = self.createEquivalentSnapshot() + + # When installing Business Snapshot, installation state should be changed + if eqv_snapshot not in [None, self]: + if site.portal_workflow.isTransitionPossible( + eqv_snapshot, 'install'): + eqv_snapshot.install() + + def getItemPathList(self): + return [l.getProperty('item_path') for l in self.objectValues()] + + def getBusinessTemplateV2List(self): + """ + Give the list of all Business Template V2(s) being touched by this Business + Commit + """ + template_list = [] + for item in self.objectValues(): + template_list.extend(item.getFollowUpValueList()) + + return list(set(template_list)) + + def getBusinessTemplateV2TitleList(self): + title_list = [l.getTitle() for l in self.getBusinessTemplateV2List()] + return title_list diff --git a/product/ERP5/Document/BusinessSnapshot.py b/product/ERP5/Document/BusinessSnapshot.py new file mode 100644 index 0000000000000000000000000000000000000000..7c709ec9482da31f076261cc7358991ad3da830e --- /dev/null +++ b/product/ERP5/Document/BusinessSnapshot.py @@ -0,0 +1,605 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SARL and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import gc +import os +import posixpath +import transaction +import imghdr +import tarfile +import time +import hashlib +import fnmatch +import re +import threading +import pprint + +from copy import deepcopy +from collections import defaultdict +from cStringIO import StringIO +from OFS.Image import Pdata +from lxml.etree import parse +from urllib import quote, unquote +from OFS import SimpleItem, XMLExportImport +from datetime import datetime +from itertools import chain +from operator import attrgetter +from persistent.list import PersistentList +from AccessControl import ClassSecurityInfo, Unauthorized, getSecurityManager +from Acquisition import Implicit, aq_base, aq_inner, aq_parent +from zLOG import LOG, INFO, WARNING + +from Products.ERP5Type.XMLObject import XMLObject +from Products.ERP5Type.Core.Folder import Folder +from Products.CMFCore.utils import getToolByName +from Products.PythonScripts.PythonScript import PythonScript +from Products.ERP5Type.dynamic.lazy_class import ERP5BaseBroken +from Products.ERP5Type.Globals import Persistent, PersistentMapping +from Products.ERP5Type import Permissions, PropertySheet, interfaces +from Products.ERP5Type.Globals import InitializeClass +from Products.ERP5Type.TransactionalVariable import getTransactionalVariable +from Products.ERP5Type.patches.ppml import importXML +from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter + + +class BusinessSnapshot(Folder): + """ + An installed/replaced snaphot should always be reduced, i.e, there can't be + more than one item on same path because it doesn't denote the state if there + is multiple on same path. + """ + + meta_type = 'ERP5 Business Snashot' + portal_type = 'Business Snapshot' + add_permission = Permissions.AddPortalContent + allowed_types = ('Business Item',) + + id_generator = '_generateUniversalUniqueId' + + # Declarative security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + template_format_version = 3 + + # Factory Type Information + factory_type_information = \ + { 'id' : portal_type + , 'meta_type' : meta_type + , 'icon' : 'file_icon.gif' + , 'product' : 'ERP5Type' + , 'factory' : '' + , 'type_class' : 'BusinessSnapshot' + , 'immediate_view' : 'BusinessSnapshot_view' + , 'allow_discussion' : 1 + , 'allowed_content_types': ('Business Item',) + , 'filter_content_types' : 1 + } + + # Declarative security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + # Declarative properties + property_sheets = ( + PropertySheet.Base, + PropertySheet.XMLObject, + PropertySheet.SimpleItem, + PropertySheet.CategoryCore, + PropertySheet.Version, + ) + + def getItemList(self): + """ + Returns the collection of all Business Item, Business Property Item and + Business Patch item at the given snapshot. + """ + return self.objectValues() + + def getItemPathList(self): + """ + Returns the path of all Business Item, Business Property Item and + Business Patch item at the given snapshot. + """ + return [l.getProperty('item_path') for l in self.getItemList()] + + def getBusinessItemByPath(self, path): + """ + Returns the Item given the path of item. Returns None if it doesn't exist + """ + item_list = self.getItemList() + try: + return [l for l in item_list if l.getProperty('item_path') == path][0] + except IndexError: + return + + def getLastSnapshot(self): + """ + Get last snapshot installed. + Returns None if there is no last snapshot. + """ + + portal = self.getPortalObject() + commit_tool = portal.portal_commits + + # XXX: Is it a good idea to be dependent on portal_catalog to get Snapshot list ? + snapshot_list = commit_tool.searchFolder( + portal_type='Business Snapshot', + validation_state='installed' + ) + + # There should never be more than 1 installed snapshot + if len(snapshot_list) == 1: + # Get the last installed snapshot + return snapshot_list[0].getObject() + + return None + + #def build(self, **kwargs): + # """ + # Using equivalent commit, create a snapshot of ZODB state + # """ + # new_item_list = [] + # new_item_path_list = [] + + # # Get the equivalent commit for the snapshot + # eqv_commit = self.getSimilarValue() + + # # Get last created snapshot + # last_snapshot = self.getLastSnapshot() + + # # Commit list of all commits between the last snapshot/first commit and the + # # current snapshot + # successor_commit_list = [] + + # # If there is last snapshot, then combine all the commit afterwards to create + # # new snapshot + # if last_snapshot: + + # for item in last_snapshot.objectValues(): + # if item.getFollowUpValue().getAvailabilityState() == 'installable': + # new_item_list.append(item) + # new_item_path_list.extend(item.getProperty('item_path')) + + # # Get next predecessor commit for this snapshot using the equivalent commit + # # Notice that we don't use the snapshot to get the next commit as the + # # snapshot is mere a state which uses `predecessor` just for mentioning the + # # equivalent commit. + # # Here the first next commit should be the commit created after last snapshot + # # which we can get using the equivalent commit of last snapshot and then + # # finding the next commit for it + # next_commit = last_snapshot.getSimilarValue().getPredecessorRelatedValue() + + # # If there is no last snapshot, create a new one by combining all the commits + # else: + # # Get the oldest commit and start from there to find the next commit + # oldest_commit = min( + # self.aq_parent.objectValues(portal_type='Business Commit'), + # key=(lambda x: x.getCreationDate())) + + # for item in oldest_commit.objectValues(): + # if item.getFollowUpValue().getAvailabilityState() == 'installable': + # new_item_list.append(item) + # new_item_path_list.extend(item.getProperty('item_path')) + + # next_commit = oldest_commit.getPredecessorRelatedValue() + + # # Fill sucessor commit list + # while (next_commit.getId() != eqv_commit.getId()): + # successor_commit_list.append(next_commit) + # next_commit = next_commit.getPredecessorRelatedValue() + + # # Append the equivalent commit to successor commits + # successor_commit_list.append(eqv_commit) + + # for commit in successor_commit_list: + # for item in commit.objectValues(): + # # Check if the item has a follow_up only with installable Business Template + # if item.getFollowUpValue().getAvailabilityState() == 'installable': + # item_path = item.getProperty('item_path') + # if item_path in new_item_path_list: + # # Replace the old item with same path with new item + # new_item_list = [l if l.getProperty('item_path') != item_path else item for l in new_item_list] + # else: + # # Add the item to list if there is no existing item at that path + # new_item_list.append(item) + # new_item_path_list.append(item_path) + + # # Create hardlinks for the objects + # for item in new_item_list: + # self._setObject(item.id, item, suppress_events=True) + + def preinstall(self): + """ + Compares the last installed snapshot, to be installed snapshot and the + state at ZODB, and then returns the modification list + + Steps: + 1. Get paths for items in old and new snapshot + 2. Create a temporary snapshot(called 'installation process') for items + which are going to be added, removed, modified + 3. Add the list of items which has been removed from last snaphshot in the + temporary snapshot while changing their item_sign to -1. + 4. For the items which are in both the snapshot, we have 2 process: + - No modification: Add new item to temporary snapshot directly + - Modification: Add old item to temporary snapshot + 5. Using installation process(items needed to be installed), + installed_snapshot and the items at ZODB, we decide what to install. + """ + modified_list = [] + zodb_modified_list = [] + + portal = self.getPortalObject() + portal_commits = portal.portal_commits + installed_snapshot = portal_commits.getInstalledSnapshot() + + # Create installation process, which have the changes to be made in the + # OFS during installation. Importantly, it should be a temp Business Snapshot + installation_process = portal_commits.newContent( + portal_type='Business Snapshot', + title='Installation Process', + temp_object=True, + ) + + if installed_snapshot not in (self, None): + + old_item_list = installed_snapshot.getItemList() + old_state_path_list = installed_snapshot.getItemPathList() + + new_item_list = self.getItemList() + new_state_path_list = self.getItemPathList() + + to_install_path_item_list = [] + + # Get the path which has been removed in new installation_state + removed_path_list = [path for path + in old_state_path_list + if path not in new_state_path_list] + + # Add the removed path with negative sign in the to_install_path_item_list + for path in removed_path_list: + old_item = installed_snapshot.getBusinessItemByPath(path) + # XXX: We can't change anything in the objects as they are just there + # for comparison and in reality they are hardlinks + #old_item = old_item._getCopy(installation_process) + installation_process._setObject(old_item.id, old_item, + suppress_events=True) + old_item.setProperty('item_sign', '-1') + + # Path Item List for installation_process should be the difference between + # old and new installation state + for item in self.objectValues(): + + old_item = installed_snapshot.getBusinessItemByPath(item.getProperty('item_path')) + self.updateHash(item) + + if old_item: + to_be_installed_item = item + # If the old_item exists, we match the hashes and if it differs, then + # add the new item + if old_item.getProperty('item_sha') != item.getProperty('item_sha'): + #to_be_installed_item = to_be_installed_item._getCopy(installation_process) + installation_process._setObject(to_be_installed_item.id, + to_be_installed_item, + suppress_events=True) + + else: + installation_process._setObject(item.id, item, + suppress_events=True) + + # If there is no snapshot installed, everything in new snapshot should be + # just compared to ZODB state. + else: + for item in self.objectValues(): + item = item._getCopy(installation_process) + installation_process._setObject(item.id, item, suppress_event=True) + + change_list = self.compareOldStateToOFS(installation_process, installed_snapshot) + + if change_list: + change_list = [(l[0].item_path, l[1]) for l in change_list] + + return change_list + + def compareOldStateToOFS(self, installation_process, installed_snapshot): + + # Get the paths about which we are concerned about + to_update_path_list = installation_process.getItemPathList() + portal = self.getPortalObject() + + # List to store what changes will be done to which path. Here we compare + # with all the states (old version, new version and state of object at ZODB) + change_list = [] + + to_update_path_list = self.sortPathList(to_update_path_list) + + for path in to_update_path_list: + try: + # Better to check for status of BusinessPatchItem separately as it + # can contain both BusinessItem as well as BusinessPropertyItem + new_item = installation_process.getBusinessItemByPath(path) + + if '#' in str(path): + isProperty = True + relative_url, property_id = path.split('#') + obj = portal.restrictedTraverse(relative_url) + property_value = obj.getProperty(property_id) + + # If the value at ZODB for the property is none, raise KeyError + # This is important to have compatibility between the way we check + # path as well as property. Otherwise, if we install a new property, + # we are always be getting an Error that there is change made at + # ZODB for this property + if not property_value: + raise KeyError + property_type = obj.getPropertyType(property_id) + obj = property_value + else: + isProperty = False + # XXX: Hardcoding because of problem with 'resource' trying to access + # the resource via acqusition. Should be removed completely before + # merging (DONT PUSH THIS) + if path == 'portal_categories/resource': + path_list = path.split('/') + container_path = path_list[:-1] + object_id = path_list[-1] + container = portal.restrictedTraverse(container_path) + obj = container._getOb(object_id) + else: + obj = portal.restrictedTraverse(path) + + obj_sha = self.calculateComparableHash(obj, isProperty) + + # Get item at old state + if not installed_snapshot: + old_item = None + else: + old_item = installed_snapshot.getBusinessItemByPath(path) + + # Check if there is an object at old state at this path + if old_item: + # Compare hash with ZODB + + if old_item.getProperty('item_sha') == obj_sha: + # No change at ZODB on old item, so get the new item + new_item = installation_process.getBusinessItemByPath(path) + # Compare new item hash with ZODB + + if new_item.getProperty('item_sha') == obj_sha: + if int(new_item.getProperty('item_sign')) == -1: + # If the sign is negative, remove the value from the path + change_list.append((new_item, 'Removing')) + else: + # If same hash, and +1 sign, do nothing + continue + + else: + # Install the new_item + change_list.append((new_item, 'Adding')) + + else: + # Change at ZODB, so get the new item + new_item = installation_process.getBusinessItemByPath(path) + # Compare new item hash with ZODB + + if new_item.getProperty('item_sha') == obj_sha: + # If same hash, do nothing + continue + + else: + # Trying to update change at ZODB + change_list.append((new_item, 'Updating')) + + else: + # Object created at ZODB by the user + # Compare with the new_item + + new_item = installation_process.getBusinessItemByPath(path) + if new_item.getProperty('item_sha') == obj_sha: + # If same hash, do nothing + continue + + else: + # Trying to update change at ZODB + change_list.append((new_item, 'Updating')) + + except (AttributeError, KeyError) as e: + # Get item at old state + if not installed_snapshot: + old_item = None + else: + old_item = installed_snapshot.getBusinessItemByPath(path) + + # Check if there is an object at old state at this path + if old_item: + # This means that the user had removed the object at this path + # Check what the sign is for the new_item + new_item = installation_process.getBusinessItemByPath(path) + # Check sign of new_item + + if int(new_item.getProperty('item_sign')) == 1: + # Object at ZODB has been removed by the user + change_list.append((new_item, 'Adding')) + + else: + # If there is no item at old state, install the new_item + new_item = installation_process.getBusinessItemByPath(path) + # XXX: Hack for not trying to install the sub-objects from zexp, + # This should rather be implemented while exporting the object, + # where we shouldn't export sub-objects in the zexp + if not isProperty: + try: + value = new_item.objectValues()[0] + except IndexError: + continue + # Installing a new item + change_list.append((new_item, 'Adding')) + + return change_list + + def updateHash(self, item): + """ + Function to update hash of Business Item or Business Property Item + """ + # Check for isProperty attribute + if item.isProperty: + value = item.getProperty('item_property_value') + else: + value_list = item.objectValues() + if value_list: + value = value_list[0] + else: + value = '' + + if value: + item.setProperty('item_sha', self.calculateComparableHash( + value, + item.isProperty, + )) + + def calculateComparableHash(self, object, isProperty=False): + """ + Remove some attributes before comparing hashses + and return hash of the comparable object dict, in case the object is + an erp5 object. + + Use shallow copy of the dict of the object at ZODB after removing + attributes which changes at small updation, like workflow_history, + uid, volatile attributes(which starts with _v) + + # XXX: Comparable hash shouldn't be used for BusinessPatchItem as whole. + We can compare the old_value and new_value, but there shouldn't be hash + for the Patch Item. + """ + if isProperty: + obj_dict = object + # Have compatibilty between tuples and list while comparing as we face + # this situation a lot especially for list type properties + if isinstance(obj_dict, list): + obj_dict = tuple(obj_dict) + else: + + klass = object.__class__ + classname = klass.__name__ + obj_dict = object.__dict__.copy() + + # If the dict is empty, do calculate hash of None as it stays same on + # one platform and in any case its impossiblt to move live python + # objects from one seeion to another + if not bool(obj_dict): + return hash(None) + + attr_set = {'_dav_writelocks', '_filepath', '_owner', '_related_index', + 'last_id', 'uid', '_mt_index', '_count', '_tree', + '__ac_local_roles__', '__ac_local_roles_group_id_dict__', + 'workflow_history', 'subject_set_uid_dict', 'security_uid_dict', + 'filter_dict', '_max_uid'} + + attr_set.update(('isIndexable',)) + + if classname in ('File', 'Image'): + attr_set.update(('_EtagSupport__etag', 'size')) + elif classname == 'Types Tool' and klass.__module__ == 'erp5.portal_type': + attr_set.add('type_provider_list') + + for attr in object.__dict__.keys(): + if attr in attr_set or attr.startswith('_cache_cookie_') or attr.startswith('_v'): + try: + del obj_dict[attr] + except AttributeError: + # XXX: Continue in cases where we want to delete some properties which + # are not in attribute list + # Raise an error + continue + + # Special case for configuration instance attributes + if attr in ['_config', '_config_metadata']: + import collections + # Order the dictionary so that comparison can be correct + obj_dict[attr] = collections.OrderedDict(sorted(obj_dict[attr].items())) + if 'valid_tags' in obj_dict[attr]: + try: + obj_dict[attr]['valid_tags'] = collections.OrderedDict(sorted(obj_dict[attr]['valid_tags'].items())) + except AttributeError: + # This can occur in case the valid_tag object is PersistentList + pass + + if 'data' in obj_dict: + try: + obj_dict['data'] = obj_dict.get('data').__dict__ + except AttributeError: + pass + + obj_sha = hash(pprint.pformat(obj_dict)) + return obj_sha + + def sortPathList(self, path_list): + """ + Custom sort for path_list according to the priorities of paths + """ + def comparePath(path): + split_path_list = path.split('/') + # Paths with property item should have the least priority as they should + # be installed after installing the object only + if '#' in path: + return 11 + if len(split_path_list) == 2 and split_path_list[0] in ('portal_types', 'portal_categories'): + return 1 + # portal_transforms objects needs portal_components installed first so + # as to register the modules + if len(split_path_list) == 2 and split_path_list[0] == 'portal_transforms': + return 12 + if len(split_path_list) > 2: + return 10 + if len(split_path_list) == 1: + return 2 + return 5 + + return sorted(path_list, key=comparePath) + + def install(self): + """ + Install the sub-objects in the commit + """ + site = self.getPortalObject() + + # While installing a new snapshot, last snapshot state should be + # changed to 'replaced' + last_snapshot = self.getLastSnapshot() + if last_snapshot not in (None, self): + if site.portal_workflow.isTransitionPossible( + last_snapshot, 'replace'): + last_snapshot.replace(self) + + # Now install the items in new snapshot, using the aq_parent of item as its + # context. This is important because if we use the snapshot as the context, + # it will change the parent of the items to snapshot, which is undesirable + # as we want them to stay as hardlinks in the snapshot + for item in self.objectValues(): + item.install(item.aq_parent) diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py index b7150c2be90163cd35a74fab9b76951a834fe98d..7e4331eefed45326dbc169d31923440c867fdc04 100644 --- a/product/ERP5/Document/BusinessTemplate.py +++ b/product/ERP5/Document/BusinessTemplate.py @@ -2531,8 +2531,13 @@ class PortalTypeWorkflowChainTemplateItem(BaseTemplateItem): force = kw.get('force') installed_bt = kw.get('installed_bt') if installed_bt is not None: - previous_portal_type_workflow_chain_list = list(installed_bt\ + try: + previous_portal_type_workflow_chain_list = list(installed_bt\ .getTemplatePortalTypeWorkflowChainList()) + except Exception: + # This will happen in case the `installed_bt` is Business Manager, so + # we won't need to goto the further installation process + return else: previous_portal_type_workflow_chain_list = [] # We now need to setup the list of workflows corresponding to @@ -4308,15 +4313,8 @@ class DocumentTemplateItem(FilesystemToZodbTemplateItem): """ if self._is_already_migrated(self._objects.keys()): ObjectTemplateItem.install(self, context, **kw) - # Reset component on the fly, because it is possible that those - # components are required in the middle of the transaction. For example: - # - A method in a component is called while installing. - # - A document component is used in a different business template, - # and those business templates are installed in a single transaction - # by upgrader. - # This reset is called at most 3 times in one business template - # installation. (for Document, Test, Extension) - self.portal_components.reset(force=True) + self.portal_components.reset(force=True, + reset_portal_type_at_transaction_boundary=True) else: FilesystemDocumentTemplateItem.install(self, context, **kw) @@ -5349,7 +5347,10 @@ Business Template is a set of definitions, such as skins, portal types and categ # always created a trash bin because we may to save object already present # but not in a previous business templates apart at creation of a new site if trash_tool is not None and (len(object_to_update) > 0 or len(self.portal_templates) > 2): - trashbin = trash_tool.newTrashBin(self.getTitle(), self) + if self.title == 'erp5_core': + trashbin = None + else: + trashbin = trash_tool.newTrashBin(self.getTitle(), self) else: trashbin = None @@ -5363,7 +5364,7 @@ Business Template is a set of definitions, such as skins, portal types and categ if update_catalog: catalog = _getCatalogValue(self) - if (catalog is None) or (not site.isIndexable): + if (catalog is None) or (not site.isIndexingRequired()): LOG('Business Template', 0, 'no SQL Catalog available') update_catalog = 0 else: diff --git a/product/ERP5/Document/BusinessTemplateV2.py b/product/ERP5/Document/BusinessTemplateV2.py new file mode 100644 index 0000000000000000000000000000000000000000..9a83eb50c4a11536c93750e692b74dfdd39dcb19 --- /dev/null +++ b/product/ERP5/Document/BusinessTemplateV2.py @@ -0,0 +1,1585 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SARL and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import gc +import os +import posixpath +import transaction +import imghdr +import tarfile +import time +import hashlib +import fnmatch +import re +import threading +import pprint +import json +import deepdiff + +from copy import deepcopy +from collections import defaultdict +from cStringIO import StringIO +from OFS.Image import Pdata +from lxml.etree import parse +from urllib import quote, unquote +from OFS import SimpleItem, XMLExportImport +from datetime import datetime +from itertools import chain +from operator import attrgetter +from persistent.list import PersistentList +from AccessControl import ClassSecurityInfo, Unauthorized, getSecurityManager +from Acquisition import Implicit, aq_base, aq_inner, aq_parent +from zLOG import LOG, INFO, WARNING + +from Products.ERP5Type.XMLObject import XMLObject +from Products.ERP5Type.Core.Folder import Folder +from Products.CMFCore.utils import getToolByName +from Products.PythonScripts.PythonScript import PythonScript +from Products.ERP5Type.dynamic.lazy_class import ERP5BaseBroken +from Products.ERP5Type.Globals import Persistent, PersistentMapping +from Products.ERP5Type import Permissions, PropertySheet, interfaces +from Products.ERP5Type.Globals import InitializeClass +from Products.ERP5Type.TransactionalVariable import getTransactionalVariable +from Products.ERP5Type.patches.ppml import importXML +from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter + +customImporters = { + XMLExportImport.magic: importXML, + } + +CACHE_DATABASE_PATH = None +try: + if int(os.getenv('ERP5_BT5_CACHE', 0)): + from App.config import getConfiguration + import gdbm + instancehome = getConfiguration().instancehome + CACHE_DATABASE_PATH = os.path.join(instancehome, 'bt5cache.db') +except TypeError: + pass +cache_database = threading.local() +_MARKER = [] + +SEPARATELY_EXPORTED_PROPERTY_DICT = { + # For objects whose class name is 'class_name', the 'property_name' + # attribute is removed from the XML export, and the value is exported in a + # separate file, with extension specified by 'extension'. + # 'extension' must be None for auto-detection. + # + # class_name: (extension, unicode_data, property_name), + "Document Component": ("py", 0, "text_content"), + "DTMLDocument": (None, 0, "raw"), + "DTMLMethod": (None, 0, "raw"), + "Extension Component": ("py", 0, "text_content"), + "File": (None, 0, "data"), + "Image": (None, 0, "data"), + "OOoTemplate": ("oot", 1, "_text"), + "PDF": ("pdf", 0, "data"), + "PDFForm": ("pdf", 0, "data"), + "Python Script": ("py", 0, "_body"), + "PythonScript": ("py", 0, "_body"), + "Spreadsheet": (None, 0, "data"), + "SQL": ("sql", 0, "src"), + "SQL Method": ("sql", 0, "src"), + "Test Component": ("py", 0, "text_content"), + "Test Page": (None, 0, "text_content"), + "Web Page": (None, 0, "text_content"), + "Web Script": (None, 0, "text_content"), + "Web Style": (None, 0, "text_content"), + "ZopePageTemplate": ("zpt", 1, "_text"), +} + + +def _delObjectWithoutHook(obj, id): + """OFS.ObjectManager._delObject without calling manage_beforeDelete.""" + ob = obj._getOb(id) + if obj._objects: + obj._objects = tuple([i for i in obj._objects if i['id'] != id]) + obj._delOb(id) + try: + ob._v__object_deleted__ = 1 + except: + pass + + +def _recursiveRemoveUid(obj): + """Recusivly set uid to None, to prevent (un)indexing. + This is used to prevent unindexing real objects when we delete subobjects on + a copy of this object. + """ + if getattr(aq_base(obj), 'uid', _MARKER) is not _MARKER: + obj.uid = None + # Make all objects and sub-object un-indexable + # XXX: Should be moved into another function or change the name and desc + # of this function + obj.isIndexable = ConstantGetter('isIndexable', value=False) + for subobj in obj.objectValues(): + _recursiveRemoveUid(subobj) + + +# New BusinessItem addition function +def manage_addBusinessItem(self, item_path='', *args, **kw): + # Create BusinessItem object container + c = BusinessItem(item_path) + + return c + + +# New BusinessPropertyItem addition function +def manage_addBusinessPropertyItem(self, item_path='', item_sign=1, item_layer=0, *args, **kw): + # Create BusinessPathItem object container + c = BusinessPropertyItem(item_path, item_sign, item_layer) + + return c + +# New BusinessPatchItem addition function +def manage_addBusinessPatchItem(self, item_path='', item_sign=1, item_layer=0, *args, **kw): + # Create BusinessPatchItem object container + c = BusinessPatchItem(item_path, item_sign, item_layer) + + return c + +class BusinessTemplateV2(XMLObject): + + """Business Template V2 is config for paths of all objects to be installed""" + + meta_type = 'ERP5 Business Template' + portal_type = 'Business Template V2' + add_permission = Permissions.AddPortalContent + + template_format_version = 3 + + # Factory Type Information + factory_type_information = \ + { 'id' : portal_type + , 'meta_type' : meta_type + , 'icon' : 'file_icon.gif' + , 'product' : 'ERP5Type' + , 'factory' : '' + , 'type_class' : 'BusinessTemplateV2' + , 'immediate_view' : 'BusinessTemplateV2_view' + , 'allow_discussion' : 1 + , 'filter_content_types' : 1 + } + + # Declarative security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + # Declarative properties + property_sheets = ( + PropertySheet.Base, + PropertySheet.XMLObject, + PropertySheet.SimpleItem, + PropertySheet.CategoryCore, + PropertySheet.Version, + PropertySheet.BusinessTemplateV2, + ) + + # XXX: This explicit setter and getter should be replaced using property + # sheet. + + def getShortRevision(self): + return None + + def getVersion(self): + # Override the getter because currently we don't migrate the version, and + # this is used to find missing dependency list + return '5.4.7' + + def install(self, **kw): + """ + Steps for installation of a Business Template: + - Get the last installed snapshot if it exists + - If not create a new snapshot with paths to be installed from the BT + - If there is snapshot installed, create a new snapshot with adding the paths + for this BT and then install the snapshot + """ + # Check if there is already a snapshot existing + portal = self.getPortalObject() + portal_commits = portal.portal_commits + snapshot_item_list = [] + + installed_snapshot = portal_commits.getInstalledSnapshot() + # If there is already an installed snapshot, add its objectValues to new + # to be installed snapshot + if installed_snapshot: + snapshot_item_list.extend(installed_snapshot.objectValues()) + + # Get the Business Items which are related to this Business Template + related_follow_up_item_list = self.getFollowUpRelatedValueList() + # Add these paths in to-be-installed-snapshot item list + snapshot_item_list.extend(related_follow_up_item_list) + + # Create a new snapshot and update it with item list and install it + snapshot = portal_commits.newContent(portal_type='Business Snapshot') + for item in snapshot_item_list: + snapshot._setObject(item.id, item, suppress_events=True) + snapshot.install() + + def changeBuildingStatetoModified(self): + """ + Change building_state to 'modified'. This is needed specifically as we want + to update the building state even if we change any sub-objects(Business Item + or Business Property Item) of Business Template V2. + """ + portal_workflow = self.getPortalObject().portal_workflow + wf = portal_workflow._getOb('business_template_v2_building_workflow') + + wf._executeMetaTransition(self, 'modified') + + def applytoERP5(self, DB): + """Apply the flattened/reduced Business Template V2 to the DB""" + portal = self.getPortalObject() + pass + + def _clean(self): + """ + Clean built information. + Remove all the built sub-objects from Business Item or Business Property + Item. + """ + for item in self.objectValues(): + if item.getPortalType() == 'Business Item': + # Delete the sub-object + id_list = [l for l in item.objectIds()] + if id_list: + item.manage_delObjects(ids=id_list) + elif item.getPortalType() == 'Business Property Item': + # Add empty property item_property_name, value and type + # XXX: Shouldn't we check if the properties exist and then just delete + # them ? + item.setProperty('item_property_name', '') + item.setProperty('item_property_value', '') + item.setProperty('item_property_type', '') + + security.declareProtected(Permissions.ManagePortal, 'preinstall') + def preinstall(self, check_dependencies=1, **kw): + """ + Preinstall for Business Template V2 comapres the installation state and returns + the changes in a manner which can keep up compatibilty with the view we use + in Business Template installation. + + This function calls `portal_templates.updateInstallationState` to get the + change_list. + + We don't care of check_dependencies here as this all would be taken care by + `udpateInstallationState` iteself. + """ + change_list = self.aq_parent.compareInstallationState([self]) + modified_object_list = {} + for path in change_list: + type_name = 'Business Item' + if '#' in path[0]: + type_name = 'Business Property Item' + modified_object_list[path[0]] = [path[1], type_name] + return modified_object_list + + security.declareProtected(Permissions.ManagePortal, 'clean') + clean = _clean + + def _setTitle(self, value): + """ + Override required due to bootstrap + """ + self.title = value + + def getPathItemList(self): + return self.objectValues() + + # XXX: Change into property + security.declareProtected(Permissions.ManagePortal, 'getTemplateFormatVersion') + def getTemplateFormatVersion(self): + return self.template_format_version + + # XXX: Change into property + def _setTemplateFormatVersion(self, value): + self.template_format_version = int(value) + + def propertyMap(self): + prop_map = super(BusinessTemplateV2, self).propertyMap() + final_prop_map = prop_map+self._properties + return final_prop_map + + def export(self, path=None, **kw): + """ + Export the object as zexp file + """ + if not self.getBuildingState() == 'built': + raise ValueError, 'Template not built properly' + f = StringIO() + + self._p_jar.exportFile(self._p_oid, f) + + # XXX: Improve naming + name = self.getTitle() + name = posixpath.join(path, name) + # XXX required due to overuse of os.path + name = name.replace('\\', '/').replace(':', '/') + name = quote(name + '.zexp') + obj_path = name.replace('/', os.sep) + + f.seek(0) + obj = f.read() + + object_path = os.path.join(path, obj_path) + path = os.path.dirname(object_path) + os.path.exists(path) or os.makedirs(path) + f = open(object_path, 'wb') + try: + f.write(obj) + finally: + f.close() + + security.declareProtected(Permissions.ManagePortal, 'importFile') + def importFile(self, path, connection=None): + """ + Import Business Template V2 object and all attribute to current BM itself + """ + if not connection: + connection = self.aq_parent._p_jar + file = open(path, 'rb') + imported_template_v2 = connection.importFile(file) + self.title = imported_template_v2.title + for obj in imported_template_v2.objectValues(): + delattr(obj, '__ac_local_roles__') + # XXX: Donot merge this, needed just for migrated erp5_core + try: + self._setObject(obj.id, aq_base(obj)) + except Exception: + pass + obj.isIndexable = ConstantGetter('isIndexable', value=False) + + def __add__(self, other): + """ + Adds the Business Item objects for the given Business Template V2 objects + """ + # XXX: Still to define + return self + + __radd__ = __add__ + + def __sub__(self, other): + """ + Override subtract to find difference b/w the values in different cases. + """ + # Create the sha list for all path item list available in current object + sha_list = [item.sha for item in self._path_item_list] + # Reverse the sign of Business Item objects for the old Business Template V2 + # Trying comparing/subtracting ZODB with old installed object + for path_item in other._path_item_list: + if path_item.sha in sha_list: + self._path_item_list = [item for item + in self._path_item_list + if item.sha != path_item.sha] + else: + path_item.sign = -1 + self._path_item_list.append(path_item) + + return self + + __rsub__ = __sub__ + + security.declareProtected(Permissions.ManagePortal, 'storeTemplateData') + def storeTemplateData(self, isBuild=False, **kw): + """ + Store data for objects in the ERP5. + Create Business Item sub-objects after resolving the paths. Also, add + layers to all Business Item objects + """ + portal = self.getPortalObject() + LOG('Business Template V2', INFO, 'Storing template Data') + + to_delete_id_list = [] + for item in self.objectValues(): + + # Only try to resolve the Business Item objects + if item.getPortalType() != 'Business Item': + continue + + item_path = item.getProperty('item_path') + # Resolve the path and update sub-objects lists + path_list = self._resolvePath(portal, [], item_path.split('/')) + + if len(path_list) == 1 and path_list[0] == item_path: + continue + else: + item_sign = item.getProperty('item_sign') + item_layer = item.getProperty('item_layer') + # Create new Business Item objects with path in path_list and sign and + # layer same as that of the path used for resolving to new paths. + for path in path_list: + path_item = self.newContent(portal_type='Business Item') + path_item.edit( + item_path=path, + item_sign=item_sign, + item_layer=item_layer + ) + # Add Id of BusinessItem to be deleted as we do already have resolved + # path and new sub-objects based on resolved paths + to_delete_id_list.append(item.getId()) + + # Now, delete the original Business Item(s) sub-object as we do have + # Business Item created from resolved paths + self.manage_delObjects(ids=to_delete_id_list) + + def _resolvePath(self, folder, relative_url_list, id_list): + """ + For Business Template V2, we expect to resolve the path incase we face + paths which expect to include sub-objects. + For example: 'portal_catalog/erp5_mysql_innodb/**' should only consider + the sub-objects of the object mentioned, and create separate BusinessItem + objects for all of them. + + This method calls itself recursively. + + The folder is the current object which contains sub-objects. + The list of ids are path components. If the list is empty, + the current folder is valid. + """ + if len(id_list) == 0: + return ['/'.join(relative_url_list)] + id = id_list[0] + if re.search('[\*\?\[\]]', id) is None: + # If the id has no meta character, do not have to check all objects. + obj = folder._getOb(id, None) + if obj is None: + raise AttributeError, "Could not resolve '%s' during business template processing." % id + return self._resolvePath(obj, relative_url_list + [id], id_list[1:]) + path_list = [] + for object_id in fnmatch.filter(folder.objectIds(), id): + if object_id != "": + path_list.extend(self._resolvePath( + folder._getOb(object_id), + relative_url_list + [object_id], id_list[1:])) + return path_list + + def getPathList(self): + path_list = [] + for item in self.objectValues(): + path_list.append(item.getProperty('item_path')) + return path_list + + def getPathItemDict(self): + path_item_dict = {} + # TODO: Handle error for BM with multiple items at same path + for item in self.objectValues(): + path_item_dict[item.getProperty('item_path')] = item + return path_item_dict + + def getBusinessItemByPath(self, path): + path_item_dict = self.getPathItemDict() + try: + return path_item_dict[path] + except KeyError: + return + + def build(self, no_action=False, **kw): + """Creates new values for business item from the values from + OFS Database""" + LOG('Business Template V2', INFO, 'Building Business Template V2') + removable_sub_object_path_list = kw.get('removable_sub_object_path', []) + removable_property_dict = kw.get('removable_property', {}) + # Now, we need to put a check here for returning whih objects should be + # updated during rebuild of BM + checkNeeded = kw.get('checkNeeded', False) + # Build all paths if there is no check required(i.e, its a new build action) + if not checkNeeded: + if not no_action: + self.storeTemplateData(isBuild=True, **kw) + for path_item in self.objectValues(): + kwargs = {} + item_path = path_item.getProperty('item_path') + kwargs['removable_property_list'] = removable_property_dict.get(item_path, []) + kwargs['remove_sub_objects'] = item_path in removable_sub_object_path_list + path_item.build(self, **kwargs) + return self + else: + item_path_list = kw.get('item_path_list', []) + if item_path_list: + for path in item_path_list: + item = self.getBusinessItemByPath(path) + item.build(self) + return self + + def flattenBusinessTemplateV2(self): + """ + Flattening a reduced Business Template V2 with two path p1 and p2 where p1 <> p2: + + flatten([(p1, s1, l1, v1), (p2, s2, l2, v2)]) = [(p1, s1, 0, v1), (p2, s2, 0, v2)] + A reduced Business Template V2 BT is said to be flattened if and only if: + flatten(BT) = BT + """ + pass + + def reduceBusinessTemplateV2(self): + """ + Reduction is a function that takes a Business Template V2 as input and returns + a smaller Business Template V2 by taking out values with lower priority layers. + + After taking out BusinessItem(s) with lower priority layer, we also go + through arithmetic in case there are multiple number of BI at the higher layer + + Two path on different layer are reduced as a single path with the highest layer: + + If l1 > l2, + reduce([(p, s, l1, (a, b, c)), (p, s, l2, (d, e))]) = [(p, s, l1, merge(a, b, c))] + + A Business Template V2 BT is said to be reduced if and only if: + reduce(BT) = BT + """ + path_list = self.getPathList() + + reduced_path_item_list = [] + + # We separate the path list in the ones which are repeated and the ones + # which are unique for the installation + seen_path_list = set() + unique_path_list = [x for x + in path_list + if x not in seen_path_list + and not seen_path_list.add(x)] + + # Create an extra dict for values on path which are repeated in the path list + seen_path_dict = {path: [] for path in seen_path_list} + + for item in self.objectValues(): + if item.getProperty('item_path') in seen_path_list: + # In case the path is repeated keep the path_item in a separate dict + # for further arithmetic + seen_path_dict[item.getProperty('item_path')].append(item) + else: + # If the path is unique, add them in the list of reduced Business Item + reduced_path_item_list.append(item) + + # Reduce the values and get the merged result out of it + for path, path_item_list in seen_path_dict.items(): + + # Create separate list of list items with highest priority + higest_priority_layer = max(path_item_list, key=attrgetter('item_layer')).item_layer + prioritized_path_item = [path_item for path_item + in path_item_list + if path_item.item_layer == higest_priority_layer] + + # Separate the positive and negative sign path_item + if len(prioritized_path_item) > 1: + path_item_list_add = [item for item + in prioritized_path_item + if item.getProperty('item_sign') > 0] + + path_item_list_subtract = [item for item + in prioritized_path_item + if item.getProperty('item_sign') < 0] + + if path_item_list_add: + + combined_added_path_item = reduce(lambda x, y: x+y, path_item_list_add) + if combined_added_path_item.getPortalType() == 'Business Item': + added_value = combined_added_path_item.objectValues()[0] + elif combined_added_path_item.getPortalType() == 'Business Property Item': + added_value = combined_added_path_item.getProperty('item_property_value') + + reduced_path_item_list.append(combined_added_path_item) + + if path_item_list_subtract: + + combined_subtracted_path_item = reduce(lambda x, y: x+y, path_item_list_subtract) + if combined_subtracted_path_item.getPortalType() == 'Business Item': + added_value = combined_subtracted_path_item.objectValues()[0] + elif combined_subtracted_path_item.getPortalType() == 'Business Property Item': + added_value = combined_subtracted_path_item.getProperty('item_property_value') + + reduced_path_item_list.append(combined_subtracted_path_item) + + # XXX: For now, we just care about added items and append them in reduced + # path list. + #if added_value != subtracted_value: + # Append the arithmetically combined path_item objects in the final + # reduced list after removing the intersection + # added_value, subtracted_value = \ + # self._simplifyValueIntersection(added_value, subtracted_value) + + # combined_added_path_item.value = added_value + # combined_subtracted_path_item.value = subtracted_value + + # Append the path_item to the final reduced path_item_list after + # doing required arithmetic on it. Make sure to first append + # subtracted item because while installation, we need to first + # uninstall the old object and then install new object at same path + # reduced_path_item_list.append(combined_subtracted_path_item) + # reduced_path_item_list.append(combined_added_path_item) + + else: + reduced_path_item_list.append(prioritized_path_item[0]) + + id_list = [l for l in self.objectIds()] + for l in id_list: + try: + self._delObject(l) + except Exception: + # XXX: REMOVE/RECHEK BEFORE MERGE + # The reason for doing this horrible workaround is to delete object + # for 'portal_memcached/persistent_memcached_plugin' as it is not getting + # deleted in 1st attempt with failure : + # AttributeError: 'NoneType' object has no attribute 'getUid' + self._delObject(l) + + for item in reduced_path_item_list: + item.isIndexable = ConstantGetter('isIndexable', value=False) + new_id = self.generateNewId() + self._setObject(new_id, aq_base(item), + suppress_events=True) + + def _simplifyValueIntersection(self, added_value, subtracted_value): + """ + Returns values for the Business Item having same path and layer after + removing the intersection of the values + + Parameters: + added_value - Value for the Business Item having sign = +1 + subtracted_value - Value for Busienss Item having sign = -1 + """ + built_in_number_type = (int, long, float, complex) + built_in_container_type = (tuple, list, dict, set) + built_in_type_list = built_in_number_type + built_in_container_type + + # For ERP5 objects, we should return the added and subtracted values as it is + if type(added_value).__name__ not in built_in_type_list and \ + type(subtracted_value).__name__ not in built_in_type_list: + return added_value, subtracted_value + + # For all the values of container type, we remove the intersection + added_value = [x for x in added_value if x not in subtracted_value] + subtracted_value = [x for x in subtracted_value if x not in added_value] + + return added_value, subtracted_value + + def mergeBusinessPatchItem(self, item1, item2): + """ + Merge two BusinessPatchItem at same layer and same sign. + + XXX: This function shouldn't be used at reduction, rather than during + updating the installation_state, because we need to know all the states to + be able to find out which patch needs to be used. + + Cases: + 1. Shouldn't matter if both have same new_value as we give preference to + the final result and try to remove conflict as much as possible. + 2. If both have different old_value and different new_value, merge should + return both of them and let the updateInstallationState process decide + which one to apply and if needed, raise a conflict + """ + pass + +class BusinessItem(XMLObject): + + """Saves the path and values for objects, properties, etc, the + attributes for a path configuration being: + + - item_path (similar to an xpath expression) + Examples of path : + portal_type/Person + portal_type/Person#title + portal_type/Person#property_sheet?ancestor=DublinCore + portal_type/Person#property_sheet?position=2 + - item_sign (+1/-1) + - item_layer (0, 1, 2, 3, etc.) + - item_value (a set of pickable value in python)""" + + add_permission = Permissions.AddPortalContent + # Declarative security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + constructors = (manage_addBusinessItem,) + portal_type = 'Business Item' + meta_type = 'Business Item' + icon = None + isProperty = False + + id_generator = '_generateUniversalUniqueId' + + def getZODBDiff(self): + """ + Compare the diff of object with ZODB state of the same object + """ + portal = self.getPortalObject() + obj = portal.restrictedTraverse(self.getProperty('item_path')) + context = self + obj = obj._getCopy(context) + obj = self.removeProperties(obj, True) + + item = self.objectValues()[0] + item = item._getCopy(context) + item = self.removeProperties(item, True) + + diff = deepdiff.DeepDiff(item.__dict__, obj.__dict__) + tree_diff = deepdiff.DeepDiff(item.__dict__, obj.__dict__, view='tree') + diff_tree_list = [] + + # Flatten the list of DiffValues + for subset in tree_diff.values(): + if isinstance(subset, set): + sublist = list(subset) + for item in sublist: + diff_tree_list.append(item) + + diff_list = [] + for val in diff_tree_list: + new_val = {} + new_val['diff'] = val.additional.get('diff', None) + new_val['t1'] = val.t1 + new_val['t2'] = val.t2 + new_val['path'] = val.path()[6:-2] + diff_list.append(new_val) + + return json.dumps(diff_list) + + def updateFollowUpPathList(self): + """ + Update the path list for Follow Up Business Template V2 + """ + template = self.getFollowUpValue() + # Check if the template has already been set or not + if template: + # Copy the path list for Business Template V2 and update it with new path + item_path_list = template.getItemPathList()[:] + old_item_path = self._v_modified_property_dict.get('item_path') + if old_item_path and item_path_list: + if old_item_path in item_path_list: + for idx, item in enumerate(item_path_list): + if item == old_item_path: + item_path_list[idx] = self.getProperty('item_path') + else: + item_path_list.append(self.getProperty('item_path')) + else: + # If there is no old_item_path or if path_list is empty, we can just + # append the new_path in path_list + item_path_list.append(self.getProperty('item_path')) + + # Update the template with new path list + template.setItemPathList(item_path_list) + + else: + # Complain loudly if the follow_up is not there + raise ValueError('Follow Up Business Template V2 is not set or defined yet') + + #def build(self, context, **kw): + # """ + # Extract value for the given path from the OFS + + # Three different situations to extract value: + # 1. For paths which point directly to an object in OFS + # 2. For paths which point to multiple objects inside a folder + # 3. For paths which point to property of an object in OFS : In this case, + # we can have URL delimiters like ?, #, = in the path + # """ + # LOG('Business Template V2', INFO, 'Building Business Item') + + # # Remove the old sub-objects if exisiting before building + # id_list = [l for l in self.objectIds()] + # if id_list: + # self.manage_delObjects(ids=id_list) + + # p = context.getPortalObject() + # path = self.getProperty('item_path') + # obj = p.unrestrictedTraverse(path) + # obj = obj._getCopy(context) + + # # We should remove the extra properties of object so that there + # # shouldn't be redundancy of the proeprties + # removable_property_list = kw.get('removable_property_list', []) + + # # We should also add extra parameter to remove sub-objects by removing + # # `_tree` for any erp5 object. This way we can have control over adding + # # sub-objects as new Business Item objects + # remove_sub_objects = kw.get('remove_sub_objects', False) + # if remove_sub_objects: + # removable_property_list.append('_tree') + # keep_workflow_history = False + # # For portal_components object, we need validation_history + # if self.getProperty('item_path').startswith('portal_components'): + # keep_workflow_history = True + # obj = self.removeProperties(obj, + # 1, + # properties=removable_property_list, + # keep_workflow_history=keep_workflow_history, + # ) + # obj = obj.__of__(context) + # # XXX: '_recursiveRemoveUid' is not working as expected + # _recursiveRemoveUid(obj) + # obj = aq_base(obj) + # obj.isIndexable = ConstantGetter('isIndexable', value=False) + # # In general, one Business Item only has one object in it, so we never end + # # up in conflict as we'll always be having its unique path(due to GUID of + # # Business Item), thus we can just use object Id as it is while making it + # # a sub-object of Business Item + # self._setObject(obj.id, obj, suppress_events=True) + + def _resolvePath(self, folder, relative_url_list, id_list): + """ + We go through 3 types of paths: + + 1. General path we find in erp5 for objects + Ex: portal_type/Person + In this case, we import/export the object on the path + + 2. Path where we consider saving sub-objects also, in that case we create + new BusinessItem for those objects + Ex: portal_catalog/erp5_mysql_innodb/** + This should create BI for the catalog methods sub-objects present in the + erp5_catalog. + + This method calls itself recursively. + + The folder is the current object which contains sub-objects. + The list of ids are path components. If the list is empty, + the current folder is valid. + """ + if len(id_list) == 0: + return ['/'.join(relative_url_list)] + id = id_list[0] + if re.search('[\*\?\[\]]', id) is None: + # If the id has no meta character, do not have to check all objects. + obj = folder._getOb(id, None) + if obj is None: + raise AttributeError, "Could not resolve '%s' during BusinessItem processing." % id + return self._resolvePath(obj, relative_url_list + [id], id_list[1:]) + path_list = [] + for object_id in fnmatch.filter(folder.objectIds(), id): + if object_id != "": + path_list.extend(self._resolvePath( + folder._getOb(object_id), + relative_url_list + [object_id], id_list[1:])) + return path_list + + def install(self, context, *args): + """ + Set the value to the defined path. + """ + # In case the path denotes property, we create separate object for + # ObjectTemplateItem and handle the installation there. + try: + portal = context.getPortalObject() + except AttributeError: + # This is a possibility during bootstrap where the context is not an + # erp5 object but a dynamic class + if args: + portal = args[0] + else: + raise AttributeError('No portal object found') + + path = self.getProperty('item_path') + path_list = path.split('/') + container_path = path_list[:-1] + object_id = path_list[-1] + try: + container = self.unrestrictedResolveValue(portal, container_path) + except KeyError: + # parent object can be set to nothing, in this case just go on + container_url = '/'.join(container_path) + old_obj = container._getOb(object_id, None) + # delete the old object before installing a new object + if old_obj: + container._delObject(object_id) + # Create a new object only if sign is +1 + # If sign is +1, set the new object on the container + if int(self.getProperty('item_sign')) == 1: + # install object + obj = self.objectValues()[0] + obj = obj._getCopy(container) + + # Update the type_provider_list if needed + # XXX: Find a way to fiter and do this check only for tool, so that we + # don't lose on perfomance in checking this everytime + if interfaces.ITypeProvider.providedBy(obj): + type_container_id = obj.id + types_tool = portal.portal_types + if type_container_id not in types_tool.type_provider_list: + types_tool.type_provider_list = tuple(types_tool.type_provider_list) + \ + (type_container_id,) + + # Before making `obj` a sub-object of `container`, we should the acquired + # roles on obj + obj.isIndexable = ConstantGetter('isIndexable', value=False) + delattr(obj, '__ac_local_roles__') + container._setObject(object_id, obj, suppress_events=True) + obj = container._getOb(object_id) + skin_tool = portal.portal_skins + if obj.aq_parent.meta_type == 'CMF Skins Tool': + registerSkinFolder(skin_tool, obj) + + def unrestrictedResolveValue(self, context=None, path='', default=_MARKER, + restricted=0): + """ + Get the value without checking the security. + This method does not acquire the parent. + """ + if isinstance(path, basestring): + stack = path.split('/') + else: + stack = list(path) + stack.reverse() + if stack: + if context is None: + portal = aq_inner(self.getPortalObject()) + container = portal + else: + container = context + + if restricted: + validate = getSecurityManager().validate + + while stack: + key = stack.pop() + try: + value = container[key] + except KeyError: + LOG('BusinessTemplateV2', WARNING, + 'Could not access object %s' % (path,)) + if default is _MARKER: + raise + return default + + if restricted: + try: + if not validate(container, container, key, value): + raise Unauthorized('unauthorized access to element %s' % key) + except Unauthorized: + LOG('BusinessTemplateV2', WARNING, + 'access to %s is forbidden' % (path,)) + if default is _MARKER: + raise + return default + + container = value + + return value + else: + return context + + def __add__(self, other): + """ + Add the values from the path when the path is same for 2 objects + """ + if self.getProperty('item_path') != other.getProperty('item_path'): + raise ValueError, "BusinessItem are incommensurable, have different path" + elif self.getProperty('item_sign') != other.getProperty('item_sign'): + raise ValueError, "BusinessItem are incommensurable, have different sign" + else: + new_value = self._mergeValue(value_list=[self.objectValues()[0], other.objectValues()[0]]) + # Remove old objects if it exists + old_id_list = [l for l in self.objectIds()] + if old_id_list: + self.manage_delObjects(ids=old_id_list) + # Add the new sub-object + self._setObject(new_value.id, new_value) + return self + + __radd__ = __add__ + + def _mergeValue(self, value_list): + """ + Merge value in value list + + merge(a, b, c) : A monotonic commutative function that depends on the + type of a, b and c: + + if a, b and c are sets, merge = union + if a, b and c are lists, merge = ordered concatenation + if a, b and c are objects, merge = the object created the last + else merge = MAX + """ + builtin_number_type = (int, long, float, complex) + + # Now, consider the type of both values + if all(isinstance(x, builtin_number_type) for x in value_list): + merged_value = max(value_list) + elif all(isinstance(x, set) for x in value_list): + merged_value = set(chain.from_iterable(value_list)) + elif all(isinstance(x, list) for x in value_list): + merged_value = list(set(chain.from_iterable(value_list))) + elif all(isinstance(x, tuple) for x in value_list): + merged_value = tuple(set(chain.from_iterable(value_list))) + else: + # In all other case, check if the values are objects and then take the + # objects created last. + + # XXX: Should we go with creation date or modification_date ?? + # TODO: + # 1. Add check that the values are ERP5 objects + # 2. In case 2 maximum values are created at same time, prefer one with + # higher priority layer + merged_value = max([max(value, key=attrgetter('creation_date')) + for value in value_list], + key=attrgetter('creation_date')) + + return merged_value + + def removeProperties(self, + obj, + export, + properties=[], + keep_workflow_history=False, + keep_workflow_history_last_history_only=False): + """ + Remove unneeded properties for export + """ + obj._p_activate() + klass = obj.__class__ + classname = klass.__name__ + attr_set = {'_dav_writelocks', '_filepath', '_owner', '_related_index', + 'last_id', 'uid', '_mt_index', '_count', '_tree', + '__ac_local_roles__', '__ac_local_roles_group_id_dict__', + 'workflow_history', 'subject_set_uid_dict', 'security_uid_dict', + 'filter_dict', '_max_uid', 'isIndexable',} + if properties: + for prop in properties: + if prop.endswith('_list'): + prop = prop[:-5] + attr_set.add(prop) + if export: + if keep_workflow_history_last_history_only: + self._removeAllButLastWorkflowHistory(obj) + elif not keep_workflow_history: + attr_set.add('workflow_history') + # PythonScript covers both Zope Python scripts + # and ERP5 Python Scripts + if isinstance(obj, PythonScript): + attr_set.update(('func_code', 'func_defaults', '_code', + '_lazy_compilation', 'Python_magic')) + for attr in 'errors', 'warnings', '_proxy_roles': + if not obj.__dict__.get(attr, 1): + delattr(obj, attr) + elif classname in ('File', 'Image'): + attr_set.update(('_EtagSupport__etag', 'size')) + elif classname == 'SQL' and klass.__module__ == 'Products.ZSQLMethods.SQL': + attr_set.update(('_arg', 'template')) + elif interfaces.IIdGenerator.providedBy(obj): + attr_set.update(('last_max_id_dict', 'last_id_dict')) + elif classname == 'Types Tool' and klass.__module__ == 'erp5.portal_type': + attr_set.add('type_provider_list') + + for attr in obj.__dict__.keys(): + if attr in attr_set or attr.startswith('_cache_cookie_') or attr.startswith('_v'): + try: + delattr(obj, attr) + except AttributeError: + # XXX: Continue in cases where we want to delete some properties which + # are not in attribute list + # Raise an error + continue + + if classname == 'PDFForm': + if not obj.getProperty('business_template_include_content', 1): + obj.deletePdfContent() + return obj + + def getBusinessPath(self): + return self.getProperty('item_path') + + #def getParentBusinessTemplateV2(self): + # return self.aq_parent + +class BusinessPropertyItem(XMLObject): + + """Class to deal with path(s) which refer to property of an ERP5 object. + Used to store property name, type and value for a given object and property""" + + add_permission = Permissions.AddPortalContent + # Declarative security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + portal_type = 'Business Property Item' + meta_type = 'Business Property Item' + icon = None + isIndexable = False + isProperty = True + constructors = (manage_addBusinessPropertyItem,) + + def _edit(self, item_path='', item_sign=1, item_layer=0, *args, **kw): + """ + Overriden function so that we can update attributes for BusinessItem objects + """ + + edited = super(BusinessPropertyItem, self)._edit(item_path=item_path, + item_sign=item_sign, + item_layer=item_layer, + **kw) + + # Build the object here, if the item_path has been added/updated + # XXX: We also need to add attribute to ensure that this doesn't happen + # while in tests or while creating them on the fly + if 'item_path' in self._v_modified_property_dict: + self.build(self.aq_parent) + + return edited + + def build(self, context, **kw): + p = context.getPortalObject() + path = self.getProperty('item_path') + relative_url, property_id = path.split('#') + obj = p.unrestrictedTraverse(relative_url) + property_value = obj.getProperty(property_id) + property_type = obj.getPropertyType(property_id) + self.setProperty('item_property_name', property_id) + self.setProperty('item_property_type', property_type) + self.setProperty('item_property_value', property_value) + + def updateFollowUpPathList(self): + """ + Update the path list for Follow Up Business Template V2 + """ + template = self.getFollowUpValue() + # Check if the template has already been set or not + if template: + # Copy the path list for Business Template V2 and update it with new path + item_path_list = template.getItemPathList()[:] + old_item_path = self._v_modified_property_dict.get('item_path') + if old_item_path and item_path_list: + if old_item_path in item_path_list: + for idx, item in enumerate(item_path_list): + if item == old_item_path: + item_path_list[idx] = self.getProperty('item_path') + else: + item_path_list.append(self.getProperty('item_path')) + else: + # If there is no old_item_path or if path_list is empty, we can just + # append the new_path in path_list + item_path_list.append(self.getProperty('item_path')) + + # Update the template with new path list + template.setItemPathList(item_path_list) + + else: + # Complain loudly if the follow_up is not there + raise ValueError('Follow Up Business Template V2 is not set or defined yet') + + def install(self, context, *args): + # Get portal object + try: + portal = context.getPortalObject() + except AttributeError: + # This is a possibility during bootstrap where the context is not an + # erp5 object but a dynamic class + if args: + portal = args[0] + else: + raise AttributeError('No portal object found') + + path = self.getProperty('item_path') + relative_url, property_id = path.split('#') + obj = portal.unrestrictedTraverse(relative_url) + property_name = self.getProperty('item_property_name') + property_type = self.getProperty('item_property_type') + property_value = self.getProperty('item_property_value') + # First remove the property from the existing path and keep the default + # empty, and update only if the sign is +1 + obj._delPropValue(property_name) + # Remove the '_list' from the end of property_name. This is required because + # of the way _setProperty is defined where if the type is list_type, it + # explicitly adds '_list' at the end of property_name before trying to call + # the accessor + if property_name.endswith('_list'): + property_name = property_name[:-5] + + # XXX: Explicit addition of property_type for 'type_workflow' property on + # 'ERP5Type' objects. This is required as we have created an explicit + # property outside of property sheet for ERP5Type objects, but at the same + # time, the object(s) also have property sheet for them. Since, there is no + # functions like _setProperty, hasProperty, etc to combine both of them + # we have to end up using explicit mention of 'list' property_value here + # 1. Other option can be to override hasProperty or _setProperty for ERP5Type + # object and write it so that it can handle both _properties attribute as + # well as accessor holders generated from property sheet(s). + # 2. After that we can use hasProperty here for objects to check their + # property_type and then just use the generic '_setProperty' function. + # XXX: For now, we just put this explicitly/hard-code + if property_name == 'type_workflow': + property_type = 'multiple selection' + + if int(self.getProperty('item_sign')) == 1: + obj._setProperty(property_name, property_value, property_type) + + def getBusinessPath(self): + return self.getProperty('item_path') + + def getBusinessPathSign(self): + return self.getProperty('item_sign', 1) + + def getBusinessPathLayer(self): + return self.getProperty('item_layer', 1) + + def getParentBusinessTemplateV2(self): + return self.aq_parent + + def getBusinessItemPropertyName(self): + return self.getProperty('item_property_name') + + def getBusinessItemPropertyType(self): + return self.getProperty('item_property_type') + + def getBusinessItemPropertyValue(self): + return self.getProperty('item_property_value') + + def __add__(self, other): + """ + Add the values from the path when the path is same for 2 objects + """ + if self.getProperty('item_path') != other.getProperty('item_path'): + raise ValueError, "BusinessItem are incommensurable, have different path" + elif self.getProperty('item_sign') != other.getProperty('item_sign'): + raise ValueError, "BusinessItem are incommensurable, have different sign" + else: + self.setProperty('item_property_value', self._mergeValue(value_list=[ + self.getProperty('item_property_value'), + other.getProperty('item_property_value')] + )) + return self + + __radd__ = __add__ + + def _mergeValue(self, value_list): + """ + Merge value in value list + + merge(a, b, c) : A monotonic commutative function that depends on the + type of a, b and c: + + if a, b and c are sets, merge = union + if a, b and c are lists, merge = ordered concatenation + if a, b and c are objects, merge = the object created the last + else merge = MAX + """ + builtin_number_type = (int, long, float, complex) + + # Now, consider the type of both values + if all(isinstance(x, builtin_number_type) for x in value_list): + merged_value = max(value_list) + elif all(isinstance(x, set) for x in value_list): + merged_value = set(chain.from_iterable(value_list)) + elif all(isinstance(x, list) for x in value_list): + merged_value = list(set(chain.from_iterable(value_list))) + elif all(isinstance(x, tuple) for x in value_list): + merged_value = tuple(set(chain.from_iterable(value_list))) + else: + # In all other case, check if the values are objects and then take the + # objects created last. + + # XXX: Should we go with creation date or modification_date ?? + # TODO: + # 1. Add check that the values are ERP5 objects + # 2. In case 2 maximum values are created at same time, prefer one with + # higher priority layer + merged_value = max([max(value, key=attrgetter('creation_date')) + for value in value_list], + key=attrgetter('creation_date')) + + return merged_value + +class BusinessPatchItem(XMLObject): + + """ + Business Item for saving patch and diff. This will help us to create a diff or + patch between the old value and current value. + + item_sign -- +1 or -1 + item_path -- extended OFS path (equivalent to deepdiff path) + ex. a/b/c#x/y/z:int/w + item_layer -- layer + old -- old value + new -- new value + dependency_list -- a list of bt5 identifiers useful to rebuild the + BusinesTemplatePatchItem instance + preserved_list -- a list of bt5 identifiers useful to rebuild the + BusinesTemplatePatchItem instance + (XXX: We don't use `preserved_list` for now) + + Business Patch Item can be both PathItem or PropertyItem, but both of them are + quite distinguishable, so we prefer not to use them as base class for it. + """ + # CMF Type definition + portal_type = 'Business Patch Item' + meta_type = 'Business Patch Item' + + # Declarative security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + icon = None + isIndexable = False + isProperty = False + constructors = (manage_addBusinessPatchItem,) + allowed_types = ('Business Item', 'Business Property Item',) + + def _edit(self, **kw): + """ + Override _edit to create Business Item and BusinessPropertyItem for old and + new value + """ + dependency_list = kw.get('dependency_list', self.getProperty('dependency_list')) + + # Raise error if no dependency_list, this way we ensure there are no useless + # patch_item objects + if not dependency_list: + raise ValueError('Please add dependency to the Business Patch Item') + + super(BusinessPatchItem, self)._edit(**kw) + + def build(self, context, **kw): + """ + Build should update the old and new value + """ + portal = self.getPortalObject() + portal_templates = portal.portal_templates + + item_path = self.getProperty('item_path') + item_layer = self.getProperty('item_layer') + item_sign = self.getProperty('item_sign') + + # Remove old objects if it exists + old_id_list = [l for l in self.objectIds()] + if old_id_list: + self.manage_delObjects(ids=old_id_list) + + # Get the dependency Business Template V2 + dependency_list = self.getProperty('dependency_list') + if dependency_list: + dependency_title = dependency_list[0] + dependency_bm = portal_templates.getInstalledBusinessTemplateV2(dependency_title) + if not dependency_bm: + raise ValueError('Missing Installed Business Template V2 for dependecy_list \ + which is required to build') + + # Use item_path to determine if we need to create Business Item or + # Business Property Item for storing old and new values + if '#' in item_path: + # Create new_prop_item and build it from ZODB + new_item = self.newContent(portal_type='Business Property Item', + item_path=item_path, + item_layer=item_layer, + item_sign=item_sign, + id='new_item') + new_item.build(self) + + else: + # Create new_item and build it from ZODB + new_item = self.newContent(portal_type='Business Item', + item_path=item_path, + item_layer=item_layer, + item_sign=item_sign, + id='new_item') + new_item.build(self) + + updated_id = 'old_item' + # Copy old item/property item from the item at similar path in dependency_bm + dependency_item = dependency_bm.getBusinessItemByPath(item_path) + + # Raise if there is no item exisiting in dependency Business Template V2 + if not dependency_item: + + raise ValueError('No %s exist at path %s in installed version of %s' + % ( new_item.getPortalType(), + item_path, + dependency_title,)) + + cp_data = dependency_bm.manage_copyObjects([dependency_item.getId()]) + new_id = self.manage_pasteObjects(cp_data)[0]['new_id'] + self.manage_renameObject(id=new_id, new_id=updated_id) + + # Get the copied object and update the properties + old_item = self._getOb(updated_id) + old_item.setProperty('item_layer', item_layer) + old_item.setProperty('item_sign', item_sign) + + # Commit the transaction + transaction.commit() + + def getOldValue(self): + """ + Returns old value for the BusinessPatchItem + """ + old_item = self._getOb('old_item')[0] + if old_item.getPortalType() == 'Business Item': + return old_item.objectValues() + else: + return old_item.getProperty('item_property_value') + + def getNewValue(self, build=False): + """ + Returns new value for the given BusinessPatchItem + """ + old_item = self._getOb('new_item') + if old_item.getPortalType() == 'Business Item': + return old_item.objectValues()[0] + else: + return old_item.getProperty('item_property_value') + + def getDiff(self, patch_format='deepdiff'): + """ + Use diff tool to find the diff between two values + + XXX: For now we display the json format of the patched diff + """ + patch = self.getPatchObject(patch_format) + if patch_format == 'deepdiff': + return patch.asDeepDiffPatch().json + else: + # For json-patch object + return patch.asJSONPatch().to_string() + + def getPatchObject(self, patch_format='deepdiff'): + portal = self.getPortalObject() + diff_tool = portal.portal_diff + + old_item = self._getOb('old_item') + new_item = self._getOb('new_item') + + if (old_item.getPortalType() == new_item.getPortalType() == 'Business Item'): + old = old_item.objectValues()[0] + new = new_item.objectValues()[0] + else: + old = old_item.getProperty('item_property_value') + new = new_item.getProperty('item_property_value') + patch = diff_tool.diffPortalObject(old=old, + new=new, + patch_format=patch_format + ) + return patch + + def install(self, context, *args): + """ + Install will call the apply function which puts the new value at the + path mentioned while checking if the old value exists. + """ + # Installation is basically running installation on the new_value + self.new_value.install(context) + + def applyPatch(self): + """ + Apply the new value by removing the old value. Also, show conflict in case + the value at old_installation_state is not same as the old value. + """ + pass + +def registerSkinFolder(skin_tool, skin_folder): + request = skin_tool.REQUEST + # XXX: Getting parameter from request instead of dialog is bad + # XXX: This is even non consistent with rest of parameters selected by user + # (like update_translation or update_catalog) + register_skin_selection = request.get('your_register_skin_selection', 1) + reorder_skin_selection = request.get('your_reorder_skin_selection', 1) + skin_layer_list = request.get('your_skin_layer_list', + skin_tool.getSkinSelections()) + + skin_folder_id = skin_folder.getId() + + try: + skin_selection_list = skin_folder.getProperty( + 'business_template_registered_skin_selections', + skin_tool.getSkinSelections() + ) + except AttributeError: + skin_selection_list = skin_tool.getSkinSelections() + + if isinstance(skin_selection_list, basestring): + skin_selection_list = skin_selection_list.split() + + def skin_sort_key(skin_folder_id): + obj = skin_tool._getOb(skin_folder_id, None) + if obj is None: + return 0, skin_folder_id + return -obj.getProperty('business_template_skin_layer_priority', + obj.meta_type == 'Filesystem Directory View' and -1 or 0), skin_folder_id + + for skin_name in skin_selection_list: + + if (skin_name not in skin_tool.getSkinSelections()) and \ + register_skin_selection: + createSkinSelection(skin_tool, skin_name) + # add newly created skins to list of skins we care for + skin_layer_list.append(skin_name) + + selection = skin_tool.getSkinPath(skin_name) or '' + selection_list = selection.split(',') + if (skin_folder_id not in selection_list): + selection_list.insert(0, skin_folder_id) + if reorder_skin_selection: + # Sort by skin priority and ID + selection_list.sort(key=skin_sort_key) + if (skin_name in skin_layer_list): + skin_tool.manage_skinLayers(skinpath=selection_list, + skinname=skin_name, add_skin=1) + skin_tool.getPortalObject().changeSkin(None) + +def createSkinSelection(skin_tool, skin_name): + # This skin selection does not exist, so we create a new one. + # We'll initialize it with all skin folders, unless: + # - they explictly define a list of + # "business_template_registered_skin_selections", and we + # are not in this list. + # - they are not registered in the default skin selection + skin_path = '' + for skin_folder in skin_tool.objectValues(): + if skin_name in skin_folder.getProperty( + 'business_template_registered_skin_selections', + (skin_name, )): + if skin_folder.getId() in \ + skin_tool.getSkinPath(skin_tool.getDefaultSkin()): + if skin_path: + skin_path = '%s,%s' % (skin_path, skin_folder.getId()) + else: + skin_path= skin_folder.getId() + # add newly created skins to list of skins we care for + skin_tool.addSkinSelection(skin_name, skin_path) + skin_tool.getPortalObject().changeSkin(None) + +def deleteSkinSelection(skin_tool, skin_name): + # Do not delete default skin + if skin_tool.getDefaultSkin() != skin_name: + for skin_folder in skin_tool.objectValues(): + try: + if skin_name in skin_folder.getProperty( + 'business_template_registered_skin_selections', ()): + break + except AttributeError: + pass + else: + skin_tool.manage_skinLayers(chosen=[skin_name], del_skin=1) + skin_tool.getPortalObject().changeSkin(None) + +def unregisterSkinFolderId(skin_tool, skin_folder_id, skin_selection_list): + for skin_selection in skin_selection_list: + selection = skin_tool.getSkinPath(skin_selection) + selection = selection.split(',') + if (skin_folder_id in selection): + selection.remove(skin_folder_id) + skin_tool.manage_skinLayers(skinpath=tuple(selection), + skinname=skin_selection, add_skin=1) + deleteSkinSelection(skin_tool, skin_selection) + skin_tool.getPortalObject().changeSkin(None) diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py index b3e18f1c76e37c9e274f1f23e322e2eede6db27e..f5284c944ae884cb5d59cb0b09a967a7c62c9c53 100644 --- a/product/ERP5/ERP5Site.py +++ b/product/ERP5/ERP5Site.py @@ -237,11 +237,12 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin): last_id = 0 icon = 'portal.gif' # Default value, prevents error during upgrade - isIndexable = ConstantGetter('isIndexable', value=True) + isIndexingRequired = ConstantGetter('isIndexingRequired', value=True) # There can remain a lot a activities to be processed once all BT5 are # installed, and scalability tests want a reliable way to know when the site # is ready to be tortured. isPortalBeingCreated = ConstantGetter('isPortalBeingCreated', value=False) + isIndexingRequired = ConstantGetter('isIndexingRequired', value=True) _properties = ( { 'id':'title', @@ -1893,7 +1894,7 @@ class ERP5Generator(PortalGenerator): portal = self.klass(id=id) # Make sure reindex will not be called until business templates # will be installed - setattr(portal, 'isIndexable', ConstantGetter('isIndexable', value=False)) + setattr(portal, 'isIndexingRequired', ConstantGetter('isIndexingRequired', value=False)) # This is only used to refine log level. # Has no functional use, and should never have any: @@ -1959,6 +1960,35 @@ class ERP5Generator(PortalGenerator): return p + @classmethod + def bootstrap_bm(cls, context, bm_name, path_list): + """ + Bootstrap Business Item from the paths needed + """ + bm_path = getBootstrapBusinessTemplateUrl(bm_name) + portal = context.getPortalObject() + try: + # If template_tool doesn't exist, do nothing + template_tool = portal.portal_templates + pt = portal.portal_types + # Create dynamic_class for Business Manager if it doesn't exist in + # portal_types + if pt.getTypeInfo('Business Manager') is None: + import erp5 + BusinessManager = getattr(erp5.portal_type, 'Business Manager') + BusinessManager.loadClass() + manager = BusinessManager(id='bootstrap_bm') + connection = pt._p_jar + else: + manager = template_tool.newContent(portal_type='Business Manager') + connection = None + manager.importFile(bm_path + '/' + bm_name + '.zexp', connection) + for path in path_list: + item = manager.getBusinessItemByPath(path) + item.install(manager, portal) + except AttributeError: + pass + @classmethod def bootstrap(cls, context, bt_name, item_name, content_id_list): bt_path = getBootstrapBusinessTemplateUrl(bt_name) @@ -1983,9 +2013,9 @@ class ERP5Generator(PortalGenerator): def bootstrap_allow_type(types_tool, portal_type): from xml.etree.cElementTree import parse bt_path = getBootstrapBusinessTemplateUrl('erp5_core') - types_tool[portal_type].allowed_content_types = [x.text for x in parse( + setattr(types_tool[portal_type], 'allowed_content_types' ,([x.text for x in parse( os.path.join(bt_path, 'PortalTypeAllowedContentTypeTemplateItem', 'allowed_content_types.xml') - ).iterfind("portal_type[@id='%s']/*" % portal_type)] + ).iterfind("portal_type[@id='%s']/*" % portal_type)])) def setupLastTools(self, p, **kw): """ @@ -1997,6 +2027,7 @@ class ERP5Generator(PortalGenerator): addERP5Tool(p, 'portal_simulation', 'Simulation Tool') addERP5Tool(p, 'portal_deliveries', 'Delivery Tool') addERP5Tool(p, 'portal_orders', 'Order Tool') + addERP5Tool(p, 'portal_diff', 'Diff Tool') def setupTemplateTool(self, p, **kw): """ @@ -2052,7 +2083,7 @@ class ERP5Generator(PortalGenerator): addERP5Tool(p, 'portal_memcached', 'Memcached Tool') # Add erp5 catalog tool - addERP5Tool(p, 'portal_catalog', 'Catalog Tool') + addERP5Tool(p, 'portal_catalog', 'ERP5 Catalog Tool') sql_reset = kw.get('sql_reset', 0) def addSQLConnection(id, title, **kw): @@ -2205,7 +2236,7 @@ class ERP5Generator(PortalGenerator): def setupIndex(self, p, **kw): # Make sure all tools and folders have been indexed if kw.get('reindex', 1): - setattr(p, 'isIndexable', ConstantGetter('isIndexable', value=True)) + setattr(p, 'isIndexingRequired', ConstantGetter('isIndexingRequired', value=True)) # Clear portal ids sql table, like this we do not take # ids for a previously created web site p.portal_ids.clearGenerator(all=True) @@ -2325,9 +2356,17 @@ class ERP5Generator(PortalGenerator): if not p.hasObject('content_type_registry'): self.setupMimetypes(p) + # Explicitly run bootstrap for portal_types and portal_property_sheets + # before installing bootstrap Business Template/Manager becuase it needs to + # be there for bootstrap portal_types and property_sheets to be used. + p.portal_types._bootstrap() + p.portal_property_sheets._bootstrap() + if not update: self.setupWorkflow(p) self.setupERP5Core(p,**kw) + # XXX: Force setting of properties setter and getters after bootstrap + p.portal_types.resetDynamicDocuments() self.setupERP5Promise(p,**kw) # Make sure the cache is initialized @@ -2346,8 +2385,8 @@ class ERP5Generator(PortalGenerator): """ template_tool = p.portal_templates if template_tool.getInstalledBusinessTemplate('erp5_core') is None: - for bt in ('erp5_property_sheets', 'erp5_core', p.erp5_catalog_storage, 'erp5_jquery', - 'erp5_xhtml_style'): + for bt in ('erp5_property_sheets', 'erp5_core', 'erp5_business_package', + p.erp5_catalog_storage, 'erp5_jquery', 'erp5_xhtml_style',): if not bt: continue url = getBootstrapBusinessTemplateUrl(bt) diff --git a/product/ERP5/Tool/CommitTool.py b/product/ERP5/Tool/CommitTool.py new file mode 100644 index 0000000000000000000000000000000000000000..ff2894a3e5f37eb61962a8b5cd8e343347892f68 --- /dev/null +++ b/product/ERP5/Tool/CommitTool.py @@ -0,0 +1,229 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved. +# Jean-Paul Smets-Solanes +# Hugo Ricateau +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from webdav.client import Resource + +from App.config import getConfiguration +import os +import time +import shutil +import sys +import hashlib +import pprint +import transaction + +from Acquisition import Implicit, Explicit +from AccessControl import ClassSecurityInfo +from AccessControl.SecurityInfo import ModuleSecurityInfo +from Products.CMFActivity.ActiveResult import ActiveResult +from Products.PythonScripts.PythonScript import PythonScript +from Products.ERP5Type.Globals import InitializeClass, DTMLFile, PersistentMapping +from Products.ERP5Type.DiffUtils import DiffFile +from Products.ERP5Type.Tool.BaseTool import BaseTool +from Products.ERP5Type.Cache import transactional_cached +from Products.ERP5Type import Permissions, interfaces +from Products.ERP5.Document.BusinessTemplate import BusinessTemplateMissingDependency +from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter +from Products.ERP5.genbt5list import generateInformation +from Acquisition import aq_base +from tempfile import mkstemp, mkdtemp +from Products.ERP5 import _dtmldir +from cStringIO import StringIO +from urllib import pathname2url, urlopen, splittype, urlretrieve +import urllib2 +import re +from xml.dom.minidom import parse +from xml.parsers.expat import ExpatError +import struct +import cPickle +from base64 import b64encode, b64decode +from Products.ERP5Type.Message import translateString +from zLOG import LOG, INFO, WARNING +from base64 import decodestring +from difflib import unified_diff +from operator import attrgetter +import subprocess +import time + +class CommitTool (BaseTool): + """ + CommitTool manages commits of Business Templates. + + CommitTool provides some methods to deal with Business Templates: + - download commits + - install commits + - push commits + - XXX + + ERP5 Business Commit contains: + - ERP5 Business Template Item + - ERP5 Business Template Property Item + - ERP5 Business Template Patch Item + in relation to one or more ERP5 Business Template (follow_up relation from BTI to BTS) + + ERP5 Business Commit has relation to: + - predecessor: previous Business Commit + + ERP5 Business Snapshot has relation to: + - similar: equivalent ERP5 Business Commit + they only serve as a way to optmize installation time by having all objects in one + folder rather than downloading 10 years of commit to get things installed + + ERP5 Business Temaplate Specification defines: + - title + - description + - dependency + - list of paths (of different kinds) to help generate initial ERP5 Business Commit + It is only a spec file with no object inside + + ERP5 Business Snapshot contains: + - all BTI BTPI and BTPI for a single BT at specifc build point + + Bootstrap: + - import zexp file to portal_commits/ + - portal_commits/business_template_index is installed (ERP5 Buiness Snapshot of the erp5_root_index business template) [BOOSTRAP] + - this makes portal_templates/* full of all possibles Business Template that can be installed + - portal_commits/business_template_index --> similar/portal_commits/387897938794876-276376 + + Portal Templates: + - portal_templates/erp5_base (only one) + - portal_templates/erp5_trade (only one) + they containing nothing inside, just their title and description and spec (like a spec file in rpm) + + Installation: + - download all commits that + - are predecessor of 387897938794876-276376 + - that are required to install (erp5_base, erp5_trade, etc.) + RESULT: + - portal_commits/387897938794876-1 (Commit) + - portal_commits/387897938794876-2 (Commit) + - portal_commits/387897938794876-3 (Commit) + - portal_commits/387897938794876-4 (Commit) + - portal_commits/387897938794876-5 (Commit) + - portal_commits/387897938794876-6 (Commit) + - portal_commits/387897938794876-7 (Commit) + - portal_commits/387897938794876-8 (Commit) + - portal_commits/387897938794876-9 (Snapshort of erp5_trade) + - portal_commits/387897938794876-10 (Snapshot of erp5_base) + + Draft -> Committed -> Pushed (to repo) |Commit] + Draft -> Installed <-> Uninstalled |Snapshot] + + Developer mode: make commits and push them (nothing else) + Developer mode: make snapshots and push them (nothing else) + + Installation: + - create an empty snapshot that that's similar to a Commit + - fill it with hard links to commits and snapshots + - install it + + Only Draft can be modified + + 3 types + - Commit - partial state (pushed) + - Save Point - complete state with copies of a single bt (only for + optimisation) (really needed ?) (pushed) + - Snapshort - complete state with hard link for all bt (installed) + + We should try first with Commit and Snapshot + """ + + id = 'portal_commits' + title = 'Commit Tool' + meta_type = 'ERP5 Commit Tool' + portal_type = 'Commit Tool' + allowed_types = ( + 'Business Commit', + 'Business Snapshot', + ) + + id_generator = '_generateUniversalUniqueId' + + # This stores information on repositories. + repository_dict = {} + + # Declarative Security + security = ClassSecurityInfo() + + security.declareProtected(Permissions.ManagePortal, 'manage_overview') + #manage_overview = DTMLFile('explainCommitTool', _dtmldir) + + def getCommitList(self): + return self.objectValues(portal_type='Business Commit') + + def getSnapshotList(self): + return self.objectValues(portal_type='Business Snapshot') + + def getInstalledSnapshot(self): + """ + Return the installed snapshot. + Returns None in case there is no snapshot installed. + """ + snapshot = [l for l + in self.getSnapshotList() + if l.getValidationState() == 'installed'] + + if len(snapshot) == 1: + return snapshot[0] + elif len(snapshot) > 1: + raise ValueError('Multiple Snapshot in installed state') + else: + return None + + security.declarePublic('getHeadCommit') + def getHeadCommit(self): + """ + Returns the HEAD commit object + """ + return self._getOb(self.getHeadCommitId()) + + security.declarePublic('newContent') + def newContent(self, id=None, portal_type=None, **kw): + """ + Overrides newContent in order to automatically hint the predecessor. + """ + + new_object = super(CommitTool, self).newContent(id, portal_type, **kw) + + # Adds the last committed or pushed commit as its predecessor if there is one + committed_or_pushed_commit_list = [c for c + in self.searchFolder(portal_type='Business Commit') + if c != new_object and + c.getValidationState() != 'draft' and + c.getValidationState() != 'deleted'] + + if committed_or_pushed_commit_list: + latest_committed_or_pushed_commit = max(committed_or_pushed_commit_list, + key=(lambda c:c.getModificationDate())) + new_object.setPredecessorValue(latest_committed_or_pushed_commit) + + return new_object + +InitializeClass(CommitTool) diff --git a/product/ERP5/Tool/DiffTool.py b/product/ERP5/Tool/DiffTool.py new file mode 100644 index 0000000000000000000000000000000000000000..7259e2c366b4f5f6c8ef7f850c95b8b85fcff71a --- /dev/null +++ b/product/ERP5/Tool/DiffTool.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SARL and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import jsonpatch +from deepdiff import DeepDiff + +from AccessControl import ClassSecurityInfo +from Products.ERP5Type.Globals import InitializeClass +from Products.ERP5Type.Tool.BaseTool import BaseTool +from Products.ERP5Type import Permissions + +class DiffTool(BaseTool): + """ + A portal tool that provides all kinds of utilities to + compare objects. + """ + id = 'portal_diff' + title = 'Diff Tool' + meta_type = 'ERP5 Diff Tool' + portal_type = 'Portal Diff Tool' + allowed_types = () + + # Declarative Security + security = ClassSecurityInfo() + + def diffPortalObject(self, old, new, path=None, patch_format="deepdiff"): + """ + Returns a PortalPatch instance with the appropriate format + original -- original object + new -- new object + path -- optional path to specify which property to diff + patch_format -- optional format (rfc6902 or deepdiff) + """ + return PortalPatch(old, new, patch_format) + + +class PortalPatch: + """ + Provides an abstraction to a patch that + depends on the patch format. + + In the case of deepdiff, the abstraction can + lead to a commutative merge system. + + In the case of rfc6902, the abstraction can not + lead to a commutative merge system but may be + useful to some UI applications. + """ + + def __init__(self, old, new, patch_format="deepdiff"): + """ + Intialises the class from a deepdiff or + a rfc6902 patch. deepdiff is the default. + """ + self.old_value = old + self.new_value = new + self.patch_format = patch_format + + def getPortalPatchOperationList(self): + """ + List all PortalPatchOperation instances in the PortalPatch + """ + patch = self.asDeepDiffPatch() + # In general, we are using `tree` view, so basically for us all operations + # currently are `values_changed` from old to new value or to none + change_list = patch.values() + # Here we can have the change_list as nested list also, for example: + # + # change_list = + # { + # 'iterable_item_removed': set([]), + # 'values_changed': set([, ]) + # } + # We can see here that the values are basically change from one value to + # another, so to get the list of operation(s), we have to flatten all the + # values in one list + flatten_change_list = [item for sublist in change_list for item in sublist] + return flatten_change_list + + def patchPortalObject(self, object): + """ + Apply patch to an object by applying + one by one each PortalPatchItem + """ + pass + + def asDeepDiffPatch(self): + """ + Returns a Json patch with deep diff extensions + """ + # Use try-except as it's easier to ask forgiveness than permission + + # `_asDict` is available only for objects, so in that case, we convert the + # ERP5-fied objects into dict and then work on them. + # In all other cases, we let `deepdiff` do its work on checking the type + try: + src = self.old_value._asDict() + except AttributeError: + src = self.old_value + + try: + dst = self.new_value._asDict() + except AttributeError: + dst = self.new_value + + # For now, we prefer having 'tree' view as it provides us with node level + # where on each node we have value changed(atleast for list and dictionary) + ddiff = DeepDiff(src, dst, view='tree') + return ddiff + + def asStrippedHTML(self): + """ + Returns an HTML representation of the whole patch + that can be embedded + """ + pass + + def asHTML(self): + """ + Returns an HTML representation of the whole patch + that can be displayed in a standalone way + """ + pass + +class PortalPatchOperation: + """ + Provides an abstraction to a patch operation that + depends on the patch format. + + In the case of deepdiff, each operation defines + actually a desired state in a declarative way. + + In the case of rfc6902, each operation is defined + in an imperative manner. + """ + + def patchPortalObject(object, unified_diff_selection=None): + """ + Apply patch to an object + + unified_diff_selection -- a selection of lines in the unified diff + that will be applied + """ + pass + + def getOperation(self): + """ + Returns one of "replace", "add" or "remove" + + (hopefully, this can also be used for deepdiff format) + set_item_added, values_changed, etc. + """ + pass + + def getPath(self): + """ + Returns a path representing the value that is changed + (hopefully, this can also be used for deepdiff format) + """ + pass + + def getOldValue(self): + """ + Returns the old value + """ + pass + + def getNewValue(self): + """ + Returns the new value + """ + pass + + def getUnifiedDiff(self): + """ + Returns a unified diff of the value changed + (this is useful for a text value) or None if + there is no such change. + + (see String difference 2 in deepdiff) + """ + pass + + def asStrippedHTML(self): + """ + Returns an HTML representation of the change + that can be embedded + """ + pass + + def asHTML(self): + """ + Returns an HTML representation that can be displayed + in a standalone way + """ + pass + +InitializeClass(DiffTool) diff --git a/product/ERP5/Tool/TemplateTool.py b/product/ERP5/Tool/TemplateTool.py index d6fd92b5b6596758b796ae3f3e756f4d42d4ee00..3fbf0daf4332873333ccd03a3272752bafd56183 100644 --- a/product/ERP5/Tool/TemplateTool.py +++ b/product/ERP5/Tool/TemplateTool.py @@ -33,17 +33,22 @@ from App.config import getConfiguration import os import shutil import sys +import hashlib +import pprint +import transaction from Acquisition import Implicit, Explicit from AccessControl import ClassSecurityInfo from AccessControl.SecurityInfo import ModuleSecurityInfo from Products.CMFActivity.ActiveResult import ActiveResult +from Products.PythonScripts.PythonScript import PythonScript from Products.ERP5Type.Globals import InitializeClass, DTMLFile, PersistentMapping from Products.ERP5Type.DiffUtils import DiffFile from Products.ERP5Type.Tool.BaseTool import BaseTool from Products.ERP5Type.Cache import transactional_cached -from Products.ERP5Type import Permissions +from Products.ERP5Type import Permissions, interfaces from Products.ERP5.Document.BusinessTemplate import BusinessTemplateMissingDependency +from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter from Products.ERP5.genbt5list import generateInformation from Acquisition import aq_base from tempfile import mkstemp, mkdtemp @@ -60,6 +65,8 @@ from base64 import b64encode, b64decode from Products.ERP5Type.Message import translateString from zLOG import LOG, INFO, WARNING from base64 import decodestring +from difflib import unified_diff +from operator import attrgetter import subprocess import time @@ -101,7 +108,10 @@ class TemplateTool (BaseTool): title = 'Template Tool' meta_type = 'ERP5 Template Tool' portal_type = 'Template Tool' - allowed_types = ('ERP5 Business Template', ) + allowed_content_types = [ + 'Business Template', + 'Business Template V2', + ] # This stores information on repositories. repository_dict = {} @@ -128,7 +138,14 @@ class TemplateTool (BaseTool): # potential danger because business templates may exchange catalog # methods, so the database could be broken temporarily. last_bt = last_time = None - for bt in self.objectValues(portal_type='Business Template'): + for bt in self.objectValues(portal_type=['Business Template', + 'Business Manager']): + if bt.getPortalType() == 'Business Manager': + if bt.getInstallationState() == 'installed' and bt.title == title: + return bt + else: + continue + return None if bt.getTitle() == title or title in bt.getProvisionList(): state = bt.getInstallationState() if state == 'installed': @@ -149,6 +166,22 @@ class TemplateTool (BaseTool): last_time = t return last_bt + security.declareProtected(Permissions.AccessContentsInformation, + 'getInstalledBusinessManager') + def getInstalledBusinessManager(self, title, strict=False, **kw): + """Returns an installed version of business manager of given title. + + Returns None if business manager is not installed or has been uninstalled. + """ + last_bm = None + for bm in self.objectValues(portal_type='Business Manager'): + if bm.getTitle() == title: + state = bm.getInstallationState() + if state == 'installed': + return bm + + return last_bm + security.declareProtected(Permissions.AccessContentsInformation, 'getInstalledBusinessTemplatesList') def getInstalledBusinessTemplatesList(self): @@ -161,7 +194,8 @@ class TemplateTool (BaseTool): """Get the list of installed business templates. """ installed_bts = [] - for bt in self.contentValues(portal_type='Business Template'): + for bt in self.contentValues(portal_type=['Business Template', + 'Business Manager']): if bt.getInstallationState() == 'installed': bt5 = bt if only_title: @@ -276,7 +310,7 @@ class TemplateTool (BaseTool): if RESPONSE is not None: RESPONSE.setHeader('Content-type','tar/x-gzip') RESPONSE.setHeader('Content-Disposition', 'inline;filename=%s-%s.bt5' - % (business_template.getTitle(), business_template.getVersion())) + % (business_template.getTitle(), business_template.getVersion())) return export_string.getvalue() finally: export_string.close() @@ -306,6 +340,7 @@ class TemplateTool (BaseTool): self.deleteContent(id) self._importObjectFromFile(StringIO(export_string), id=id) + security.declareProtected( Permissions.ManagePortal, 'manage_download' ) def manage_download(self, url, id=None, REQUEST=None): """The management interface for download. @@ -321,9 +356,14 @@ class TemplateTool (BaseTool): REQUEST.RESPONSE.redirect("%s?portal_status_message=%s" % (ret_url, psm)) - def _download_local(self, path, bt_id): + def _download_local(self, path, bt_id, format_version=1): """Download Business Template from local directory or file """ + if format_version == 3: + bm = self.newContent(bt_id, 'Business Template V2') + bm.importFile(path) + return bm + bt = self.newContent(bt_id, 'Business Template') bt.importFile(path) return bt @@ -361,12 +401,17 @@ class TemplateTool (BaseTool): # come from the management interface. if REQUEST is not None: return self.manage_download(url, id=id, REQUEST=REQUEST) - if id is None: id = self.generateNewId() - urltype, path = splittype(url) - if WIN and urltype and '\\' in path: + urltype, name = splittype(url) + # Create a zexp path which would be used for Business Manager files + zexp_path = name + '/' + name.split('/')[-1] + '.zexp' + # Better to expand path as we now use ~software_release for the software + # folder + zexp_path = os.path.expanduser(zexp_path) + + if WIN and urltype and '\\' in name: urltype = None path = url if urltype and urltype != 'file': @@ -377,9 +422,28 @@ class TemplateTool (BaseTool): del bt.uid return self[self._setObject(id, bt)] bt = self._download_url(url, id) + elif os.path.exists(zexp_path): + # If the path exists, we create a Business Manager object after + # downloading it from zexp path + bt = self._download_local(os.path.normpath(zexp_path), id, format_version=3) else: - path = os.path.normpath(os.path.expanduser(path)) - bt = self._download_local(path, id) + template_version_path_list = [ + name+'/bt/template_format_version', + ] + + for path in template_version_path_list: + try: + file = open(os.path.normpath(path)) + except IOError: + continue + try: + format_version = int(file.read()) + file.close() + except UnboundLocalError: + # In case none of the above paths do have template_format_version + format_version = 1 + # XXX: Download only needed in case the file is in directory + bt = self._download_local(os.path.expanduser(os.path.normpath(name)), id, format_version) bt.build(no_action=True) return bt @@ -534,6 +598,412 @@ class TemplateTool (BaseTool): self.activate(activity='SQLQueue').\ importAndReExportBusinessTemplateFromPath(template_path) + security.declareProtected( 'Import/Export objects', 'migrateBTToBM') + def migrateBTToBM(self, template_path, isReduced=False, REQUEST=None, **kw): + """ + Migrate business template repository to Business Manager repo. + Business Manager completely rely only on BusinessItem and to show + the difference between both of them + + So, the steps should be: + 1. Install the business template which is going to be migrated + 2. Create a new Business Manager with random id and title + 3. Add the path, build and export the template + 4. Remove the business template from the directory and add the business + manager there instead + 5. Change the ID and title of the business manager + 6. Export the business manager to the directory, leaving anything in + the installed erp5 unchanged + """ + import_template = self.download(url=template_path) + if import_template.getPortalType() == 'Business Manager': + LOG(import_template.getTitle(),0,'Already migrated') + return + + export_dir = mkdtemp() + + removable_property = {} + removable_sub_object_path = [] + + installed_bt_list = self.getInstalledBusinessTemplatesList() + installed_bt_title_list = [bt.title for bt in installed_bt_list] + + is_installed = False + if import_template.getTitle() not in installed_bt_title_list: + # Install the business template + import_template.install(**kw) + is_installed = True + + # Make list of object paths which needs to be added in the bm5 + # This can be decided by looping over every type of items we do have in + # bt5 and checking if there have been any changes being made to it via this + # bt5 installation or not. + # For ex: + # CatalogTempalteMethodItem, CatalogResultsKeyItem, etc. do make some + # changes in erp5_mysql_innodb(by adding properties, by adding sub-objects), + # so we need to add portal_catalog/erp5_mysql_innodb everytime we find + # a bt5 making changes in any of these items. + + portal_path = self.getPortalObject() + template_path_list = [] + property_path_list = [] + + # For modules, we don't need to create path for the module + module_list = import_template.getTemplateModuleIdList() + for path in module_list: + template_path_list.append(path) + + # For portal_types, we have to add path and subobjects + portal_type_id_list = import_template.getTemplatePortalTypeIdList() + portal_type_path_list = [] + portal_type_workflow_chain_path_list = [] + for id in portal_type_id_list: + portal_type_path_list.append('portal_types/'+id) + # Add type_worklow list separately in path + portal_type_workflow_chain_path_list.append('portal_types/'+id+'#type_workflow_list') + # Remove type_workflow_list from the objects, so that we don't end up in + # conflict + portal_type_path = 'portal_types/' + id + removable_property[portal_type_path] = ['type_workflow_list'] + template_path_list.extend(portal_type_path_list) + template_path_list.extend(portal_type_workflow_chain_path_list) + + # For categories, we create path for category objects as well as the subcategories + category_list = import_template.getTemplateBaseCategoryList() + category_path_list = [] + for base_category in category_list: + category_path_list.append('portal_categories/'+base_category) + #category_path_list.append('portal_categories/'+base_category+'/**') + template_path_list.extend(category_path_list) + + # Adding tools + template_tool_id_list = import_template.getTemplateToolIdList() + tool_id_list = [] + for tool_id in template_tool_id_list: + tool_id_list.append(tool_id) + template_path_list.extend(tool_id_list) + + # Adding business template skin selection property on the portal_tempaltes + template_skin_selection_list = import_template.getTemplateRegisteredSkinSelectionList() + selection_list = [] + for selection in template_skin_selection_list: + skin, selection = selection.split(' | ') + selection_list.append('portal_skins/%s#business_template_registered_skin_selections'%skin) + + # For portal_skins, we export the folder + portal_skin_list = import_template.getTemplateSkinIdList() + portal_skin_path_list = [] + for skin in portal_skin_list: + portal_skin_path_list.append('portal_skins/'+skin) + #portal_skin_path_list.append('portal_skins/'+skin+'/**') + template_path_list.extend(portal_skin_path_list) + + # For workflow chains, + # We have 2 objects in the Business Template design where we deal with + # workflow objects, we deal with the installation separately: + # 1. Workflow_id : We export the whole workflow objects in this case + # 2. Portal Workflow chain: It is already being exported via portal_types + # XXX: CHECK For 2, keeping in mind the migration of workflow would be merged + # before this part where we make workflow_list as property of portal_type + workflow_id_list = import_template.getTemplateWorkflowIdList() + workflow_path_list = [] + for workflow in workflow_id_list: + workflow_path_list.append('portal_workflow/' + workflow) + #workflow_path_list.append('portal_workflow/' + workflow + '/**') + template_path_list.extend(workflow_path_list) + + # For tests in portal components add them with portal_components head + test_id_list = import_template.getTemplateTestIdList() + test_path_list = [] + for path in test_id_list: + test_path_list.append('portal_components/' + path) + template_path_list.extend(test_path_list) + + # For documents in portal components add them with portal_components head + document_id_list = import_template.getTemplateDocumentIdList() + document_path_list = [] + for path in document_id_list: + document_path_list.append('portal_components/' + path) + template_path_list.extend(document_path_list) + + # For extensions in portal components add them with portal_components head + extension_id_list = import_template.getTemplateExtensionIdList() + extension_path_list = [] + for path in extension_id_list: + extension_path_list.append('portal_components/' + path) + template_path_list.extend(extension_path_list) + + # For paths, we add them directly to the path list + path_list = import_template.getTemplatePathList() + for path in path_list: + template_path_list.append(path) + + # Catalog methods would be added as sub objects + catalog_method_item_list = import_template.getTemplateCatalogMethodIdList() + catalog_method_path_list = [] + for method in catalog_method_item_list: + catalog_method_path_list.append('portal_catalog/' + method) + template_path_list.extend(catalog_method_path_list) + + # For catalog objects, we check if there is any catalog object, and then + # add catalog object also in the path if there is + template_catalog_datetime_key = import_template.getTemplateCatalogDatetimeKeyList() + template_catalog_full_text_key = import_template.getTemplateCatalogFullTextKeyList() + template_catalog_keyword_key = import_template.getTemplateCatalogKeywordKeyList() + template_catalog_local_role_key = import_template.getTemplateCatalogLocalRoleKeyList() + template_catalog_multivalue_key = import_template.getTemplateCatalogMultivalueKeyList() + template_catalog_related_key = import_template.getTemplateCatalogRelatedKeyList() + template_catalog_request_key = import_template.getTemplateCatalogRequestKeyList() + template_catalog_result_key = import_template.getTemplateCatalogResultKeyList() + template_catalog_result_table = import_template.getTemplateCatalogResultTableList() + template_catalog_role_key = import_template.getTemplateCatalogRoleKeyList() + template_catalog_scriptable_key = import_template.getTemplateCatalogScriptableKeyList() + template_catalog_search_key = import_template.getTemplateCatalogSearchKeyList() + template_catalog_security_uid_column = import_template.getTemplateCatalogSecurityUidColumnList() + template_catalog_topic_key = import_template.getTemplateCatalogTopicKeyList() + + catalog_property_list = [ + template_catalog_datetime_key, + template_catalog_full_text_key, + template_catalog_keyword_key, + template_catalog_local_role_key, + template_catalog_multivalue_key, + template_catalog_related_key, + template_catalog_request_key, + template_catalog_result_key, + template_catalog_result_table, + template_catalog_role_key, + template_catalog_scriptable_key, + template_catalog_search_key, + template_catalog_security_uid_column, + template_catalog_topic_key, + ] + is_property_added = any(catalog_property_list) + + properties_removed = [ + 'sql_catalog_datetime_search_keys_list', + 'sql_catalog_full_text_search_keys_list', + 'sql_catalog_keyword_search_keys_list', + 'sql_catalog_local_role_keys_list', + 'sql_catalog_multivalue_keys_list', + 'sql_catalog_related_keys_list', + 'sql_catalog_request_keys_list', + 'sql_search_result_keys_list', + 'sql_search_tables_list', + 'sql_catalog_role_keys_list', + 'sql_catalog_scriptable_keys_list', + 'sql_catalog_search_keys_list', + 'sql_catalog_security_uid_columns_list', + 'sql_catalog_topic_search_keys_list', + ] + + if is_property_added: + if catalog_method_path_list: + catalog_path = catalog_method_path_list[0].rsplit('/', 1)[0] + else: + catalog_path = 'portal_catalog/erp5_mysql_innodb' + removable_sub_object_path.append(catalog_path) + removable_property[catalog_path] = properties_removed + for prop in properties_removed: + property_path_list.append('%s#%s' % (catalog_path, prop)) + + # Add these catalog items in the object_property instead of adding + # dummy path item for them + if import_template.getTitle() == 'erp5_mysql_innodb_catalog': + template_path_list.append('portal_catalog/erp5_mysql_innodb') + + # Add portal_property_sheets + property_sheet_id_list = import_template.getTemplatePropertySheetIdList() + property_sheet_path_list = [] + for property_sheet in property_sheet_id_list: + property_sheet_path_list.append('portal_property_sheets/' + property_sheet) + #property_sheet_path_list.append('portal_property_sheets/' + property_sheet + '/**') + template_path_list.extend(property_sheet_path_list) + + # Create new objects for business manager + migrated_bm = self.newContent( + portal_type='Business Manager', + title=import_template.getTitle() + ) + + template_path_list.extend(property_path_list) + template_path_list.extend(selection_list) + template_path_list = self.cleanTemplatePathList(template_path_list) + + # XXX: Add layer=1 and sign=1 for default for all paths + template_path_list = [l + ' | 1 | 1' for l in template_path_list] + + def reduceDependencyList(bt, template_path_list): + """ + Used for recursive udpation of layer for dependency in a BT + """ + dependency_list = bt.getDependencyList() + # XXX: Do not return template_path_list of the new BM incase there is no + # dependency_list, instead look for the latest updated version of + # new_template_path_list + if not dependency_list: + return template_path_list + else: + # Copy of the initial template list to be used to update the layer + new_template_path_list = list(template_path_list) + for item in dependency_list: + dependency = item.split(' ', 1) + if len(dependency) > 1: + version = dependency[1] + if version: + version = version[1:-1] + else: + version = None + try: + base_bt = self.getLastestBTOnRepos(dependency[0], version) + except BusinessTemplateIsMeta: + bt_list = self.getProviderList(dependency[0]) + # We explicilty use the Business Template which is used the most + # while dealing with provision list + repository_list = self.getRepositoryList() + if dependency[0] == 'erp5_full_text_catalog': + base_bt = [repository_list[0], 'erp5_full_text_mroonga_catalog'] + if dependency[0] == 'erp5_view_style': + base_bt = [repository_list[1], 'erp5_xhtml_style'] + if dependency[0] == 'erp5_catalog': + base_bt = [repository_list[1], 'erp5_mysql_innodb_catalog'] + + # Download the base_bt + base_bt_path = os.path.join(base_bt[0], base_bt[1]) + base_bt = self.download(base_bt_path) + + # Check for the item list and if the BT is Business Manager, + # if BM, then compare and update layer and if not run migration and + # then do it again + if base_bt.getPortalType() != 'Business Manager': + # If the base_bt is not Business Manager, run the migration on the + # base_bt + base_bt = self.migrateBTToBM(base_bt_path, isReduced=True) + + # Check for item path which also exists in base_bt + base_path_list = base_bt.getPathList() + + copy_of_template_path_list = new_template_path_list[:] + # Loop through all the paths in the new_template_path_list and + # check for their existence in base_path_list + for idx, path in enumerate(new_template_path_list): + path_list = path.split(' | ') + item_path = path_list[0] + item_layer = path_list[2] + if item_path in base_path_list: + # TODO: Increase the layer of the path item by +1 and save it + # back at updated_template_path_list + item_layer = int(item_layer) + 1 + updated_path = item_path + ' | 1 | ' + str(item_layer) + copy_of_template_path_list[idx] = updated_path + new_template_path_list = copy_of_template_path_list + + if base_bt.getPortalType() != 'Business Manager': + # Recursively reduce the base Business Templatem no need to do + # this for Business Manager(s) as it had already been migrated + # with taking care of layer + reduceDependencyList(base_bt, new_template_path_list) + + return new_template_path_list + + # Take care about the the dependency_list also and then update the layer + # accordingly for the path(s) that already exists in the dependencies. + template_path_list = reduceDependencyList(import_template, template_path_list) + + # Create new sub-objects instead based on template_path_list + for path in template_path_list: + + path_list = path.split(' | ') + + # Create Business Property Item for objects with property in path + if '#' in path_list[0]: + migrated_bm.newContent( + portal_type='Business Property Item', + item_path=path_list[0], + item_sign=path_list[1], + item_layer=path_list[2], + ) + else: + migrated_bm.newContent( + portal_type='Business Item', + item_path=path_list[0], + item_sign=path_list[1], + item_layer=path_list[2], + ) + + kw['removable_property'] = removable_property + kw['removable_sub_object_path'] = removable_sub_object_path + migrated_bm.build(**kw) + + # Commit transaction to generate all oids before exporting + transaction.commit() + # Export the newly built business manager to the export directory + migrated_bm.export(path=export_dir, local=True) + + if is_installed: + import_template.uninstall() + + if isReduced: + return migrated_bm + + def cleanTemplatePathList(self, path_list): + """ + Remove redundant paths and sub-objects' path if the object path already + exist. + """ + # Split path into list + a2 = [l.split('/') for l in path_list] + # Create new list for paths with ** + a3 = [l for l in a2 if l[-1] in ('**', '*')] + # Create new list for paths without ** + a4 = [l for l in a2 if l[-1] not in ('**', '*')] + # Remove ** from paths in a3 + reserved_id = ('portal_transforms', 'portal_ids') + a3 = [l[:-1] for l in a3 if l[0] not in reserved_id] + [l for l in a3 if l[0] in reserved_id] + # Create new final path list + a2 = a3+a4 + # Join the path list + a2 = [('/').join(l) for l in a2] + # Remove the redundant paths + seen = set() + seen_add = seen.add + # XXX: What about redundant signs with different layers + # Maybe we will end up reducing them + a2 = [x for x in a2 if not (x in seen or seen_add(x))] + + return a2 + + security.declareProtected( 'Import/Export objects', 'migrateBTListToBM') + def migrateBTToBMRequest(self, bt_title_list, REQUEST=None, **kw): + """ + Run migration for BT5 one by one in a given repository. This will be done + via activities. + """ + if REQUEST is None: + REQUEST = getattr(self, 'REQUEST', None) + + if len(bt_title_list) == 0 and REQUEST: + ret_url = self.absolute_url() + REQUEST.RESPONSE.redirect("%s?portal_status_message=%s" + % (ret_url, 'No BT title was given')) + + repository_list = self.getRepositoryList() + for title in bt_title_list: + title = title.rstrip('\n') + title = title.rstrip('\r') + for repository in repository_list: + if title in os.listdir(repository): + template_path = os.path.join(repository, title) + else: + continue + if os.path.isfile(template_path): + LOG(title, 0, 'is file, so it is skipped') + else: + if not os.path.exists((os.path.join(template_path, 'bt'))): + LOG(title, 0, 'has no bt sub-folder, so it is skipped') + else: + self.migrateBTToBM(template_path) + security.declareProtected(Permissions.ManagePortal, 'getFilteredDiff') def getFilteredDiff(self, diff): """ @@ -1141,10 +1611,8 @@ class TemplateTool (BaseTool): template_title_list, with_test_dependency_list=False): available_bt5_list = self.getRepositoryBusinessTemplateList() - template_title_list = set(template_title_list) installed_bt5_title_list = self.getInstalledBusinessTemplateTitleList() - bt5_set = set() for available_bt5 in available_bt5_list: if available_bt5.title in template_title_list: @@ -1341,8 +1809,11 @@ class TemplateTool (BaseTool): if update_catalog is CATALOG_UPDATABLE and install_kw != {}: update_catalog = imported_bt5.isCatalogUpdatable() - imported_bt5.install(object_to_update=install_kw, - update_catalog=update_catalog) + if imported_bt5.getPortalType() == 'Business Manager': + self.updateInstallationState([imported_bt5]) + else: + imported_bt5.install(object_to_update=install_kw, + update_catalog=update_catalog) # Run After script list for after_triggered_bt5_id in after_triggered_bt5_id_list: @@ -1357,6 +1828,611 @@ class TemplateTool (BaseTool): return imported_bt5 + security.declareProtected(Permissions.ManagePortal, + 'installBusinessManager') + def installBusinessManager(self, bm): + """ + Run installation on flattened Business Manager + """ + # Run install on separate Business Item one by one + for path_item in bm._path_item_list: + path_item.install(self) + + bm.setStatus('installed') + + def updateHash(self, item): + """ + Function to update hash of Business Item or Business Property Item + """ + # Check for isProperty attribute + if item.isProperty: + value = item.getProperty('item_property_value') + else: + value_list = item.objectValues() + if value_list: + value = value_list[0] + else: + value = '' + + if value: + item.setProperty('item_sha', self.calculateComparableHash( + value, + item.isProperty, + )) + + def rebuildBusinessManager(self, bm): + """ + Compare the sub-objects in the Business Manager to the previous built + state to give user powet to decide on which item to rebuild. + """ + checkNeeded = True + changed_path_list = [] + + if bm.getBuildingState() not in ['built', 'modified']: + # In case the building_state is not built, we build the BM without + # comparing anything + checkNeeded = False + return checkNeeded, changed_path_list + + portal = self.getPortalObject() + for item in bm.objectValues(): + # Check for the change compared to old building state, i.e, if there is + # some change made at ZODB state(it also count changes made due to + # change while installation of other BM) + path = item.getProperty('item_path') + + try: + if item.isProperty: + # Get the value for Business Property Item + value = item.getProperty('item_property_value') + # Get the value at ZODB + relative_url, property_id = path.split('#') + obj = portal.restrictedTraverse(relative_url) + property_value = obj.getProperty(property_id) + + # If the value at ZODB for the property is none, raise KeyError + # This is important to have compatibility between the way we check + # path as well as property. Otherwise, if we install a new property, + # we are always be getting an Error that there is change made at + # ZODB for this property + if not property_value: + raise KeyError + + obj = property_value + else: + # Get the value of the Business Path Item + value_list = item.objectValues() + if value_list: + value = value_list[0] + else: + # If there is no value, it means the path_item is new, thus no + # need to comapre hash and check anything + changed_path_list.append((path, 'New')) + continue + + # Get the object at ZODB + obj = portal.restrictedTraverse(path) + + # Calculate hash for value at ZODB + obj_sha = self.calculateComparableHash(obj, item.isProperty) + + # Update hash for value at property_value + self.updateHash(item) + item_sha = item.getProperty('item_sha') + + # Compare the hash with the item hash + if obj_sha != item_sha: + changed_path_list.append((path, 'Changed')) + else: + changed_path_list.append((path, 'Unchanged')) + + # KeyError is raised in case the value/object has been deleted at ZODB + except KeyError: + changed_path_list.append((path, 'Deleted')) + + return checkNeeded, changed_path_list + + security.declareProtected(Permissions.ManagePortal, + 'updateInstallationState') + def compareInstallationState(self, bm_list): + """ + Run installation after comparing combined Business Manager status + + Steps: + 1. Create combinedBM for the bm_list + 2. Get the old combinedBM by checking the 'installed' status for it or + by checking timestamp (?? which is better) + CombinedBM: Collection of all Business item(s) whether installed or + uninstalled + 3. Build BM from the filesystem + 4. Compare the combinedBM state to the last combinedBM state + 5. Compare the installation state to the OFS state + 6. If conflict while comaprison at 3, raise the error + 7. In all other case, install the BM List + """ + + # Create old installation state from Installed Business Manager + installed_bm_list = self.getInstalledBusinessManagerList() + combined_installed_path_item = [item for bm + in installed_bm_list + for item in bm.objectValues()] + + # Create BM for old installation state and update its path item list + old_installation_state = self.newContent( + portal_type='Business Manager', + title='Old Installation State', + temp_object=True, + ) + + for item in combined_installed_path_item: + item.isIndexable = ConstantGetter('isIndexable', value=False) + # Better to use new ids so that we don't end up in conflicts + new_id = old_installation_state.generateNewId() + old_installation_state._setObject(new_id, aq_base(item), + suppress_events=True) + + forbidden_bm_title_list = ['Old Installation State',] + for bm in bm_list: + forbidden_bm_title_list.append(bm.title) + + new_installed_bm_list = [l for l + in self.getInstalledBusinessManagerList() + if l.title not in forbidden_bm_title_list] + new_installed_bm_list.extend(bm_list) + + combined_new_path_item = [item for bm + in new_installed_bm_list + for item in bm.objectValues()] + + # Create BM for new installation state and update its path item list + new_installation_state = self.newContent( + portal_type='Business Manager', + title='New Installation State', + temp_object=True, + ) + + for item in combined_new_path_item: + item.isIndexable = ConstantGetter('isIndexable', value=False) + new_id = new_installation_state.generateNewId() + new_installation_state._setObject(new_id, aq_base(item), + suppress_events=True) + + # Create installation process, which have the changes to be made in the + # OFS during installation. Importantly, it should also be a Business Manager + installation_process = self.newContent( + portal_type='Business Manager', + title='Installation Process', + temp_object=True, + ) + + # Reduce both old and new Installation State + old_installation_state.reduceBusinessManager() + new_installation_state.reduceBusinessManager() + + # Get path list for old and new states + old_state_path_list = old_installation_state.getPathList() + new_state_path_list = new_installation_state.getPathList() + + to_install_path_item_list = [] + + # Get the path which has been removed in new installation_state + removed_path_list = [path for path + in old_state_path_list + if path not in new_state_path_list] + + # Add the removed path with negative sign in the to_install_path_item_list + for path in removed_path_list: + old_item = old_installation_state.getBusinessItemByPath(path) + old_item.setProperty('item_sign', '-1') + to_install_path_item_list.append(old_item) + + # Reduce old_installation_state again as changes as new sub-objects maybe + # added to the old_installation_state + old_installation_state.reduceBusinessManager() + + # XXX: At this point, we expect all the Business Manager objects as 'reduced', + # thus all the BusinessItem sub-objects should have single value + # Update hashes of item in old state before installation + for item in old_installation_state.objectValues(): + + # In case of Business Patch Item we need to update hash of both new and + # old value + if item.getPortalType() == 'Business Patch Item': + new_val = item._getOb('new_item') + old_val = item._getOb('old_item') + self.updateHash(new_val) + self.updateHash(old_val) + else: + self.updateHash(item) + + # Path Item List for installation_process should be the difference between + # old and new installation state + for item in new_installation_state.objectValues(): + + # If the path has been removed, then add it with sign = -1 + old_item = old_installation_state.getBusinessItemByPath(item.getProperty('item_path')) + + # In case of Business Patch Item we need to update hash of both new and + # old value + if item.getPortalType() == 'Business Patch Item': + new_val = item._getOb('new_item') + old_val = item._getOb('old_item') + self.updateHash(new_val) + self.updateHash(old_val) + else: + self.updateHash(item) + + if old_item: + to_be_installed_item = item + if old_item.getPortalType() == 'Business Patch Item': + # In case of Business Patch Item, we just need to compare the hash + # of old_item + old_item = old_item._getOb('old_item') + item = item._getOb('old_item') + + # If the old_item exists, we match the hashes and if it differs, then + # add the new item + if old_item.getProperty('item_sha') != item.getProperty('item_sha'): + to_install_path_item_list.append(to_be_installed_item) + + else: + to_install_path_item_list.append(item) + + for item in to_install_path_item_list: + item.isIndexable = ConstantGetter('isIndexable', value=False) + new_id = new_installation_state.generateNewId() + installation_process._setObject(new_id, aq_base(item), + suppress_events=True) + + change_list = self.compareOldStateToOFS(installation_process, old_installation_state) + + if change_list: + change_list = [(l[0].item_path, l[1]) for l in change_list] + + return change_list + + def updateInstallationState(self, bm_list, force=1): + """ + First compare installation state and then install the final value + """ + change_list = self.compareInstallationState(bm_list) + + if force: + to_install_path_list = [l[0] for l in change_list] + to_install_path_list = self.sortPathList(to_install_path_list) + + # Install the path items with bm_list as context + self.installBusinessItemList(bm_list, to_install_path_list) + + installMultipleBusinessManager = updateInstallationState + + def installBusinessItemList(self, manager_list, item_path_list): + """ + Install Business Item/Business Property Item from the current Installation + Process given the change_list which carries the list of paths to be + installed + """ + LOG('INFO', 0, '%s' % [item_path_list]) + + # Create BM for new installation state and update its path item list + new_installation_state = self.newContent( + portal_type='Business Manager', + title='Final Installation State', + temp_object=True, + ) + combined_new_path_item_list = [item for bm + in manager_list + for item in bm.objectValues()] + + for item in combined_new_path_item_list: + item.isIndexable = ConstantGetter('isIndexable', value=False) + new_id = new_installation_state.generateNewId() + new_installation_state._setObject(new_id, aq_base(item), + suppress_events=True) + + for path in item_path_list: + item = new_installation_state.getBusinessItemByPath(path) + if item is None: + raise ValueError("Couldn't find path in current Installation State") + item.install(new_installation_state) + + # Update workflow history of the installed Business Manager(s) + # Get the 'business_manager_installation_workflow' as it is already + # bootstrapped and installed + portal_workflow = self.getPortalObject().portal_workflow + wf = portal_workflow._getOb('business_manager_installation_workflow') + + # Change the installation state for all the BM(s) in manager_list. + for manager in manager_list: + wf._executeMetaTransition(manager, 'installed') + + def calculateComparableHash(self, object, isProperty=False): + """ + Remove some attributes before comparing hashses + and return hash of the comparable object dict, in case the object is + an erp5 object. + + Use shallow copy of the dict of the object at ZODB after removing + attributes which changes at small updation, like workflow_history, + uid, volatile attributes(which starts with _v) + + # XXX: Comparable hash shouldn't be used for BusinessPatchItem as whole. + We can compare the old_value and new_value, but there shouldn't be hash + for the Patch Item. + """ + if isProperty: + obj_dict = object + # Have compatibilty between tuples and list while comparing as we face + # this situation a lot especially for list type properties + if isinstance(obj_dict, list): + obj_dict = tuple(obj_dict) + else: + + klass = object.__class__ + classname = klass.__name__ + obj_dict = object.__dict__.copy() + + # If the dict is empty, do calculate hash of None as it stays same on + # one platform and in any case its impossiblt to move live python + # objects from one seeion to another + if not bool(obj_dict): + return hash(None) + + attr_set = {'_dav_writelocks', '_filepath', '_owner', '_related_index', + 'last_id', 'uid', '_mt_index', '_count', '_tree', + '__ac_local_roles__', '__ac_local_roles_group_id_dict__', + 'workflow_history', 'subject_set_uid_dict', 'security_uid_dict', + 'filter_dict', '_max_uid'} + + attr_set.update(('isIndexable',)) + + if classname in ('File', 'Image'): + attr_set.update(('_EtagSupport__etag', 'size')) + elif classname == 'Types Tool' and klass.__module__ == 'erp5.portal_type': + attr_set.add('type_provider_list') + + for attr in object.__dict__.keys(): + if attr in attr_set or attr.startswith('_cache_cookie_') or attr.startswith('_v'): + try: + del obj_dict[attr] + except AttributeError: + # XXX: Continue in cases where we want to delete some properties which + # are not in attribute list + # Raise an error + continue + + # Special case for configuration instance attributes + if attr in ['_config', '_config_metadata']: + import collections + # Order the dictionary so that comparison can be correct + obj_dict[attr] = collections.OrderedDict(sorted(obj_dict[attr].items())) + if 'valid_tags' in obj_dict[attr]: + try: + obj_dict[attr]['valid_tags'] = collections.OrderedDict(sorted(obj_dict[attr]['valid_tags'].items())) + except AttributeError: + # This can occur in case the valid_tag object is PersistentList + pass + + if 'data' in obj_dict: + try: + obj_dict['data'] = obj_dict.get('data').__dict__ + except AttributeError: + pass + + obj_sha = hash(pprint.pformat(obj_dict)) + return obj_sha + + def sortPathList(self, path_list): + """ + Custom sort for path_list according to the priorities of paths + """ + def comparePath(path): + split_path_list = path.split('/') + # Paths with property item should have the least priority as they should + # be installed after installing the object only + if '#' in path: + return 11 + if len(split_path_list) == 2 and split_path_list[0] in ('portal_types', 'portal_categories'): + return 1 + # portal_transforms objects needs portal_components installed first so + # as to register the modules + if len(split_path_list) == 2 and split_path_list[0] == 'portal_transforms': + return 12 + if len(split_path_list) > 2: + return 10 + if len(split_path_list) == 1: + return 2 + return 5 + + return sorted(path_list, key=comparePath) + + def compareOldStateToOFS(self, installation_process, old_state): + + # Get the paths about which we are concerned about + to_update_path_list = installation_process.getPathList() + portal = self.getPortalObject() + + # List to store what changes will be done to which path. Here we compare + # with all the states (old version, new version and state of object at ZODB) + change_list = [] + + to_update_path_list = self.sortPathList(to_update_path_list) + + for path in to_update_path_list: + try: + # Better to check for status of BusinessPatchItem separately as it + # can contain both BusinessItem as well as BusinessPropertyItem + new_item = installation_process.getBusinessItemByPath(path) + if new_item.getPortalType() == 'Business Patch Item': + patch_item = new_item + # If the value is in ZODB, then compare it to the old_value + if '#' in str(path): + isProperty = True + relative_url, property_id = path.split('#') + obj = portal.restrictedTraverse(relative_url) + property_value = obj.getProperty(property_id) + if not property_value: + raise KeyError + property_type = obj.getPropertyType(property_id) + obj = property_value + else: + # If the path is path on an object and not of a property + isProperty = False + obj = portal.restictedTraverse(path) + + obj_sha = self.calculateComparableHash(obj, isProperty) + + # Get the sha of new_item from the BusinessPatchItem object + new_item_sha = patch_item._getOb('new_item').getProperty('item_sha') + old_item_sha = patch_item._getOb('old_item').getProperty('item_sha') + + if new_item_sha == obj_sha: + # If the new_item in the patch is same as the one at ZODB, do + # nothing + continue + elif old_item_sha == obj_sha: + change_list.append((patch_item._getOb('new_item'), 'Adding')) + else: + change_list.append((patch_item._getOb('new_item'), 'Removing')) + + if '#' in str(path): + isProperty = True + relative_url, property_id = path.split('#') + obj = portal.restrictedTraverse(relative_url) + property_value = obj.getProperty(property_id) + + # If the value at ZODB for the property is none, raise KeyError + # This is important to have compatibility between the way we check + # path as well as property. Otherwise, if we install a new property, + # we are always be getting an Error that there is change made at + # ZODB for this property + if not property_value: + raise KeyError + property_type = obj.getPropertyType(property_id) + obj = property_value + else: + isProperty = False + # XXX: Hardcoding because of problem with 'resource' trying to access + # the resource via acqusition. Should be removed completely before + # merging (DONT PUSH THIS) + if path == 'portal_categories/resource': + path_list = path.split('/') + container_path = path_list[:-1] + object_id = path_list[-1] + container = portal.restrictedTraverse(container_path) + obj = container._getOb(object_id) + else: + obj = portal.restrictedTraverse(path) + + obj_sha = self.calculateComparableHash(obj, isProperty) + + # Get item at old state + old_item = old_state.getBusinessItemByPath(path) + # Check if there is an object at old state at this path + + if old_item: + # Compare hash with ZODB + + if old_item.getProperty('item_sha') == obj_sha: + # No change at ZODB on old item, so get the new item + new_item = installation_process.getBusinessItemByPath(path) + # Compare new item hash with ZODB + + if new_item.getProperty('item_sha') == obj_sha: + if int(new_item.getProperty('item_sign')) == -1: + # If the sign is negative, remove the value from the path + change_list.append((new_item, 'Removing')) + else: + # If same hash, and +1 sign, do nothing + continue + + else: + # Install the new_item + change_list.append((new_item, 'Adding')) + + else: + # Change at ZODB, so get the new item + new_item = installation_process.getBusinessItemByPath(path) + # Compare new item hash with ZODB + + if new_item.getProperty('item_sha') == obj_sha: + # If same hash, do nothing + continue + + else: + # Trying to update change at ZODB + change_list.append((new_item, 'Updating')) + + else: + # Object created at ZODB by the user + # Compare with the new_item + + new_item = installation_process.getBusinessItemByPath(path) + if new_item.getProperty('item_sha') == obj_sha: + # If same hash, do nothing + continue + + else: + # Trying to update change at ZODB + change_list.append((new_item, 'Updating')) + + except (AttributeError, KeyError) as e: + # Get item at old state + old_item = old_state.getBusinessItemByPath(path) + # Check if there is an object at old state at this path + + if old_item: + # This means that the user had removed the object at this path + # Check what the sign is for the new_item + new_item = installation_process.getBusinessItemByPath(path) + # Check sign of new_item + + if int(new_item.getProperty('item_sign')) == 1: + # Object at ZODB has been removed by the user + change_list.append((new_item, 'Adding')) + + else: + # If there is no item at old state, install the new_item + new_item = installation_process.getBusinessItemByPath(path) + # XXX: Hack for not trying to install the sub-objects from zexp, + # This should rather be implemented while exporting the object, + # where we shouldn't export sub-objects in the zexp + if not isProperty: + try: + value = new_item.objectValues()[0] + except IndexError: + continue + # Installing a new item + change_list.append((new_item, 'Adding')) + + return change_list + + def getInstalledBusinessManagerList(self): + bm_list = self.objectValues(portal_type='Business Manager') + installed_bm_list = [bm for bm in bm_list + if bm.getInstallationState() == 'installed'] + return installed_bm_list + + def getInstalledBusinessManagerTitleList(self): + installed_bm_list = self.getInstalledBusinessManagerList() + if not len(installed_bm_list): + return [] + installed_bm_title_list = [bm.title for bm in installed_bm_list] + return installed_bm_title_list + + def getInstalledBusinessTemplateV2List(self): + bt_list = self.objectValues(portal_type='Business Template V2') + installed_bt_list = [bt for bt in bt_list + if bt.getAvailabilityState() == 'installable'] + return installed_bt_list + + def getInstalledBusinessTemplateV2TitleList(self): + installed_bt_list = self.getInstalledBusinessManagerV2List() + if not len(installed_bt_list): + return [] + installed_bt_title_list = [bt.getTitle() for bt in installed_bt_list] + return installed_bt_title_list + security.declareProtected(Permissions.ManagePortal, 'getBusinessTemplateUrl') def getBusinessTemplateUrl(self, base_url_list, bt5_title): diff --git a/product/ERP5/__init__.py b/product/ERP5/__init__.py index 523ce4ac81b71870072ec14a78a95b5fbfe8c930..21ea0d8d8572ab4d2473224e963783df7bbbce57 100644 --- a/product/ERP5/__init__.py +++ b/product/ERP5/__init__.py @@ -51,12 +51,15 @@ from Tool import CategoryTool, SimulationTool, RuleTool, IdTool, TemplateTool,\ GadgetTool, ContributionRegistryTool, IntrospectionTool,\ AcknowledgementTool, SolverTool, SolverProcessTool,\ ConversionTool, RoundingTool, UrlRegistryTool, InterfaceTool,\ - CertificateAuthorityTool, InotifyTool, TaskDistributionTool + CertificateAuthorityTool, InotifyTool, TaskDistributionTool,\ + DiffTool, CommitTool import ERP5Site -from Document import PythonScript, SQLMethod +from Document import PythonScript, BusinessTemplateV2 object_classes = ( ERP5Site.ERP5Site, PythonScript.PythonScriptThroughZMI, - SQLMethod.SQLMethod, + BusinessTemplateV2.BusinessItem, + BusinessTemplateV2.BusinessPropertyItem, + BusinessTemplateV2.BusinessPatchItem, ) portal_tools = ( CategoryTool.CategoryTool, SimulationTool.SimulationTool, @@ -85,6 +88,8 @@ portal_tools = ( CategoryTool.CategoryTool, InotifyTool.InotifyTool, TaskDistributionTool.TaskDistributionTool, InterfaceTool.InterfaceTool, + DiffTool.DiffTool, + CommitTool.CommitTool, ) content_classes = () content_constructors = () diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/build_items.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/build_items.xml new file mode 100644 index 0000000000000000000000000000000000000000..d32ff9a6d8290d05bedb2dcc0efd8ad8fb24deb4 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/build_items.xml @@ -0,0 +1,100 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_action + + + + + category + object_action + + + condition + + AAAAAAAAAAM= + + + + description + + + + + + icon + + + + id + build_items + + + permissions + + + Manage portal + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + Build all items + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/BusinessCommit_buildItems + + + + + + + + + + + + text + python: here.getValidationState() == \'draft\' + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/install.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/install.xml new file mode 100644 index 0000000000000000000000000000000000000000..7d04ec53a1365e8c0ce3a7d7aeba6d66826f5913 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/install.xml @@ -0,0 +1,100 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_action + + + + + category + object_action + + + condition + + AAAAAAAAAAM= + + + + description + + + + + + icon + + + + id + install + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 2.0 + + + title + Install Commit + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/BusinessCommit_install + + + + + + + + + + + + text + python: here.getValidationState() in (\'commited\', \'pushed\') + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/view.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/view.xml new file mode 100644 index 0000000000000000000000000000000000000000..1d62283640a9970c1bc25fe362f14ab82b90fd19 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Commit/view.xml @@ -0,0 +1,85 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_view + + + + + category + object_view + + + condition + + + + description + + + + + + icon + + + + id + view + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + View + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/BusinessCommit_view + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Item/goto_path.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Item/goto_path.xml new file mode 100644 index 0000000000000000000000000000000000000000..4c71419bbd32c66b909f27d2e7b6a676060747a6 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Item/goto_path.xml @@ -0,0 +1,85 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_jump + + + + + category + object_jump + + + condition + + + + description + + + + + + icon + + + + id + goto_path + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + Go To ZODB Object Path + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/BusinessItem_redirectToZODBPath + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Item/view.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Item/view.xml new file mode 100644 index 0000000000000000000000000000000000000000..2750a133d6ca8c164f213a1e9ddd11f9e418a4e3 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Item/view.xml @@ -0,0 +1,85 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_view + + + + + category + object_view + + + condition + + + + description + + + + + + icon + + + + id + view + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + View + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/BusinessItem_view + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Snapshot/view.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Snapshot/view.xml new file mode 100644 index 0000000000000000000000000000000000000000..b6d493280c4974176b411fb22815ffb1235fa746 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Snapshot/view.xml @@ -0,0 +1,85 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_view + + + + + category + object_view + + + condition + + + + description + + + + + + icon + + + + id + view + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + View + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/BusinessSnapshot_view + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Template%20V2/content_view.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Template%20V2/content_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b44df545ad95392a36cf649b9972117f7a356ab --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Business%20Template%20V2/content_view.xml @@ -0,0 +1,85 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_view + + + + + category + object_view + + + condition + + + + description + + + + + + icon + + + + id + content_view + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + View + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/BusinessTemplateV2_view + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Commit%20Tool/create_snapshot.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Commit%20Tool/create_snapshot.xml new file mode 100644 index 0000000000000000000000000000000000000000..c7ed8b4d541679a121f6dc51ef511d866683d70a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Commit%20Tool/create_snapshot.xml @@ -0,0 +1,85 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_action + + + + + category + object_action + + + condition + + + + description + + + + + + icon + + + + id + create_snapshot + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + Generate Snapshot + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/CommitTool_createSnapshot + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Commit%20Tool/view.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Commit%20Tool/view.xml new file mode 100644 index 0000000000000000000000000000000000000000..13a6253b1a4db946984d4195a112fda1a2702ea8 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/Commit%20Tool/view.xml @@ -0,0 +1,85 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + categories + + + action_type/object_view + + + + + category + object_view + + + condition + + + + description + + + + + + icon + + + + id + view + + + permissions + + + View + + + + + portal_type + Action Information + + + priority + 1.0 + + + title + View + + + visible + 1 + + + + + + + + + + + + text + string:${object_url}/CommitTool_viewCommitList + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/portal_actions/commit_tool.xml b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/portal_actions/commit_tool.xml new file mode 100644 index 0000000000000000000000000000000000000000..a483e9c6f9f9121ba3f606a665e240fa43e13248 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ActionTemplateItem/portal_types/portal_actions/commit_tool.xml @@ -0,0 +1,71 @@ + + + + + + + + + + action + + AAAAAAAAAAI= + + + + category + global + + + condition + + + + description + + + + icon + + + + id + commit_tool + + + permissions + + + Manage portal + + + + + priority + 2.5 + + + title + Manage Commits and Snapshots + + + visible + 1 + + + + + + + + + + + + text + string:${portal_url}/portal_commits/view + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ExtensionTemplateItem/portal_components/extension.erp5.CommitUtils.py b/product/ERP5/bootstrap/erp5_business_package/ExtensionTemplateItem/portal_components/extension.erp5.CommitUtils.py new file mode 100644 index 0000000000000000000000000000000000000000..bfb81fdc5498785963e61545491b80317ee27116 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ExtensionTemplateItem/portal_components/extension.erp5.CommitUtils.py @@ -0,0 +1,47 @@ +############################################################################## +# +# Copyright (c) 2017 Nexedi SA and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +def getLatestCommitTitle(commit): + """ + Function to get last commit title. + Returns None if there is no last commit + """ + portal = commit.getPortalObject() + commit_tool = portal.portal_commits + + # Get all commits in commit tool + commit_list = commit_tool.objectValues(portal_type='Business Commit') + # Remove the current created commit from the commit_list + commit_list = [l for l in commit_list if l != commit] + + # Get the commit which was created last + latest_commit = max(commit_list, key=lambda x: x.getCreationDate()) + + if latest_commit is None: + return '' + return latest_commit.getTitle() diff --git a/product/ERP5/bootstrap/erp5_business_package/ExtensionTemplateItem/portal_components/extension.erp5.CommitUtils.xml b/product/ERP5/bootstrap/erp5_business_package/ExtensionTemplateItem/portal_components/extension.erp5.CommitUtils.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5f8fc99762fe8cc18e40ab47497d80d5af3dcd0 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ExtensionTemplateItem/portal_components/extension.erp5.CommitUtils.xml @@ -0,0 +1,121 @@ + + + + + + + + + + _recorded_property_dict + + AAAAAAAAAAI= + + + + default_reference + CommitUtils + + + description + Utility functions to be used with commit tool + + + id + extension.erp5.CommitUtils + + + portal_type + Extension Component + + + sid + + + + + + text_content_error_message + + + + + + text_content_warning_message + + + + + + version + erp5 + + + workflow_history + + AAAAAAAAAAM= + + + + + + + + + + + + + data + + + + + + + + + + + + + + + data + + + + component_validation_workflow + + AAAAAAAAAAQ= + + + + + + + + + + + + + + + + + + + action + validate + + + validation_state + validated + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml new file mode 100644 index 0000000000000000000000000000000000000000..95f3aa6637524c7e92bc1a6f8fb8df13bb507c9e --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml @@ -0,0 +1,9 @@ + + + Business Item + + + Business Commit + Business Snapshot + + \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeBaseCategoryTemplateItem/base_category_list.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeBaseCategoryTemplateItem/base_category_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..9805350955f0a21f3ebf7eec7b4e89d60ea57a3d --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeBaseCategoryTemplateItem/base_category_list.xml @@ -0,0 +1,12 @@ + + + predecessor + + + follow_up + predecessor + + + predecessor + + \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeHiddenContentTypeTemplateItem/hidden_content_type_list.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeHiddenContentTypeTemplateItem/hidden_content_type_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..5784d887f3c42ac930b10d6eced4fc8ce797ee57 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeHiddenContentTypeTemplateItem/hidden_content_type_list.xml @@ -0,0 +1,5 @@ + + + Business Item + + \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypePropertySheetTemplateItem/property_sheet_list.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypePropertySheetTemplateItem/property_sheet_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..7454c941899791ab3f47b041451fd719ac623a11 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypePropertySheetTemplateItem/property_sheet_list.xml @@ -0,0 +1,15 @@ + + + BusinessCommit + + + BusinessItem + BusinessItemConstraint + + + BusinessCommit + + + CommitTool + + \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Commit.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Commit.xml new file mode 100644 index 0000000000000000000000000000000000000000..fb702c5c17fa70eb9cda1908c5de883cecabe4ce --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Commit.xml @@ -0,0 +1,69 @@ + + + + + + + + + + content_icon + + + + + + description + + + + + + filter_content_types + 1 + + + id + Business Commit + + + permission + + + + + + portal_type + Base Type + + + searchable_text_property_id + + + title + description + reference + short_title + + + + + type_class + BusinessCommit + + + type_interface + + + + + + type_mixin + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Item.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Item.xml new file mode 100644 index 0000000000000000000000000000000000000000..374b90fae96318983768c9f525c82ce93b58d9d9 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Item.xml @@ -0,0 +1,75 @@ + + + + + + + + + + content_icon + + + + + + description + + + + + + filter_content_types + 1 + + + id + Business Item + + + init_script + + + + + + permission + + + + + + portal_type + Base Type + + + searchable_text_property_id + + + title + description + reference + short_title + + + + + type_class + BusinessItem + + + type_interface + + + + + + type_mixin + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Snapshot.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Snapshot.xml new file mode 100644 index 0000000000000000000000000000000000000000..657d0db34a15da8650568d32746f460c8e06c2aa --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Snapshot.xml @@ -0,0 +1,69 @@ + + + + + + + + + + content_icon + + + + + + description + + + + + + filter_content_types + 0 + + + id + Business Snapshot + + + permission + + + + + + portal_type + Base Type + + + searchable_text_property_id + + + title + description + reference + short_title + + + + + type_class + BusinessSnapshot + + + type_interface + + + + + + type_mixin + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Template%20V2.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Template%20V2.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b0ce4b3de3fed7e0b4dd8c432c60c118b000232 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Business%20Template%20V2.xml @@ -0,0 +1,62 @@ + + + + + + + + + + content_icon + + + + + + description + Simplified version of Business Template + + + filter_content_types + 1 + + + id + Business Template V2 + + + init_script + + + + + + permission + + + + + + portal_type + Base Type + + + type_class + BusinessTemplateV2 + + + type_interface + + + + + + type_mixin + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Commit%20Tool.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Commit%20Tool.xml new file mode 100644 index 0000000000000000000000000000000000000000..8249e930d1e62f263c19e3bf536af112830d550f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeTemplateItem/portal_types/Commit%20Tool.xml @@ -0,0 +1,69 @@ + + + + + + + + + + content_icon + + + + + + description + + + + + + filter_content_types + 1 + + + id + Commit Tool + + + permission + + + + + + portal_type + Base Type + + + searchable_text_property_id + + + title + description + reference + short_title + + + + + type_class + CommitTool + + + type_interface + + + + + + type_mixin + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml b/product/ERP5/bootstrap/erp5_business_package/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml new file mode 100644 index 0000000000000000000000000000000000000000..ae52ba580d8b32784cc9d23d59383682192c7f31 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml @@ -0,0 +1,18 @@ + + + Business Commit + business_commit_interaction_workflow, business_commit_validation_workflow + + + Business Item + business_item_interaction_workflow, business_item_validation_workflow + + + Business Snapshot + business_snapshot_validation_workflow + + + Business Template V2 + business_template_availability_workflow + + \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint.xml new file mode 100644 index 0000000000000000000000000000000000000000..6e3b8067c14f3746cc99b725111ddb22353fef6f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint.xml @@ -0,0 +1,66 @@ + + + + + + + + + + _count + + AAAAAAAAAAI= + + + + _mt_index + + AAAAAAAAAAM= + + + + _tree + + AAAAAAAAAAQ= + + + + description + + + + + + id + BusinessItemConstraint + + + portal_type + Property Sheet + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint/business_template_existence_constraint.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint/business_template_existence_constraint.xml new file mode 100644 index 0000000000000000000000000000000000000000..de371829698150fc8f63488e5d62aa5736497f5e --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint/business_template_existence_constraint.xml @@ -0,0 +1,86 @@ + + + + + + + + + + _identity_criterion + + AAAAAAAAAAI= + + + + _range_criterion + + AAAAAAAAAAM= + + + + constraint_base_category + + + follow_up + + + + + constraint_portal_type + python: (\'Business Template V2\',) + + + description + Follow Up Business Template must be defined + + + id + business_template_existence_constraint + + + message_category_not_set + Follow Up Business Template must be defined + + + portal_type + Category Existence Constraint + + + use_acquisition + 0 + + + + + + + + + + + + data + + + + + + + + + + + + + + + data + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint/path_existence_constraint.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint/path_existence_constraint.xml new file mode 100644 index 0000000000000000000000000000000000000000..25149405f2fe918366468052b6a4f376be90d9db --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessItemConstraint/path_existence_constraint.xml @@ -0,0 +1,80 @@ + + + + + + + + + + _identity_criterion + + AAAAAAAAAAI= + + + + _range_criterion + + AAAAAAAAAAM= + + + + constraint_property + + + item_path + + + + + description + + + + + + id + path_existence_constraint + + + message_no_such_property + Path must be defined + + + portal_type + Property Existence Constraint + + + + + + + + + + + + data + + + + + + + + + + + + + + + data + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5b707bf6c31f037bf158abbaefde3e29d5db339 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2.xml @@ -0,0 +1,66 @@ + + + + + + + + + + _count + + AAAAAAAAAAI= + + + + _mt_index + + AAAAAAAAAAM= + + + + _tree + + AAAAAAAAAAQ= + + + + description + + + + + + id + BusinessTemplateV2 + + + portal_type + Property Sheet + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/change_log_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/change_log_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..f0cbc40e0a8b993cde8fe0c31167b698f1a4e6c2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/change_log_property.xml @@ -0,0 +1,57 @@ + + + + + + + + + + _local_properties + + + + + id + mode + + + type + string + + + + + + + categories + + + elementary_type/text + + + + + description + A change log + + + id + change_log_property + + + mode + w + + + portal_type + Standard Property + + + property_default + python: \'\' + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/copyright_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/copyright_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..a252ad67ca1f94bd716ac13f4e04e43899206732 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/copyright_property.xml @@ -0,0 +1,57 @@ + + + + + + + + + + _local_properties + + + + + id + mode + + + type + string + + + + + + + categories + + + elementary_type/lines + + + + + description + A list of copyright holders + + + id + copyright_property + + + mode + w + + + portal_type + Standard Property + + + property_default + python: () + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/dependency_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/dependency_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..e6548c11580fbe70bdb0e5d5edb60e03111aac16 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/dependency_property.xml @@ -0,0 +1,57 @@ + + + + + + + + + + _local_properties + + + + + id + mode + + + type + string + + + + + + + categories + + + elementary_type/lines + + + + + description + a list of template names required by this template + + + id + dependency_property + + + mode + w + + + portal_type + Standard Property + + + property_default + python: () + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/item_path_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/item_path_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..6607d3c0b7c81ee393cfadd62f1ad7dce071e79f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/item_path_property.xml @@ -0,0 +1,36 @@ + + + + + + + + + + categories + + + elementary_type/lines + + + + + description + A list of paths used by this template. They can be path of erp5 objects or also of the property. + + + id + item_path_property + + + portal_type + Standard Property + + + property_default + python: () + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/license_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/license_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..893a9cb28aba0da7d605990a816325a328ad1a73 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/license_property.xml @@ -0,0 +1,57 @@ + + + + + + + + + + _local_properties + + + + + id + mode + + + type + string + + + + + + + categories + + + elementary_type/text + + + + + description + License + + + id + license_property + + + mode + w + + + portal_type + Standard Property + + + property_default + python: \'\' + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/maintainer_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/maintainer_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..50802df01b215411a109516b359ce75da5a7848c --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/maintainer_property.xml @@ -0,0 +1,57 @@ + + + + + + + + + + _local_properties + + + + + id + mode + + + type + string + + + + + + + categories + + + elementary_type/lines + + + + + description + A list of maintainers + + + id + maintainer_property + + + mode + w + + + portal_type + Standard Property + + + property_default + python: () + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/provision_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/provision_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..0c5b93d0aa0327e12c26700a57d31294ab95cd56 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/provision_property.xml @@ -0,0 +1,57 @@ + + + + + + + + + + _local_properties + + + + + id + mode + + + type + string + + + + + + + categories + + + elementary_type/lines + + + + + description + a list of template names provided by this template + + + id + provision_property + + + mode + w + + + portal_type + Standard Property + + + property_default + python: () + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/test_dependency_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/test_dependency_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..d9ce685dd8d5323afd2794eafbb468364f72b5d1 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/BusinessTemplateV2/test_dependency_property.xml @@ -0,0 +1,36 @@ + + + + + + + + + + categories + + + elementary_type/lines + + + + + description + a list of template names required by this template to run unit tests from an instance created only for unit tests + + + id + test_dependency_property + + + portal_type + Standard Property + + + property_default + python: () + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/CommitTool.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/CommitTool.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e901c7fa8e3b146991163cec7bedf108a1e9938 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/CommitTool.xml @@ -0,0 +1,66 @@ + + + + + + + + + + _count + + AAAAAAAAAAI= + + + + _mt_index + + AAAAAAAAAAM= + + + + _tree + + AAAAAAAAAAQ= + + + + description + + + + + + id + CommitTool + + + portal_type + Property Sheet + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/CommitTool/head_commit_id_property.xml b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/CommitTool/head_commit_id_property.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d2b4f10a2ad07587c9d61d55f5692489a6b2f62 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/PropertySheetTemplateItem/portal_property_sheets/CommitTool/head_commit_id_property.xml @@ -0,0 +1,34 @@ + + + + + + + + + + categories + + + elementary_type/string + + + + + description + + + + + + id + head_commit_id_property + + + portal_type + Standard Property + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit.xml new file mode 100644 index 0000000000000000000000000000000000000000..62e2a0f7fa1f8e2a1c529ab506e24e3f8c3a7385 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit.xml @@ -0,0 +1,26 @@ + + + + + + + + + + _objects + + + + + + id + erp5_commit + + + title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastCommit.py b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastCommit.py new file mode 100644 index 0000000000000000000000000000000000000000..6b02838592bb1e43f4a9c9dcf7c1897ff60f48c2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastCommit.py @@ -0,0 +1,14 @@ +from operator import attrgetter + +portal = context.getPortalObject() + +commit_tool = portal.portal_commits +# Get all commits in commit tool +commit_list = commit_tool.objectValues(portal_type='Business Commit') + +lastest_commit = max(commit_list, key=attrgetter('creation_date')) + +if latest_commit is None: + return '' + +return latest_commit.title diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastCommit.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastCommit.xml new file mode 100644 index 0000000000000000000000000000000000000000..66021cc628082efe88557f6d23e0896a0e9f1e79 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastCommit.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + + + + id + Base_getLastCommit + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastHistoryDiff.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastHistoryDiff.xml new file mode 100644 index 0000000000000000000000000000000000000000..dc1281ebf224711562d5fc73a20e41f3605faee2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getLastHistoryDiff.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _function + getLastHistoryDiff + + + _module + ZODBHistory + + + id + Base_getLastHistoryDiff + + + title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getTruncatedDescription.py b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getTruncatedDescription.py new file mode 100644 index 0000000000000000000000000000000000000000..7f2af2ed3b661490291171fab43db087dabe1ab1 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getTruncatedDescription.py @@ -0,0 +1,22 @@ +object_truncated_description_length = 72 # as in Fortran70 (it must be greeter than 3) + +object_description = context.getDescription('') +word_list = object_description.split() + +object_flat_description = ' '.join(word_list) +if len(object_flat_description) <= object_truncated_description_length: + return object_flat_description + +# object_truncated_description = object_flat_description[:object_truncated_description_length - 3] + '...' +object_truncated_description = '' +for word in word_list: + if len(object_truncated_description) + len(word) + 4 <= object_truncated_description_length: + object_truncated_description += word + ' ' + else: + last_word = word + break +truncated_last_word = last_word[:object_truncated_description_length - len(object_truncated_description) - 3] +if truncated_last_word != last_word: + object_truncated_description += truncated_last_word +object_truncated_description += '...' +return object_truncated_description diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getTruncatedDescription.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getTruncatedDescription.xml new file mode 100644 index 0000000000000000000000000000000000000000..1f05989f7e7fc3f0c4275dd68a47e792554555d7 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/Base_getTruncatedDescription.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + + + + id + Base_getTruncatedDescription + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_buildItems.py b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_buildItems.py new file mode 100644 index 0000000000000000000000000000000000000000..782366722de1d0da08d60b6a4d049421f755888c --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_buildItems.py @@ -0,0 +1,7 @@ +site = context.getPortalObject() + +commit_item_list = context.objectValues() + +for item in commit_item_list: + if site.portal_workflow.isTransitionPossible(item, 'build'): + site.portal_workflow.doActionFor(item, 'build_action') diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_buildItems.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_buildItems.xml new file mode 100644 index 0000000000000000000000000000000000000000..deb5f883c02e2eda3740fa904e9be823bc6d361d --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_buildItems.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + + + + id + BusinessCommit_buildItems + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_getLastCommitTitle.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_getLastCommitTitle.xml new file mode 100644 index 0000000000000000000000000000000000000000..818ee4ab74d1faccc7274b1cc6ba9eb786324d98 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_getLastCommitTitle.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _function + getLatestCommitTitle + + + _module + CommitUtils + + + id + BusinessCommit_getLastCommitTitle + + + title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_install.py b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_install.py new file mode 100644 index 0000000000000000000000000000000000000000..fb1d7d2da8a8ea1032b936d80d067b073e3120c1 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_install.py @@ -0,0 +1,3 @@ +commit = context + +commit.install() diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_install.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_install.xml new file mode 100644 index 0000000000000000000000000000000000000000..e8888da4b0d42255094ce3d13fcd4c4a9e5de9d0 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_install.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + + + + id + BusinessCommit_install + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e6ca18e8c544e30b7d1902535983693cda1ce43 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view.xml @@ -0,0 +1,145 @@ + + + + + + + + + + _objects + + + + + + action + Base_edit + + + description + + + + edit_order + + + + + + encoding + UTF-8 + + + enctype + + + + group_list + + + left + right + center + bottom + hidden + + + + + groups + + + + bottom + + + listbox + + + + + center + + + my_description + + + + + hidden + + + listbox_follow_up_title_list + + + + + left + + + my_id + my_predecessor_id + my_authors + my_subject + + + + + right + + + my_portal_type + my_creation_date + my_modification_date + my_translated_validation_state_title + + + + + + + + id + BusinessCommit_view + + + method + POST + + + name + BusinessCommit_view + + + pt + form_view + + + row_length + 4 + + + stored_encoding + UTF-8 + + + title + Business Commit Definition + + + unicode_mode + 0 + + + update_action + + + + update_action_title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/listbox.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/listbox.xml new file mode 100644 index 0000000000000000000000000000000000000000..3312e42efb815722e0c94c62dd615d2d97b71807 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/listbox.xml @@ -0,0 +1,163 @@ + + + + + + + + + + delegated_list + + + columns + lines + list_method + search + selection_name + sort + title + + + + + id + listbox + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + columns + + + + id + UUID + + + predecessor_id + Reference Item + + + translated_validation_state_title + State + + + modification_date + Modification Date + + + item_path + Path + + + follow_up_title_list + Business Templates + + + + + + field_id + my_view_mode_listbox + + + form_id + Base_viewFieldLibrary + + + lines + 40 + + + list_method + + AAAAAAAAAAI= + + + + search + 1 + + + selection_name + business_manager_view_selection + + + sort + + + + modification_date + Modification Date + + + + + + title + Items + + + + + + + + + + + + + + + method_name + searchFolder + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/listbox_follow_up_title_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/listbox_follow_up_title_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa520a1fee15bd28bef48a0e2d1757128ac9ef9f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/listbox_follow_up_title_list.xml @@ -0,0 +1,287 @@ + + + + + + + + + + id + listbox_follow_up_title_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + AAAAAAAAAAI= + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + listbox_follow_up_title_list + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + + + + + + + + _text + python: \', \'.join(cell.getFollowUpTitleList()) + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_authors.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_authors.xml new file mode 100644 index 0000000000000000000000000000000000000000..cf23e261994d4fe703fa3507881cfb51834e73c0 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_authors.xml @@ -0,0 +1,287 @@ + + + + + + + + + + id + my_authors + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + AAAAAAAAAAI= + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Contributors + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + + + + + + + + _text + python: here.getValidationState() == "draft" + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_creation_date.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_creation_date.xml new file mode 100644 index 0000000000000000000000000000000000000000..b453039ec487e20f7c27bc55bcee17198fd02eaa --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_creation_date.xml @@ -0,0 +1,89 @@ + + + + + + + + + + delegated_list + + + editable + title + + + + + id + my_creation_date + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + editable + 0 + + + field_id + my_date_time_field + + + form_id + Base_viewFieldLibrary + + + title + Creation Date + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_description.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_description.xml new file mode 100644 index 0000000000000000000000000000000000000000..be6c670dec4ac1825b6ae5f40eb1281aa0a08051 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_description.xml @@ -0,0 +1,103 @@ + + + + + + + + + + delegated_list + + + editable + + + + + id + my_description + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + editable + + AAAAAAAAAAI= + + + + field_id + + + + form_id + + + + + + + values + + + + editable + 1 + + + field_id + my_view_mode_description + + + form_id + Base_viewFieldLibrary + + + + + + + + + + + + + + + _text + python: here.getValidationState() == "draft" + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_id.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_id.xml new file mode 100644 index 0000000000000000000000000000000000000000..4deb2c7f0366caeb4afa055214609edfa908e7ec --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_id.xml @@ -0,0 +1,264 @@ + + + + + + + + + + id + my_id + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + Identification + + + display_maxwidth + + + + display_width + 30 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 1 + + + title + UUID + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_modification_date.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_modification_date.xml new file mode 100644 index 0000000000000000000000000000000000000000..d4173e8eb28ad3f4abaa62a84c2d11c39a897584 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_modification_date.xml @@ -0,0 +1,89 @@ + + + + + + + + + + delegated_list + + + editable + title + + + + + id + my_modification_date + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + editable + 0 + + + field_id + my_date_time_field + + + form_id + Base_viewFieldLibrary + + + title + Modification Date + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_portal_type.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_portal_type.xml new file mode 100644 index 0000000000000000000000000000000000000000..70ec596f18669e71dede72bf38b52eacf0cc4e75 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_portal_type.xml @@ -0,0 +1,272 @@ + + + + + + + + + + id + my_portal_type + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Type + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_predecessor_id.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_predecessor_id.xml new file mode 100644 index 0000000000000000000000000000000000000000..629b2a2ebddf54829c9fc8d8843b48675098cccd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_predecessor_id.xml @@ -0,0 +1,216 @@ + + + + + + + + + + delegated_list + + + allow_creation + base_category + catalog_index + columns + editable + first_item + parameter_list + portal_type + title + + + + + id + my_predecessor_id + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + base_category + + + + catalog_index + + + + columns + + + + editable + + AAAAAAAAAAI= + + + + field_id + + + + first_item + + + + form_id + + + + parameter_list + + + + portal_type + + + + title + + + + + + + values + + + + allow_creation + 0 + + + base_category + predecessor + + + catalog_index + id + + + columns + + + + id + UUID + + + predecessor_id + Predecessor + + + translated_validation_state_title + State + + + modification_date + Modification Date + + + description + Description + + + authors + Contributors + + + subject + Project + + + + + + editable + 1 + + + field_id + my_relation_field + + + first_item + 1 + + + form_id + Base_viewFieldLibrary + + + parameter_list + + + + validation_state + NOT draft AND NOT deleted + + + + + + portal_type + + + + Business Commit + Business Commit + + + + + + title + Predecessor + + + + + + + + + + + + + + + _text + python: here.getValidationState() == "draft" + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_subject.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_subject.xml new file mode 100644 index 0000000000000000000000000000000000000000..bae582ca1fd37c23cfbc87667021334011d1482f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_subject.xml @@ -0,0 +1,287 @@ + + + + + + + + + + id + my_subject + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + AAAAAAAAAAI= + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Project + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + + + + + + + + _text + python: here.getValidationState() == "draft" + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_translated_validation_state_title.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_translated_validation_state_title.xml new file mode 100644 index 0000000000000000000000000000000000000000..c0cc8eb8b25d05afeb7b2b87ec4c559c39648522 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessCommit_view/my_translated_validation_state_title.xml @@ -0,0 +1,272 @@ + + + + + + + + + + id + my_translated_validation_state_title + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + Draft, Pushed, Committed + + + display_maxwidth + + + + display_width + 20 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Validation State + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_getObjectViewUrl.py b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_getObjectViewUrl.py new file mode 100644 index 0000000000000000000000000000000000000000..476087ce39ba9490159a831de16524fdcee1e0b3 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_getObjectViewUrl.py @@ -0,0 +1,3 @@ +url = context.id +view_url = url+'/view' +return view_url diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_getObjectViewUrl.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_getObjectViewUrl.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3fbde43288be6cf65b410fe8142c21fc63afbae --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_getObjectViewUrl.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + **kw + + + id + BusinessItem_getObjectViewUrl + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_redirectToZODBPath.py b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_redirectToZODBPath.py new file mode 100644 index 0000000000000000000000000000000000000000..4c800f4ea6b07b8486f850ed86945526398017f0 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_redirectToZODBPath.py @@ -0,0 +1,3 @@ +item_path = context.getProperty('item_path') + +return context.Base_redirect('%s/view' % item_path) diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_redirectToZODBPath.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_redirectToZODBPath.xml new file mode 100644 index 0000000000000000000000000000000000000000..b37f5bbd6cc81903d7c2696f7d1b2938b21c2185 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_redirectToZODBPath.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + + + + id + BusinessItem_redirectToZODBPath + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..a3d76b99b28c6b4fa59e2b969f48bae08daed699 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view.xml @@ -0,0 +1,140 @@ + + + + + + + + + + _objects + + + + + + action + Base_edit + + + description + + + + edit_order + + + + + + encoding + UTF-8 + + + enctype + + + + group_list + + + left + right + center + bottom + hidden + + + + + groups + + + + bottom + + + + + + center + + + + + + hidden + + + + + + left + + + my_id + my_item_path + my_follow_up_title_list + my_predecessor_id + my_item_patch_behaviour + + + + + right + + + my_portal_type + my_creation_date + my_modification_date + my_translated_validation_state_title + + + + + + + + id + BusinessItem_view + + + method + POST + + + name + BusinessItem_view + + + pt + form_view + + + row_length + 4 + + + stored_encoding + UTF-8 + + + title + Business Item Definition + + + unicode_mode + 0 + + + update_action + + + + update_action_title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_creation_date.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_creation_date.xml new file mode 100644 index 0000000000000000000000000000000000000000..b453039ec487e20f7c27bc55bcee17198fd02eaa --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_creation_date.xml @@ -0,0 +1,89 @@ + + + + + + + + + + delegated_list + + + editable + title + + + + + id + my_creation_date + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + editable + 0 + + + field_id + my_date_time_field + + + form_id + Base_viewFieldLibrary + + + title + Creation Date + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_follow_up_title_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_follow_up_title_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..c10489a06cdc8c4f3894556dc5217bca6fb4c3f0 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_follow_up_title_list.xml @@ -0,0 +1,165 @@ + + + + + + + + + + delegated_list + + + columns + editable + portal_type + required + title + + + + + id + my_follow_up_title_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + target + + + + + + + tales + + + + editable + + AAAAAAAAAAI= + + + + field_id + + + + form_id + + + + portal_type + + + + required + + + + target + + + + title + + + + + + + values + + + + columns + + + + title + Title + + + description + Description + + + + + + editable + 1 + + + field_id + my_view_mode_follow_up_title_list + + + form_id + Base_viewDMSFieldLibrary + + + portal_type + + + + Business Template V2 + Business Template + + + + + + required + 1 + + + target + Click to edit the target + + + title + Business Templates + + + + + + + + + + + + + + + _text + python: here.getValidationState() == "draft" or here.getValidationState() == "built" + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_id.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_id.xml new file mode 100644 index 0000000000000000000000000000000000000000..4deb2c7f0366caeb4afa055214609edfa908e7ec --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_id.xml @@ -0,0 +1,264 @@ + + + + + + + + + + id + my_id + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + Identification + + + display_maxwidth + + + + display_width + 30 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 1 + + + title + UUID + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_item_patch_behaviour.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_item_patch_behaviour.xml new file mode 100644 index 0000000000000000000000000000000000000000..7dd397537119cafebe742a018773083d9fa2bd81 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_item_patch_behaviour.xml @@ -0,0 +1,207 @@ + + + + + + + + + + delegated_list + + + default + editable + enabled + items + required + title + + + + + id + my_item_patch_behaviour + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + target + + + + + + + tales + + + + default + + + + editable + + AAAAAAAAAAI= + + + + enabled + + AAAAAAAAAAM= + + + + field_id + + + + form_id + + + + items + + AAAAAAAAAAQ= + + + + required + + AAAAAAAAAAU= + + + + target + + + + title + + + + + + + values + + + + default + + + + editable + 1 + + + enabled + 0 + + + field_id + my_view_mode_classification + + + form_id + Base_viewDMSFieldLibrary + + + items + + + + + + required + 0 + + + target + Click to edit the target + + + title + Patch Behaviour + + + + + + + + + + + + + + + _text + python: here.getPredecessorId() and (here.getValidationState() == "draft" or here.getValidationState() == "built") + + + + + + + + + + + + _text + python: here.getPredecessorId() + + + + + + + + + + + + _text + python: (getattr(here.portal_categories[field.getId().replace(\'my_\', \'\', 1)], preferences.getPreference(\'preferred_category_child_item_list_method_id\', \'getCategoryChildCompactLogicalPathItemList\'))(local_sort_id=(\'int_index\', \'translated_title\'), checked_permission=\'View\'))[1:] + + + + + + + + + + + + _text + python: here.getPredecessorId() + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_item_path.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_item_path.xml new file mode 100644 index 0000000000000000000000000000000000000000..05dc20c506742de361c59fc945a41fe3ed37f4ec --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_item_path.xml @@ -0,0 +1,287 @@ + + + + + + + + + + id + my_item_path + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + AAAAAAAAAAI= + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + portal_ + + + description + + + + display_maxwidth + + + + display_width + 1000 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 1 + + + title + Path + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + + + + + + + + _text + python: not here.getPredecessorId() and (here.getValidationState() == "draft" or here.getValidationState() == "built") + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_modification_date.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_modification_date.xml new file mode 100644 index 0000000000000000000000000000000000000000..d4173e8eb28ad3f4abaa62a84c2d11c39a897584 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_modification_date.xml @@ -0,0 +1,89 @@ + + + + + + + + + + delegated_list + + + editable + title + + + + + id + my_modification_date + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + editable + 0 + + + field_id + my_date_time_field + + + form_id + Base_viewFieldLibrary + + + title + Modification Date + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_portal_type.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_portal_type.xml new file mode 100644 index 0000000000000000000000000000000000000000..70ec596f18669e71dede72bf38b52eacf0cc4e75 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_portal_type.xml @@ -0,0 +1,272 @@ + + + + + + + + + + id + my_portal_type + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Type + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_predecessor_id.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_predecessor_id.xml new file mode 100644 index 0000000000000000000000000000000000000000..71bca184e275ff20f0b9a1159ed771e9a2c99353 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_predecessor_id.xml @@ -0,0 +1,212 @@ + + + + + + + + + + delegated_list + + + allow_creation + base_category + catalog_index + columns + editable + first_item + parameter_list + portal_type + title + + + + + id + my_predecessor_id + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + base_category + + + + catalog_index + + + + columns + + + + editable + + AAAAAAAAAAI= + + + + field_id + + + + first_item + + + + form_id + + + + parameter_list + + + + portal_type + + + + title + + + + + + + values + + + + allow_creation + 0 + + + base_category + predecessor + + + catalog_index + id + + + columns + + + + id + UUID + + + predecessor_id + Reference Item + + + modification_date + Modification Date + + + item_path + Path + + + follow_up_title_list + Business Templates + + + parent_id + Related Commit + + + + + + editable + 1 + + + field_id + my_relation_field + + + first_item + 1 + + + form_id + Base_viewFieldLibrary + + + parameter_list + + + + validation_state + validated + + + + + + portal_type + + + + Business Item + Business Item + + + + + + title + Reference Item + + + + + + + + + + + + + + + _text + python: here.getValidationState() == "draft" or here.getValidationState() == "built" + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_translated_validation_state_title.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_translated_validation_state_title.xml new file mode 100644 index 0000000000000000000000000000000000000000..c0cc8eb8b25d05afeb7b2b87ec4c559c39648522 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessItem_view/my_translated_validation_state_title.xml @@ -0,0 +1,272 @@ + + + + + + + + + + id + my_translated_validation_state_title + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + Draft, Pushed, Committed + + + display_maxwidth + + + + display_width + 20 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Validation State + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..793320e533f99500ecd5d9fe4fb2d223ba794d4d --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view.xml @@ -0,0 +1,141 @@ + + + + + + + + + + _objects + + + + + + action + Base_edit + + + description + + + + edit_order + + + + + + encoding + UTF-8 + + + enctype + + + + group_list + + + left + right + center + bottom + hidden + + + + + groups + + + + bottom + + + + + + center + + + my_description + + + + + hidden + + + listbox + + + + + left + + + my_id + my_predecessor_id + + + + + right + + + my_portal_type + my_creation_date + my_modification_date + my_translated_validation_state_title + + + + + + + + id + BusinessSnapshot_view + + + method + POST + + + name + BusinessSnapshot_view + + + pt + form_view + + + row_length + 4 + + + stored_encoding + UTF-8 + + + title + Business Snapshot Definition + + + unicode_mode + 0 + + + update_action + + + + update_action_title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/listbox.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/listbox.xml new file mode 100644 index 0000000000000000000000000000000000000000..0f06e09e4a8374fe585401e663928ce776dacf4e --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/listbox.xml @@ -0,0 +1,138 @@ + + + + + + + + + + delegated_list + + + columns + lines + list_method + selection_name + sort + title + + + + + id + listbox + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + columns + + + + item_path + Path + + + + + + field_id + my_view_mode_listbox + + + form_id + Base_viewFieldLibrary + + + lines + 40 + + + list_method + + AAAAAAAAAAI= + + + + selection_name + business_manager_view_selection + + + sort + + + + item_path + Path + + + + + + title + Items + + + + + + + + + + + + + + + method_name + objectValues + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_creation_date.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_creation_date.xml new file mode 100644 index 0000000000000000000000000000000000000000..b453039ec487e20f7c27bc55bcee17198fd02eaa --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_creation_date.xml @@ -0,0 +1,89 @@ + + + + + + + + + + delegated_list + + + editable + title + + + + + id + my_creation_date + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + editable + 0 + + + field_id + my_date_time_field + + + form_id + Base_viewFieldLibrary + + + title + Creation Date + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_description.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_description.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d173a2447e3e25703aa04960fedeff0f0f47a79 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_description.xml @@ -0,0 +1,103 @@ + + + + + + + + + + delegated_list + + + editable + + + + + id + my_description + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + editable + + AAAAAAAAAAI= + + + + field_id + + + + form_id + + + + + + + values + + + + editable + 0 + + + field_id + my_view_mode_description + + + form_id + Base_viewFieldLibrary + + + + + + + + + + + + + + + _text + python: here.getValidationState() == "draft" + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_id.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_id.xml new file mode 100644 index 0000000000000000000000000000000000000000..4deb2c7f0366caeb4afa055214609edfa908e7ec --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_id.xml @@ -0,0 +1,264 @@ + + + + + + + + + + id + my_id + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + Identification + + + display_maxwidth + + + + display_width + 30 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 1 + + + title + UUID + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_modification_date.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_modification_date.xml new file mode 100644 index 0000000000000000000000000000000000000000..d4173e8eb28ad3f4abaa62a84c2d11c39a897584 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_modification_date.xml @@ -0,0 +1,89 @@ + + + + + + + + + + delegated_list + + + editable + title + + + + + id + my_modification_date + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + editable + 0 + + + field_id + my_date_time_field + + + form_id + Base_viewFieldLibrary + + + title + Modification Date + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_portal_type.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_portal_type.xml new file mode 100644 index 0000000000000000000000000000000000000000..70ec596f18669e71dede72bf38b52eacf0cc4e75 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_portal_type.xml @@ -0,0 +1,272 @@ + + + + + + + + + + id + my_portal_type + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Type + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_predecessor_id.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_predecessor_id.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b8040ee69665c6b94f5dfe0386c299294746775 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_predecessor_id.xml @@ -0,0 +1,213 @@ + + + + + + + + + + delegated_list + + + allow_creation + base_category + catalog_index + columns + editable + first_item + parameter_list + portal_type + required + title + + + + + id + my_predecessor_id + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + base_category + + + + catalog_index + + + + editable + + AAAAAAAAAAI= + + + + field_id + + + + first_item + + + + form_id + + + + portal_type + + + + title + + + + + + + values + + + + allow_creation + 0 + + + base_category + predecessor + + + catalog_index + id + + + columns + + + + id + UUID + + + predecessor_id + Predecessor + + + translated_validation_state_title + State + + + modification_date + Modification Date + + + description + Description + + + authors + Contributors + + + subject + Project + + + + + + editable + 1 + + + field_id + my_relation_field + + + first_item + 1 + + + form_id + Base_viewFieldLibrary + + + parameter_list + + + + validation_state + NOT draft AND NOT deleted + + + + + + portal_type + + + + Business Commit + Business Commit + + + + + + required + 1 + + + title + Equivalent Commit + + + + + + + + + + + + + + + _text + python: here.getValidationState() == "draft" + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_translated_validation_state_title.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_translated_validation_state_title.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4bfced8ba8ba753fe1fabc13d9dab1633d0cb10 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessSnapshot_view/my_translated_validation_state_title.xml @@ -0,0 +1,272 @@ + + + + + + + + + + id + my_translated_validation_state_title + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + Draft, Built, Committed, Pushed + + + display_maxwidth + + + + display_width + 20 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Validation State + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..34e7b2cae4e3d42253a0f13a407ba3aa97e140c9 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view.xml @@ -0,0 +1,147 @@ + + + + + + + + + + _objects + + + + + + action + Base_edit + + + description + + + + edit_order + + + + + + encoding + UTF-8 + + + enctype + + + + group_list + + + left + right + center + bottom + hidden + + + + + groups + + + + bottom + + + my_item_path_list + + + + + center + + + + + + hidden + + + my_id + my_provision_list + my_version + my_translated_availability_state_title + my_change_log + + + + + left + + + my_title + my_description + my_comment + + + + + right + + + my_dependency_list + my_test_dependency_list + my_copyright_list + my_license + my_maintainer_list + + + + + + + + id + BusinessTemplateV2_view + + + method + POST + + + name + BusinessTemplateV2_view + + + pt + form_view + + + row_length + 4 + + + stored_encoding + UTF-8 + + + title + Business Template V2 Definition + + + unicode_mode + 0 + + + update_action + + + + update_action_title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_change_log.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_change_log.xml new file mode 100644 index 0000000000000000000000000000000000000000..2ac7cf11224d6dc3a48911f70a28fe3bc389c12d --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_change_log.xml @@ -0,0 +1,280 @@ + + + + + + + + + + id + my_change_log + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + line_too_long + A line was too long. + + + required_not_found + Input is required but no input given. + + + too_long + You entered too many characters. + + + too_many_lines + You entered too many lines. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + whitespace_preserve + + + + width + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + whitespace_preserve + + + + width + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + A list of changes done on the document + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + height + 8 + + + hidden + 0 + + + max_length + + + + max_linelength + + + + max_lines + + + + required + 0 + + + title + Change Log + + + unicode + 0 + + + whitespace_preserve + 0 + + + width + 40 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_comment.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_comment.xml new file mode 100644 index 0000000000000000000000000000000000000000..d38560271476d04907d0052a96d861f613d41192 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_comment.xml @@ -0,0 +1,280 @@ + + + + + + + + + + id + my_comment + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + line_too_long + A line was too long. + + + required_not_found + Input is required but no input given. + + + too_long + You entered too many characters. + + + too_many_lines + You entered too many lines. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + whitespace_preserve + + + + width + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + whitespace_preserve + + + + width + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + Comments which can be read by internal users but unlike description, are not printed out on official documents. + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + height + 6 + + + hidden + 0 + + + max_length + + + + max_linelength + + + + max_lines + + + + required + 0 + + + title + Comments + + + unicode + 0 + + + whitespace_preserve + 1 + + + width + 40 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_copyright_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_copyright_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..8d2b0182e5f875d83f1a7913635c072ce3cfdedb --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_copyright_list.xml @@ -0,0 +1,298 @@ + + + + + + + + + + id + my_copyright_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + line_too_long + A line was too long. + + + required_not_found + Input is required but no input given. + + + too_long + You entered too many characters. + + + too_many_lines + You entered too many lines. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + + + description + + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + height + 2 + + + hidden + 0 + + + max_length + + + + max_linelength + + + + max_lines + + + + required + 0 + + + title + Copyright + + + unicode + 0 + + + view_separator + + +]]> + + + whitespace_preserve + 0 + + + width + 40 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_dependency_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_dependency_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..7241712f1ef30cbf5a6c3a4fd6cbb69fe6a55c41 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_dependency_list.xml @@ -0,0 +1,298 @@ + + + + + + + + + + id + my_dependency_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + line_too_long + A line was too long. + + + required_not_found + Input is required but no input given. + + + too_long + You entered too many characters. + + + too_many_lines + You entered too many lines. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + + + description + + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + height + 3 + + + hidden + 0 + + + max_length + + + + max_linelength + + + + max_lines + + + + required + 0 + + + title + Dependencies + + + unicode + 0 + + + view_separator + + +]]> + + + whitespace_preserve + 0 + + + width + 40 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_description.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_description.xml new file mode 100644 index 0000000000000000000000000000000000000000..64596a36d4d32098b320a93896d87c19ddae676b --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_description.xml @@ -0,0 +1,280 @@ + + + + + + + + + + id + my_description + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + line_too_long + A line was too long. + + + required_not_found + Input is required but no input given. + + + too_long + You entered too many characters. + + + too_many_lines + You entered too many lines. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + whitespace_preserve + + + + width + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + whitespace_preserve + + + + width + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + General description of a document in ERP5. Descriptions are not supposed to be internal, and in a case of certain documents such as invoices for example, will be seen by your customers. + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + height + 4 + + + hidden + 0 + + + max_length + + + + max_linelength + + + + max_lines + + + + required + 0 + + + title + Description + + + unicode + 0 + + + whitespace_preserve + 1 + + + width + 40 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_id.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_id.xml new file mode 100644 index 0000000000000000000000000000000000000000..05966633b56823a1a3da65714da3f29b08f475ba --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_id.xml @@ -0,0 +1,260 @@ + + + + + + + + + + id + my_id + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + Identification + + + display_maxwidth + + + + display_width + 30 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + max_length + + + + required + 1 + + + title + ID + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_item_path_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_item_path_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..78d733c1436b67b2c911364cfda9e05084abd648 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_item_path_list.xml @@ -0,0 +1,94 @@ + + + + + + + + + + delegated_list + + + height + title + width + + + + + id + my_item_path_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + field_id + my_lines_field + + + form_id + Base_viewFieldLibrary + + + height + 10 + + + title + Path List + + + width + 80 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_license.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_license.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa45fd689480e5bd070dcdae3d2351f8000214c9 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_license.xml @@ -0,0 +1,260 @@ + + + + + + + + + + id + my_license + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + max_length + + + + required + 0 + + + title + License + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_maintainer_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_maintainer_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ec5300955497250f409d1d14a0516532bac8606 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_maintainer_list.xml @@ -0,0 +1,298 @@ + + + + + + + + + + id + my_maintainer_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + line_too_long + A line was too long. + + + required_not_found + Input is required but no input given. + + + too_long + You entered too many characters. + + + too_many_lines + You entered too many lines. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + + + description + + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + height + 2 + + + hidden + 0 + + + max_length + + + + max_linelength + + + + max_lines + + + + required + 0 + + + title + Maintainers + + + unicode + 0 + + + view_separator + + +]]> + + + whitespace_preserve + 0 + + + width + 20 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_provision_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_provision_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..89f0a38d4c0d0855a8211746ffa36ecdf7c0b5a2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_provision_list.xml @@ -0,0 +1,298 @@ + + + + + + + + + + id + my_provision_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + line_too_long + A line was too long. + + + required_not_found + Input is required but no input given. + + + too_long + You entered too many characters. + + + too_many_lines + You entered too many lines. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + + + description + + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + height + 3 + + + hidden + 0 + + + max_length + + + + max_linelength + + + + max_lines + + + + required + 0 + + + title + Provision + + + unicode + 0 + + + view_separator + + +]]> + + + whitespace_preserve + 0 + + + width + 40 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_test_dependency_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_test_dependency_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..85addd242ef0c8e47496dfaaef0beba8f696b192 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_test_dependency_list.xml @@ -0,0 +1,298 @@ + + + + + + + + + + id + my_test_dependency_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + line_too_long + A line was too long. + + + required_not_found + Input is required but no input given. + + + too_long + You entered too many characters. + + + too_many_lines + You entered too many lines. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + height + + + + hidden + + + + max_length + + + + max_linelength + + + + max_lines + + + + required + + + + title + + + + unicode + + + + view_separator + + + + whitespace_preserve + + + + width + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + + + description + + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + height + 3 + + + hidden + 0 + + + max_length + + + + max_linelength + + + + max_lines + + + + required + 0 + + + title + Tests Dependencies + + + unicode + 0 + + + view_separator + + +]]> + + + whitespace_preserve + 0 + + + width + 40 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_title.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_title.xml new file mode 100644 index 0000000000000000000000000000000000000000..b2b86ecfcbbe895352d1c583f249ed54363eb08a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_title.xml @@ -0,0 +1,264 @@ + + + + + + + + + + id + my_title + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + The name of the business template, must not change between revision as this is the property used to retrieve old one when upgrading + + + display_maxwidth + + + + display_width + 30 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 1 + + + title + Title + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_translated_availability_state_title.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_translated_availability_state_title.xml new file mode 100644 index 0000000000000000000000000000000000000000..bee42ab921463c09f66c5ac3236d6aa500a4569a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_translated_availability_state_title.xml @@ -0,0 +1,272 @@ + + + + + + + + + + id + my_translated_availability_state_title + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 0 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + Availability State + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_version.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_version.xml new file mode 100644 index 0000000000000000000000000000000000000000..6c8cab9687b2c835707b2438306934870962f978 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/BusinessTemplateV2_view/my_version.xml @@ -0,0 +1,260 @@ + + + + + + + + + + id + my_version + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + The Version of the Business Template + + + display_maxwidth + + + + display_width + 20 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + max_length + + + + required + 0 + + + title + Version + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_createSnapshot.py b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_createSnapshot.py new file mode 100644 index 0000000000000000000000000000000000000000..9bf4b7e367782bec0496ed6c71fc3c6c35467142 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_createSnapshot.py @@ -0,0 +1,11 @@ +# Check if the conext is Commit Tool +if context.getPortalType() != 'Commit Tool': + return 'context is not commit tool' + +# Get the HEAD commit and create a snapshot based on it +head_commit = context.getHeadCommit() + +# Create a new snapshot based on HEAD commit +snapshot = head_commit.createEquivalentSnapshot() + +return context.Base_redirect('view') diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_createSnapshot.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_createSnapshot.xml new file mode 100644 index 0000000000000000000000000000000000000000..90b360682eab7ab71d1c3507758d00df5d848d68 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_createSnapshot.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + **kw + + + id + CommitTool_createSnapshot + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList.xml new file mode 100644 index 0000000000000000000000000000000000000000..782f49eebc3a03c600b9e2f2bdcf0bdb1c57ff03 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList.xml @@ -0,0 +1,135 @@ + + + + + + + + + + _objects + + + + + + action + + + + description + + + + edit_order + + + + + + encoding + UTF-8 + + + enctype + + + + group_list + + + left + right + center + bottom + hidden + + + + + groups + + + + bottom + + + listbox + + + + + center + + + + + + hidden + + + listbox_path_list + listbox_description + listbox_business_template_title_list + + + + + left + + + + + + right + + + + + + + + + id + CommitTool_viewCommitList + + + method + POST + + + name + CommitTool_viewCommitList + + + pt + form_list + + + row_length + 4 + + + stored_encoding + UTF-8 + + + title + Commits + + + unicode_mode + 0 + + + update_action + + + + update_action_title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox.xml new file mode 100644 index 0000000000000000000000000000000000000000..934a035ff9da4486c5e104ca671b99283958df5a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox.xml @@ -0,0 +1,209 @@ + + + + + + + + + + delegated_list + + + all_columns + columns + hide_rows_on_no_search_criterion + lines + list_method + search + select + selection_name + sort + title + + + + + id + listbox + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + field_id + + + + form_id + + + + + + + values + + + + all_columns + + + + authors + Contributors + + + subject + Project + + + creation_date + Creation Date + + + business_template_title_list + Business Templates + + + path_list + Paths + + + + + + columns + + + + portal_type + Type + + + id + UUID + + + predecessor_id + Predecessor / Equivalent Commit + + + translated_validation_state_title + State + + + modification_date + Modification Date + + + description + Description + + + + + + field_id + my_view_mode_listbox + + + form_id + Base_viewFieldLibrary + + + hide_rows_on_no_search_criterion + 0 + + + lines + 100 + + + list_method + + AAAAAAAAAAI= + + + + search + 1 + + + select + 1 + + + selection_name + commit_tool_selection + + + sort + + + + portal_type + Type + + + creation_date + Creation Date + + + + + + title + + + + + + + + + + + + + + + + method_name + searchFolder + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_business_template_title_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_business_template_title_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..c63b1fb96993e9c9e8b9cecf55329dc7ede65bc9 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_business_template_title_list.xml @@ -0,0 +1,287 @@ + + + + + + + + + + id + listbox_business_template_title_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + AAAAAAAAAAI= + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + listbox_business_template_title_list + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + + + + + + + + _text + python: \', \'.join(list(set([template for sublist in [item.getFollowUpTitleList() for item in cell.objectValues() if cell.getPortalType() == \'Business Commit\'] for template in sublist]))) + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_description.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_description.xml new file mode 100644 index 0000000000000000000000000000000000000000..01ddd0e2f23abc597f9c0f4ab16119d221012b66 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_description.xml @@ -0,0 +1,287 @@ + + + + + + + + + + id + listbox_description + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + required_not_found + Input is required but no input given. + + + too_long + Too much input was given. + + + + + + overrides + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + tales + + + + alternate_name + + + + css_class + + + + default + + AAAAAAAAAAI= + + + + description + + + + display_maxwidth + + + + display_width + + + + editable + + + + enabled + + + + external_validator + + + + extra + + + + hidden + + + + input_type + + + + max_length + + + + required + + + + title + + + + truncate + + + + unicode + + + + whitespace_preserve + + + + + + + values + + + + alternate_name + + + + css_class + + + + default + + + + description + + + + display_maxwidth + + + + display_width + 20 + + + editable + 1 + + + enabled + 1 + + + external_validator + + + + extra + + + + hidden + 0 + + + input_type + text + + + max_length + + + + required + 0 + + + title + listbox_description + + + truncate + 0 + + + unicode + 0 + + + whitespace_preserve + 0 + + + + + + + + + + + + + + + _text + python: cell.Base_getTruncatedDescription() + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_path_list.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_path_list.xml new file mode 100644 index 0000000000000000000000000000000000000000..293ebcde316d0a439f2e5a66e4c910a5e7305fc7 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/CommitTool_viewCommitList/listbox_path_list.xml @@ -0,0 +1,114 @@ + + + + + + + + + + delegated_list + + + default + title + + + + + id + listbox_path_list + + + message_values + + + + external_validator_failed + The input failed the external validator. + + + + + + overrides + + + + field_id + + + + form_id + + + + + + + tales + + + + default + + AAAAAAAAAAI= + + + + field_id + + + + form_id + + + + title + + + + + + + values + + + + default + + + + + + field_id + my_lines_field + + + form_id + Base_viewFieldLibrary + + + title + listbox_path_list + + + + + + + + + + + + + + + _text + python: \'\\n \'.join(list(set([item.getItemPath() for item in cell.objectValues() if cell.getPortalType() == \'Business Commit\']))) + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.css.css b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.css.css new file mode 100644 index 0000000000000000000000000000000000000000..7e5f3b6fbf52031582291510981f530ea336ac2a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.css.css @@ -0,0 +1,6 @@ +pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; } +.string { color: green; } +.number { color: darkorange; } +.boolean { color: blue; } +.null { color: magenta; } +.key { color: red; } \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.css.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.css.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb37083f761e00866d1e968aea148853d012f1a4 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.css.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + business_patch_item_view_diff_gadget.css + + + content_type + text/css + + + precondition + + + + title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.html.html b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.html.html new file mode 100644 index 0000000000000000000000000000000000000000..f73d15d35678c6615ba6acfb255c908b2fb35f82 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.html.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.html.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.html.xml new file mode 100644 index 0000000000000000000000000000000000000000..87d02b1cd258d752130c0b0c540fcd1b93d8d0aa --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.html.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + business_patch_item_view_diff_gadget.html + + + content_type + text/html + + + precondition + + + + title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.js.js b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.js.js new file mode 100644 index 0000000000000000000000000000000000000000..44ed5400c18206fc8ae6410c4664e190d9001a26 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.js.js @@ -0,0 +1,39 @@ +/*global window, rJS, RSVP, Handlebars, jIO, location, console */ +/*jslint nomen: true, maxlen:80, indent:2*/ +(function (rJS, jIO, Handlebars, RSVP, window) { + "use strict"; + var gk = rJS(window); + + function output(inp) { + document.body.appendChild(document.createElement('pre')).innerHTML = inp; + } + + function syntaxHighlight(json) { + json = json.replace(/&/g, '&').replace(//g, '>'); + return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { + var cls = 'number'; + if (/^"/.test(match)) { + if (/:$/.test(match)) { + cls = 'key'; + } else { + cls = 'string'; + } + } else if (/true|false/.test(match)) { + cls = 'boolean'; + } else if (/null/.test(match)) { + cls = 'null'; + } + return '' + match + ''; + }); + } + + rJS(window) + + .declareMethod('render', function (options) { + var patch = options.value; + console.log(patch); + // this.element.innerHTML = output(patch); + this.element.innerHTML = '
'+syntaxHighlight(JSON.stringify(JSON.parse(patch), undefined, 1))+'
'; + }); + +}(rJS, jIO, Handlebars, RSVP, window)); diff --git a/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.js.xml b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..4b7e2408c8c00a45cddbe378e8fd0d54526e442b --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/SkinTemplateItem/portal_skins/erp5_commit/business_patch_item_view_diff_gadget.js.xml @@ -0,0 +1,28 @@ + + + + + + + + + + __name__ + business_patch_item_view_diff_gadget.js + + + content_type + application/javascript + + + precondition + + + + title + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/TestTemplateItem/portal_components/test.erp5.testPortalPatchItem.py b/product/ERP5/bootstrap/erp5_business_package/TestTemplateItem/portal_components/test.erp5.testPortalPatchItem.py new file mode 100644 index 0000000000000000000000000000000000000000..65848f974943d80f7e4204118669059360887018 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/TestTemplateItem/portal_components/test.erp5.testPortalPatchItem.py @@ -0,0 +1,134 @@ +############################################################################## +# +# Copyright (c) 2002-2017 Nexedi SA and Contributors. All Rights Reserved. +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +############################################################################## + +import time +from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase + +class TestPortalPatch(ERP5TypeTestCase): + """ + Test class to test that Business Package object can export some paths + and install them on an erp5 site + + Steps: + - Create BusinessPackage object + - Add path list to the object + - Build the package and expect the items mentioned in path list gets + exported in the build step + - Remove the objects mentioned in path_list from the site + - Install the package + - Expected result should be that it installs the objects on the site + """ + + def getTitle(self): + return "TestPortalPatch" + + def getBusinessTemplateList(self): + """ + Tuple of Business Templates we need to install + """ + return ( + 'erp5_base', + 'erp5_core', + 'erp5_dms', + 'erp5_property_sheets', + 'erp5_business_package', + ) + + def afterSetUp(self): + """ + This is ran before anything, used to set the environment + """ + # here, you can create the categories and objects your test will depend on + #self.export_dir = tempfile.mkdtmp(dir=tests_home) + self.export_dir = '' + self.portal = self.getPortalObject() + + def beforeTearDown(self): + pass + + def _createBusinessManager(self, sequence=None, bm_id=None, title=None): + if not bm_id: + bm_id = 'manager_%s' % str(time.time()) + if not title: + title = bm_id + manager = self.portal.portal_templates.newContent( + id=bm_id, + title=title, + portal_type='Business Manager') + self.tic() + return manager + + def test_businessPatchItemForWorkflowChain(self): + """ + Test if we are able to use PatchItem for adding Workflow Chain ( priority + doesn't matter ) + """ + portal = self.portal + manager_A = self._createBusinessManager() + manager_A.newContent(portal_type='Business Property Item', + item_path='portal_types/Business Manager#type_workflow_list') + manager_A.build() + + # Change the value for object on ZODB + obj = portal.unrestrictedTraverse('portal_types/Business Manager') + obj.setWorkflowTypeList('type_workflow_list', ['a', 'b', 'c']) + + manager_B = self._createBusinessManager() + + # Create Business Patch Item for the same property_path as we used in + # property_item, and use manager_A as a value in dependency_list + manager_B.newContent(portal_type='Business Patch Item', + path='portal_types/Business Manager#type_workflow_list', + dependency_list=[manager_A,]) + + # Build Business Manager + manager_B.build() + # After build, we expect manager_B to have 2 Business Property Item, one for + # storing new_value(where we do update when we rebuild) and another from + # old_value(which we take from older version of Business Manager) + + # Change the value for object on ZODB to old again + obj.setWorkflowTypeList('type_workflow_list', ['a', 'c']) + + # Get the patch item for the given path + bm_item = manager_B.getBusinessItemByPath( + 'portal_types/Business Manager#type_workflow_list', + patch=True) + + # Get the old and new value + old = bm_item.getOldValue() + new = bm_item.getNewValue() + + # Get Diff Tool + portal_diff = portal.getDiffTool() + # Create patch using the old and new values + patch = portal_diff.diffPortalObject(old, new) + # Get the patch_operation which we have for this patch + patch_operation_list = patch.getPortalPatchOperationList() + for operation in patch_operation_list: + # Select the operation and apply the patch on the object + obj.patch(operation) diff --git a/product/ERP5/bootstrap/erp5_business_package/TestTemplateItem/portal_components/test.erp5.testPortalPatchItem.xml b/product/ERP5/bootstrap/erp5_business_package/TestTemplateItem/portal_components/test.erp5.testPortalPatchItem.xml new file mode 100644 index 0000000000000000000000000000000000000000..9233e5c2538cf9a782c61a4be6ab969a337ffd22 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/TestTemplateItem/portal_components/test.erp5.testPortalPatchItem.xml @@ -0,0 +1,104 @@ + + + + + + + + + + default_reference + testPortalPatchItem + + + description + + + + + + id + test.erp5.testPortalPatchItem + + + portal_type + Test Component + + + sid + + + + + + text_content_error_message + + + + + + text_content_warning_message + + + + + + version + erp5 + + + workflow_history + + AAAAAAAAAAI= + + + + + + + + + + + + + data + + + + component_validation_workflow + + AAAAAAAAAAM= + + + + + + + + + + + + + + + + + + + action + + + + + + validation_state + draft + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/ToolTemplateItem/portal_commits.xml b/product/ERP5/bootstrap/erp5_business_package/ToolTemplateItem/portal_commits.xml new file mode 100644 index 0000000000000000000000000000000000000000..4008d91600baa22cceed5a5809a0ff6094f45b4f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/ToolTemplateItem/portal_commits.xml @@ -0,0 +1,60 @@ + + + + + + + + + + _count + + AAAAAAAAAAI= + + + + _mt_index + + AAAAAAAAAAM= + + + + _tree + + AAAAAAAAAAQ= + + + + head_commit_id + ed17780c-424a-11e8-9b15-0cc47ae46e4c + + + id + portal_commits + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow.xml new file mode 100644 index 0000000000000000000000000000000000000000..d7cbcc97efd57c85b6e375340507e6172fa3e19c --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow.xml @@ -0,0 +1,46 @@ + + + + + + + + + + _objects + + + + + + creation_guard + + + + + + description + + + + groups + + + + + + id + business_commit_interaction_workflow + + + manager_bypass + 0 + + + title + Business Commit Interaction Workflow + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions.xml new file mode 100644 index 0000000000000000000000000000000000000000..e18bf8cbf778a6808aa24ec39bba4b527d7b1bef --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + interactions + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions/BusinessCommit_updateHeadCommitId.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions/BusinessCommit_updateHeadCommitId.xml new file mode 100644 index 0000000000000000000000000000000000000000..e0c27c4007acc57f6691f9cff8fae1d92b9fb15d --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions/BusinessCommit_updateHeadCommitId.xml @@ -0,0 +1,100 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_name + + + + actbox_url + + + + activate_script_name + + + + + + after_script_name + + + + + + before_commit_script_name + + + BusinessCommit_updateHeadCommitId + + + + + description + + + + guard + + + + + + id + BusinessCommit_updateHeadCommitId + + + method_id + + + commit + + + + + once_per_transaction + 0 + + + portal_type_filter + + + + + + portal_type_group_filter + + + + + + script_name + + + + + + temporary_document_disallowed + 0 + + + title + ? + + + trigger_type + 2 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions/BusinessCommit_updateTemplateStatustoAvailable.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions/BusinessCommit_updateTemplateStatustoAvailable.xml new file mode 100644 index 0000000000000000000000000000000000000000..d32ad109753df6f4a83d92a4bc561171d3deb208 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/interactions/BusinessCommit_updateTemplateStatustoAvailable.xml @@ -0,0 +1,100 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_name + + + + actbox_url + + + + activate_script_name + + + + + + after_script_name + + + + + + before_commit_script_name + + + BusinessCommit_updateTemplateStatus + + + + + description + + + + guard + + + + + + id + BusinessCommit_updateTemplateStatustoAvailable + + + method_id + + + commit + + + + + once_per_transaction + 0 + + + portal_type_filter + + + + + + portal_type_group_filter + + + + + + script_name + + + + + + temporary_document_disallowed + 0 + + + title + ? + + + trigger_type + 2 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts.xml new file mode 100644 index 0000000000000000000000000000000000000000..072c8f6540c07806bee17a34c920ec09b2de1bd5 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + scripts + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateHeadCommitId.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateHeadCommitId.py new file mode 100644 index 0000000000000000000000000000000000000000..7659dac2e904431d32adaf19ad64ffb31282cdcb --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateHeadCommitId.py @@ -0,0 +1,8 @@ +modified = state_change['object'] +site = context.getPortalObject() +portal_commits = site.portal_commits + +# If the state of modified commit is commited, then update the value of HEAD +# commit ID +if modified.getValidationState() == 'commited': + portal_commits.setHeadCommitId(modified.getId()) diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateHeadCommitId.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateHeadCommitId.xml new file mode 100644 index 0000000000000000000000000000000000000000..3720da8ece35f837b9c19fd0dc430e49f1d3b678 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateHeadCommitId.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessCommit_updateHeadCommitId + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateTemplateStatus.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateTemplateStatus.py new file mode 100644 index 0000000000000000000000000000000000000000..3f9103e9538f89787e2e2a0c00a5067b9e741fb0 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateTemplateStatus.py @@ -0,0 +1,15 @@ +modified = state_change['object'] +site = context.getPortalObject() + +if modified.getValidationState() == 'committed': + # Get all Business Template which are affected by this commit + bt_list = list(set([item for sublist + in [l.getFollowUpValueList() + for l in modified.objectValues()] + for item in sublist])) + +# Now update the status of all Business Template to 'available' +for bt in bt_list: + if site.portal_workflow.isTransitionPossible( + bt, 'exhibit'): + bt.exhibit() diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateTemplateStatus.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateTemplateStatus.xml new file mode 100644 index 0000000000000000000000000000000000000000..95a6c64ff6d8777969937f423cb8c9f56c2981d5 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/scripts/BusinessCommit_updateTemplateStatus.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessCommit_updateTemplateStatus + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/variables.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/variables.xml new file mode 100644 index 0000000000000000000000000000000000000000..6ae03699d19840ac42b097dfc0a5f34edd416170 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/variables.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + variables + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/worklists.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/worklists.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3432aa051eac2d67ec0692a384adb38d1b6bac8 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_interaction_workflow/worklists.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + worklists + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow.xml new file mode 100644 index 0000000000000000000000000000000000000000..bd54d77b563b3f4193427543d45b040ed014b5b5 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow.xml @@ -0,0 +1,66 @@ + + + + + + + + + + _objects + + + + + + creation_guard + + + + + + description + + + + groups + + + + + + id + business_commit_validation_workflow + + + initial_state + draft + + + manager_bypass + 0 + + + permissions + + + Access contents information + View + Add portal content + Modify portal content + Delete objects + + + + + state_var + validation_state + + + title + Business Commit Validation Workflow + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts.xml new file mode 100644 index 0000000000000000000000000000000000000000..072c8f6540c07806bee17a34c920ec09b2de1bd5 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + scripts + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_commit.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_commit.py new file mode 100644 index 0000000000000000000000000000000000000000..b8a10d6c10715bbbfff8f49721f9cfbf702dc2c7 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_commit.py @@ -0,0 +1,24 @@ +context.BusinessCommit_validateItemsOnCommitCommit(state_change) +context.BusinessCommit_updateUuidOnCommitCommit(state_change) + +#""" +#Validate Business Commit and checks if it has atleast one item +#""" +# +#from Products.DCWorkflow.DCWorkflow import ValidationFailed +#from Products.ERP5Type.Message import translateString +# +#business_commit = state_change['object'] +# +#business_commit.Base_checkConsistency() +#business_item_list = business_commit.objectValues() +# +#commit_path_list = business_commit.getItemPathList() +## Raise error in case the commit have 2 items which has same path +#if len(commit_path_list) != len(set(commit_path_list)): +# raise ValidationFailed(translateString('Multiple items have same path !')) +# +## Raise error in case there is no Business Item or Business Property Item added +## in the Business Commit +#if not business_item_list: +# raise ValidationFailed(translateString('Please add item(s) in commit before committing')) diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_commit.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_commit.xml new file mode 100644 index 0000000000000000000000000000000000000000..84031af723ad43db5b7ea65acc8ce55b38010efe --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_commit.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessCommit_commit + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_delete.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_delete.py new file mode 100644 index 0000000000000000000000000000000000000000..99b1272de830a04e514e82328e1a3d3a492deae0 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_delete.py @@ -0,0 +1 @@ +context.BusinessCommit_deleteItemsOnCommitDelete(state_change) diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_delete.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_delete.xml new file mode 100644 index 0000000000000000000000000000000000000000..37ddd2cb0e2ce31a772c1e1d5a34d107e44238b5 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_delete.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessCommit_delete + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_deleteItemsOnCommitDelete.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_deleteItemsOnCommitDelete.py new file mode 100644 index 0000000000000000000000000000000000000000..2cd2b5637049492f4e656a6524193d4a17f8a656 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_deleteItemsOnCommitDelete.py @@ -0,0 +1,8 @@ +site = context.getPortalObject() + +commit = state_change['object'] +commit_item_list = commit.objectValues() + +for item in commit_item_list: + if site.portal_workflow.isTransitionPossible(item, 'delete'): + site.portal_workflow.doActionFor(item, 'delete_action') diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_deleteItemsOnCommitDelete.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_deleteItemsOnCommitDelete.xml new file mode 100644 index 0000000000000000000000000000000000000000..730800a58ea46d0321d21cf021a4366b8d062f19 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_deleteItemsOnCommitDelete.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessCommit_deleteItemsOnCommitDelete + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_updateUuidOnCommitCommit.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_updateUuidOnCommitCommit.py new file mode 100644 index 0000000000000000000000000000000000000000..b93a91210a25e577e2301fc087a55e89c7800b96 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_updateUuidOnCommitCommit.py @@ -0,0 +1,2 @@ +commit = state_change['object'] +commit.getObject().setId(commit.generateNewId()) diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_updateUuidOnCommitCommit.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_updateUuidOnCommitCommit.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e7bca0ebad9c4ee8a940a2403eb5c83f042ebf7 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_updateUuidOnCommitCommit.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessCommit_updateUuidOnCommitCommit + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_validateItemsOnCommitCommit.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_validateItemsOnCommitCommit.py new file mode 100644 index 0000000000000000000000000000000000000000..18062d8b2702f774dd9c110705c48fadc9be1c47 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_validateItemsOnCommitCommit.py @@ -0,0 +1,10 @@ +site = context.getPortalObject() + +commit = state_change['object'] +commit_item_list = commit.objectValues() + +for item in commit_item_list: + if site.portal_workflow.isTransitionPossible(item, 'validate'): + site.portal_workflow.doActionFor(item, 'validate_action') + elif site.portal_workflow.isTransitionPossible(item, 'delete'): + site.portal_workflow.doActionFor(item, 'delete_action') diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_validateItemsOnCommitCommit.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_validateItemsOnCommitCommit.xml new file mode 100644 index 0000000000000000000000000000000000000000..e3012b541a9961c707b36c8d650fbb2b41eb42a4 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/scripts/BusinessCommit_validateItemsOnCommitCommit.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessCommit_validateItemsOnCommitCommit + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states.xml new file mode 100644 index 0000000000000000000000000000000000000000..27ec9069024e0f59bf4b612113789f37da98879b --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + states + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/committed.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/committed.xml new file mode 100644 index 0000000000000000000000000000000000000000..29471d9ca7895ca0e12ab59ea348fb2452190731 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/committed.xml @@ -0,0 +1,91 @@ + + + + + + + + + + description + + + + id + committed + + + permission_roles + + AAAAAAAAAAI= + + + + title + Committed + + + transitions + + + push + push_action + + + + + type_list + + + + + + + + + + + + + + + data + + + + Access contents information + + + + + + Add portal content + + + + + + Delete objects + + + + + + Modify portal content + + + + + + View + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/deleted.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/deleted.xml new file mode 100644 index 0000000000000000000000000000000000000000..2212a0b56c6b2f10b7e89e48034909daf7ce5f85 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/deleted.xml @@ -0,0 +1,92 @@ + + + + + + + + + + description + + + + id + deleted + + + permission_roles + + AAAAAAAAAAI= + + + + title + Deleted + + + transitions + + + + + + type_list + + + + + + + + + + + + + + + data + + + + Access contents information + + + Manager + + + + + Add portal content + + + + + + Delete objects + + + + + + Modify portal content + + + + + + View + + + Manager + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/draft.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/draft.xml new file mode 100644 index 0000000000000000000000000000000000000000..77eb3c836ed2f41789e0102da90d78382c251453 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/draft.xml @@ -0,0 +1,93 @@ + + + + + + + + + + description + + + + id + draft + + + permission_roles + + AAAAAAAAAAI= + + + + title + Draft + + + transitions + + + commit + commit_action + delete + delete_action + + + + + type_list + + + + + + + + + + + + + + + data + + + + Access contents information + + + + + + Add portal content + + + + + + Delete objects + + + + + + Modify portal content + + + + + + View + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/pushed.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/pushed.xml new file mode 100644 index 0000000000000000000000000000000000000000..6a742cc9b7585f287fde5dd0cf1ceb1cfd01929f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/states/pushed.xml @@ -0,0 +1,88 @@ + + + + + + + + + + description + + + + id + pushed + + + permission_roles + + AAAAAAAAAAI= + + + + title + Pushed + + + transitions + + + + + + type_list + + + + + + + + + + + + + + + data + + + + Access contents information + + + + + + Add portal content + + + + + + Delete objects + + + + + + Modify portal content + + + + + + View + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions.xml new file mode 100644 index 0000000000000000000000000000000000000000..aa36144efed916b804f5f80df9452b1e3166bdec --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + transitions + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/commit.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/commit.xml new file mode 100644 index 0000000000000000000000000000000000000000..44380455a71ee818b82a252059d6d0bad9dcbdfb --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/commit.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + + + + actbox_url + + + + after_script_name + + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + commit + + + new_state_id + committed + + + script_name + BusinessCommit_commit + + + title + Commit + + + trigger_type + 2 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/commit_action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/commit_action.xml new file mode 100644 index 0000000000000000000000000000000000000000..878c40853280a3d3ff7aa20f622409d3595befa4 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/commit_action.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + Commit + + + actbox_url + %(content_url)s/Base_viewWorkflowActionDialog?workflow_action=commit_action + + + after_script_name + commit + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + commit_action + + + new_state_id + + + + script_name + + + + title + Commit Action + + + trigger_type + 1 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/delete.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/delete.xml new file mode 100644 index 0000000000000000000000000000000000000000..f95c1e4093475613a3a7bbd9449e0d2aa28ab1f2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/delete.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + + + + actbox_url + + + + after_script_name + + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + delete + + + new_state_id + deleted + + + script_name + BusinessCommit_delete + + + title + Delete + + + trigger_type + 2 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/delete_action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/delete_action.xml new file mode 100644 index 0000000000000000000000000000000000000000..2b5fc74c2de7236dc884d4e82d93303a75d1e9c9 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/delete_action.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + Delete + + + actbox_url + %(content_url)s/Base_viewWorkflowActionDialog?workflow_action=delete_action + + + after_script_name + delete + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + delete_action + + + new_state_id + + + + script_name + + + + title + Delete Action + + + trigger_type + 1 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/push.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/push.xml new file mode 100644 index 0000000000000000000000000000000000000000..cd2cf907ff28e10b405ea040ae5ef74f9edc2f56 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/push.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + + + + actbox_url + + + + after_script_name + + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + push + + + new_state_id + pushed + + + script_name + + + + title + Push + + + trigger_type + 2 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/push_action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/push_action.xml new file mode 100644 index 0000000000000000000000000000000000000000..b06361674f81864a142c96f8889ed5fc2727cee9 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/transitions/push_action.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + Push + + + actbox_url + %(content_url)s/Base_viewWorkflowActionDialog?workflow_action=push_action + + + after_script_name + push + + + description + Push the content of the commit to the remote. + + + guard + + AAAAAAAAAAI= + + + + id + push_action + + + new_state_id + + + + script_name + + + + title + Push Action + + + trigger_type + 1 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb12bef805f190ec50e023368d6ee5c6c990b816 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + variables + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/action.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb5af22d393b9d5705b4db17eab482f3c69afa35 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/action.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Transition id + + + for_catalog + 0 + + + for_status + 1 + + + id + action + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + transition/getId|nothing + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/actor.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/actor.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd10331a7a0afa069e0ae18222e2c7b7fd2045fd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/actor.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Name of the user who performed transition + + + for_catalog + 0 + + + for_status + 1 + + + id + actor + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + user/getIdOrUserName + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/comment.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/comment.xml new file mode 100644 index 0000000000000000000000000000000000000000..fda919ee8613b8374150500ddfd080ca5d68d7bd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/comment.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Comment about transition + + + for_catalog + 0 + + + for_status + 1 + + + id + comment + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + python:state_change.kwargs.get(\'comment\', \'\') + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/error_message.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/error_message.xml new file mode 100644 index 0000000000000000000000000000000000000000..535863de2a26221cff2a356674852ea83bcee061 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/error_message.xml @@ -0,0 +1,48 @@ + + + + + + + + + + default_expr + + + + + + default_value + + + + description + Error message if validation failed + + + for_catalog + 0 + + + for_status + 1 + + + id + error_message + + + info_guard + + + + + + update_always + 1 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/history.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/history.xml new file mode 100644 index 0000000000000000000000000000000000000000..44306b76d7460536661dc87f7786d58d071917d2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/history.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Provides access to workflow history + + + for_catalog + 0 + + + for_status + 0 + + + id + history + + + info_guard + + + + + + update_always + 0 + + + + + + + + + + + + text + state_change/getHistory + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/portal_type.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/portal_type.xml new file mode 100644 index 0000000000000000000000000000000000000000..89576a7a56ae4e16ceb1cf44e2f9ff9e2ff85f3f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/portal_type.xml @@ -0,0 +1,48 @@ + + + + + + + + + + default_expr + + + + + + default_value + + + + description + Portal type (used as filter for worklists) + + + for_catalog + 1 + + + for_status + 0 + + + id + portal_type + + + info_guard + + + + + + update_always + 0 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/time.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/time.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d2d8d7e22159b7b4db1fe60eea58cb239a5105a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/variables/time.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Transition timestamp + + + for_catalog + 0 + + + for_status + 1 + + + id + time + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + state_change/getDateTime + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/worklists.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/worklists.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3432aa051eac2d67ec0692a384adb38d1b6bac8 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_commit_validation_workflow/worklists.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + worklists + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a09c8360e1372ab1cd4e424745350968d3492ed --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow.xml @@ -0,0 +1,46 @@ + + + + + + + + + + _objects + + + + + + creation_guard + + + + + + description + + + + groups + + + + + + id + business_item_interaction_workflow + + + manager_bypass + 0 + + + title + Business Item Interaction Workflow + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions.xml new file mode 100644 index 0000000000000000000000000000000000000000..e18bf8cbf778a6808aa24ec39bba4b527d7b1bef --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + interactions + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_rebuildItemOnPathChange.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_rebuildItemOnPathChange.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d647b2c8dfad0eecc908a8e2d6888666f4fe8a3 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_rebuildItemOnPathChange.xml @@ -0,0 +1,102 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_name + + + + actbox_url + + + + activate_script_name + + + + + + after_script_name + + + BusinessItem_rebuildItemOnPathChange + + + + + before_commit_script_name + + + + + + description + + + + guard + + + + + + id + BusinessItem_rebuildItemOnPathChange + + + method_id + + + _setItemPath.* + + + + + once_per_transaction + 0 + + + portal_type_filter + + + Business Item + + + + + portal_type_group_filter + + + + + + script_name + + + + + + temporary_document_disallowed + 0 + + + title + + + + trigger_type + 2 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_updateFollowUpItemPathList.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_updateFollowUpItemPathList.xml new file mode 100644 index 0000000000000000000000000000000000000000..3a6def628b67c3ddd196e51c2182985251b539bd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_updateFollowUpItemPathList.xml @@ -0,0 +1,100 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_name + + + + actbox_url + + + + activate_script_name + + + + + + after_script_name + + + + + + before_commit_script_name + + + BusinessItem_updateFollowUpItemPathList + + + + + description + + + + guard + + + + + + id + BusinessItem_updateFollowUpItemPathList + + + method_id + + + edit + + + + + once_per_transaction + 0 + + + portal_type_filter + + + + + + portal_type_group_filter + + + + + + script_name + + + + + + temporary_document_disallowed + 0 + + + title + + + + trigger_type + 2 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_updatePathOnReferenceChange.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_updatePathOnReferenceChange.xml new file mode 100644 index 0000000000000000000000000000000000000000..0256b55720fc0b987d0bb1c9d52df03dd4ad20d3 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/interactions/BusinessItem_updatePathOnReferenceChange.xml @@ -0,0 +1,102 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_name + + + + actbox_url + + + + activate_script_name + + + + + + after_script_name + + + BusinessItem_updatePathOnReferenceChange + + + + + before_commit_script_name + + + + + + description + + + + guard + + + + + + id + BusinessItem_updatePathOnReferenceChange + + + method_id + + + _setPredecessor.* + + + + + once_per_transaction + 0 + + + portal_type_filter + + + Business Item + + + + + portal_type_group_filter + + + + + + script_name + + + + + + temporary_document_disallowed + 0 + + + title + + + + trigger_type + 2 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts.xml new file mode 100644 index 0000000000000000000000000000000000000000..072c8f6540c07806bee17a34c920ec09b2de1bd5 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + scripts + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_rebuildItemOnPathChange.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_rebuildItemOnPathChange.py new file mode 100644 index 0000000000000000000000000000000000000000..d0ebd2bc5484524c5ce6e61db38e405fbcc6bb47 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_rebuildItemOnPathChange.py @@ -0,0 +1,6 @@ +site = context.getPortalObject() + +item = state_change['object'] + +if item.getValidationState() == 'built': + site.portal_workflow.doActionFor(item, 'build_action') diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_rebuildItemOnPathChange.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_rebuildItemOnPathChange.xml new file mode 100644 index 0000000000000000000000000000000000000000..8b2e926a80e1b28390465095c20d9cdd42d2cfd9 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_rebuildItemOnPathChange.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessItem_rebuildItemOnPathChange + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updateFollowUpItemPathList.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updateFollowUpItemPathList.py new file mode 100644 index 0000000000000000000000000000000000000000..fc30dc8b6689d2eee698a146412fc51030c893fc --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updateFollowUpItemPathList.py @@ -0,0 +1,4 @@ +modified = state_change['object'] + +# Update Follow Up Item Path List +#modified.updateFollowUpPathList() diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updateFollowUpItemPathList.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updateFollowUpItemPathList.xml new file mode 100644 index 0000000000000000000000000000000000000000..18370e4d67b140b62d6966cd0989a726e9c83ced --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updateFollowUpItemPathList.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessItem_updateFollowUpItemPathList + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updatePathOnReferenceChange.py b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updatePathOnReferenceChange.py new file mode 100644 index 0000000000000000000000000000000000000000..07a146c5bf1fcc34234ad8742fbcb263970dfdc3 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updatePathOnReferenceChange.py @@ -0,0 +1,10 @@ +item = state_change['object'] +item_new_reference_item = item.getPredecessorValue() + +if item_new_reference_item: + item_new_reference_item_path = item_new_reference_item.getItemPath() + if item.getItemPath() != item_new_reference_item_path: + item.setItemPath(item_new_reference_item_path) + + if not item.getItemPatchBehaviour(): + item.setItemPatchBehaviour('force_apply') diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updatePathOnReferenceChange.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updatePathOnReferenceChange.xml new file mode 100644 index 0000000000000000000000000000000000000000..7700cfcecf1917a7ce89bfa6a3c1b0fbc5068d7b --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/scripts/BusinessItem_updatePathOnReferenceChange.xml @@ -0,0 +1,62 @@ + + + + + + + + + + Script_magic + 3 + + + _bind_names + + + + + + + + + + _asgns + + + + name_container + container + + + name_context + context + + + name_m_self + script + + + name_subpath + traverse_subpath + + + + + + + + + + + _params + state_change + + + id + BusinessItem_updatePathOnReferenceChange + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/variables.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/variables.xml new file mode 100644 index 0000000000000000000000000000000000000000..6ae03699d19840ac42b097dfc0a5f34edd416170 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/variables.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + variables + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/worklists.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/worklists.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3432aa051eac2d67ec0692a384adb38d1b6bac8 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_item_interaction_workflow/worklists.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + worklists + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow.xml new file mode 100644 index 0000000000000000000000000000000000000000..7f3ea13428f9bf1650410dc78ec1b7a94823f2b8 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow.xml @@ -0,0 +1,66 @@ + + + + + + + + + + _objects + + + + + + creation_guard + + + + + + description + + + + groups + + + + + + id + business_snapshot_validation_workflow + + + initial_state + draft + + + manager_bypass + 0 + + + permissions + + + Access contents information + View + Add portal content + Delete objects + Modify portal content + + + + + state_var + validation_state + + + title + Business Snapshot Validation Workflow + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/scripts.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/scripts.xml new file mode 100644 index 0000000000000000000000000000000000000000..a703b14c4ca0bde0a51a531783d85f8be1ccd853 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/scripts.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + scripts + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states.xml new file mode 100644 index 0000000000000000000000000000000000000000..27ec9069024e0f59bf4b612113789f37da98879b --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + states + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/built.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/built.xml new file mode 100644 index 0000000000000000000000000000000000000000..e380b6135ee02402515911ffad43649e07b57eea --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/built.xml @@ -0,0 +1,88 @@ + + + + + + + + + + description + + + + id + built + + + permission_roles + + AAAAAAAAAAI= + + + + title + Built + + + transitions + + + + + + type_list + + + + + + + + + + + + + + + data + + + + Access contents information + + + + + + Add portal content + + + + + + Delete objects + + + + + + Modify portal content + + + + + + View + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/deleted.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/deleted.xml new file mode 100644 index 0000000000000000000000000000000000000000..2212a0b56c6b2f10b7e89e48034909daf7ce5f85 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/deleted.xml @@ -0,0 +1,92 @@ + + + + + + + + + + description + + + + id + deleted + + + permission_roles + + AAAAAAAAAAI= + + + + title + Deleted + + + transitions + + + + + + type_list + + + + + + + + + + + + + + + data + + + + Access contents information + + + Manager + + + + + Add portal content + + + + + + Delete objects + + + + + + Modify portal content + + + + + + View + + + Manager + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/draft.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/draft.xml new file mode 100644 index 0000000000000000000000000000000000000000..694343bdff22e23c359ffa7c1a74ecb565f6cc2c --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/states/draft.xml @@ -0,0 +1,93 @@ + + + + + + + + + + description + + + + id + draft + + + permission_roles + + AAAAAAAAAAI= + + + + title + Draft + + + transitions + + + build + build_action + delete + delete_action + + + + + type_list + + + + + + + + + + + + + + + data + + + + Access contents information + + + + + + Add portal content + + + + + + Delete objects + + + + + + Modify portal content + + + + + + View + + + + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions.xml new file mode 100644 index 0000000000000000000000000000000000000000..aa36144efed916b804f5f80df9452b1e3166bdec --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + transitions + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/build.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/build.xml new file mode 100644 index 0000000000000000000000000000000000000000..6517122149eb7c6c1eae0bd4d391bd82f7a705cf --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + + + + actbox_url + + + + after_script_name + + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + build + + + new_state_id + built + + + script_name + + + + title + Build + + + trigger_type + 2 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/build_action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/build_action.xml new file mode 100644 index 0000000000000000000000000000000000000000..8323e7e09d4db2d8aa7d73197d7b9aa3abada11e --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/build_action.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + Build + + + actbox_url + %(content_url)s/Base_viewWorkflowActionDialog?workflow_action=build_action + + + after_script_name + build + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + build_action + + + new_state_id + + + + script_name + + + + title + Build Action + + + trigger_type + 1 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/delete.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/delete.xml new file mode 100644 index 0000000000000000000000000000000000000000..73c3a0390a527eb78c6e95f931c1fde673c5781b --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/delete.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + + + + actbox_url + + + + after_script_name + + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + delete + + + new_state_id + deleted + + + script_name + + + + title + Delete + + + trigger_type + 2 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/delete_action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/delete_action.xml new file mode 100644 index 0000000000000000000000000000000000000000..2b5fc74c2de7236dc884d4e82d93303a75d1e9c9 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/transitions/delete_action.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + Delete + + + actbox_url + %(content_url)s/Base_viewWorkflowActionDialog?workflow_action=delete_action + + + after_script_name + delete + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + delete_action + + + new_state_id + + + + script_name + + + + title + Delete Action + + + trigger_type + 1 + + + + + + + + + + + + permissions + + + Manage portal + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb12bef805f190ec50e023368d6ee5c6c990b816 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + variables + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/action.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb5af22d393b9d5705b4db17eab482f3c69afa35 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/action.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Transition id + + + for_catalog + 0 + + + for_status + 1 + + + id + action + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + transition/getId|nothing + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/actor.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/actor.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd10331a7a0afa069e0ae18222e2c7b7fd2045fd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/actor.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Name of the user who performed transition + + + for_catalog + 0 + + + for_status + 1 + + + id + actor + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + user/getIdOrUserName + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/comment.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/comment.xml new file mode 100644 index 0000000000000000000000000000000000000000..fda919ee8613b8374150500ddfd080ca5d68d7bd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/comment.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Comment about transition + + + for_catalog + 0 + + + for_status + 1 + + + id + comment + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + python:state_change.kwargs.get(\'comment\', \'\') + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/error_message.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/error_message.xml new file mode 100644 index 0000000000000000000000000000000000000000..535863de2a26221cff2a356674852ea83bcee061 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/error_message.xml @@ -0,0 +1,48 @@ + + + + + + + + + + default_expr + + + + + + default_value + + + + description + Error message if validation failed + + + for_catalog + 0 + + + for_status + 1 + + + id + error_message + + + info_guard + + + + + + update_always + 1 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/history.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/history.xml new file mode 100644 index 0000000000000000000000000000000000000000..44306b76d7460536661dc87f7786d58d071917d2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/history.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Provides access to workflow history + + + for_catalog + 0 + + + for_status + 0 + + + id + history + + + info_guard + + + + + + update_always + 0 + + + + + + + + + + + + text + state_change/getHistory + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/portal_type.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/portal_type.xml new file mode 100644 index 0000000000000000000000000000000000000000..89576a7a56ae4e16ceb1cf44e2f9ff9e2ff85f3f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/portal_type.xml @@ -0,0 +1,48 @@ + + + + + + + + + + default_expr + + + + + + default_value + + + + description + Portal type (used as filter for worklists) + + + for_catalog + 1 + + + for_status + 0 + + + id + portal_type + + + info_guard + + + + + + update_always + 0 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/time.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/time.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d2d8d7e22159b7b4db1fe60eea58cb239a5105a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/variables/time.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Transition timestamp + + + for_catalog + 0 + + + for_status + 1 + + + id + time + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + state_change/getDateTime + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/worklists.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/worklists.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3432aa051eac2d67ec0692a384adb38d1b6bac8 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_snapshot_validation_workflow/worklists.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + worklists + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow.xml new file mode 100644 index 0000000000000000000000000000000000000000..44ff66afea33b7b824c1f28019c74b26c1ed9dce --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow.xml @@ -0,0 +1,66 @@ + + + + + + + + + + _objects + + + + + + creation_guard + + + + + + description + + + + groups + + + + + + id + business_template_availability_workflow + + + initial_state + draft + + + manager_bypass + 0 + + + permissions + + + Access contents information + View + Add portal content + Modify portal content + Delete objects + + + + + state_var + availability_state + + + title + Business Template Availabilty Workflow + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/scripts.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/scripts.xml new file mode 100644 index 0000000000000000000000000000000000000000..a703b14c4ca0bde0a51a531783d85f8be1ccd853 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/scripts.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + scripts + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states.xml new file mode 100644 index 0000000000000000000000000000000000000000..27ec9069024e0f59bf4b612113789f37da98879b --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + states + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/available.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/available.xml new file mode 100644 index 0000000000000000000000000000000000000000..50fe73afe45eb21b69436f83c65b7d285bef492a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/available.xml @@ -0,0 +1,39 @@ + + + + + + + + + + description + It denotes that the Business Template is available for installation, but it is not installed currently. + + + id + available + + + title + Available + + + transitions + + + install + install_action + + + + + type_list + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/draft.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/draft.xml new file mode 100644 index 0000000000000000000000000000000000000000..333e14c5d2a7db3b3cd4860ae86882eddcc00c88 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/draft.xml @@ -0,0 +1,39 @@ + + + + + + + + + + description + A newly created Business Template which we can modify and attach the changes to one or more Business Commit and make it available. + + + id + draft + + + title + Draft + + + transitions + + + exhibit + exhibit_action + + + + + type_list + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/installable.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/installable.xml new file mode 100644 index 0000000000000000000000000000000000000000..db5415a136cbd41bed8832078935c322f3118fae --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/states/installable.xml @@ -0,0 +1,39 @@ + + + + + + + + + + description + Installable will be case when either we have an already installed Business Template which we can install again if needed(with or without changes) + + + id + installable + + + title + Installable + + + transitions + + + reinstall + reinstall_action + + + + + type_list + + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions.xml new file mode 100644 index 0000000000000000000000000000000000000000..aa36144efed916b804f5f80df9452b1e3166bdec --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + transitions + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/exhibit.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/exhibit.xml new file mode 100644 index 0000000000000000000000000000000000000000..0f45ce95b9452637cfb2c3ab3c48bbde17da9803 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/exhibit.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + + + + actbox_url + + + + after_script_name + + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + exhibit + + + new_state_id + available + + + script_name + + + + title + Exhibit Business Template + + + trigger_type + 2 + + + + + + + + + + + + permissions + + + Modify portal content + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/exhibit_action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/exhibit_action.xml new file mode 100644 index 0000000000000000000000000000000000000000..9a68929927a3f277ac566612523275f29e66bf06 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/exhibit_action.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + Exhibit Business Template V2 + + + actbox_url + %(content_url)s/Base_viewWorkflowActionDialog?workflow_action=exhibit_action + + + after_script_name + exhibit + + + description + Make the Business Template available, i.e, the path items should be committed in a Business Commit. + + + guard + + AAAAAAAAAAI= + + + + id + exhibit_action + + + new_state_id + + + + script_name + + + + title + Exhibit Business Template Action + + + trigger_type + 1 + + + + + + + + + + + + permissions + + + Modify portal content + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/install.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/install.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4c8c98d777dc0d7a5e7f23364fabcc8c71d40bd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/install.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + + + + actbox_url + + + + after_script_name + + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + install + + + new_state_id + installable + + + script_name + + + + title + Install Business Template + + + trigger_type + 2 + + + + + + + + + + + + permissions + + + Modify portal content + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/install_action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/install_action.xml new file mode 100644 index 0000000000000000000000000000000000000000..58e56f223d4b67e8a13cc654166172849e0d65be --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/install_action.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + Install Business Template V2 + + + actbox_url + %(content_url)s/Base_viewWorkflowActionDialog?workflow_action=install_action + + + after_script_name + install + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + install_action + + + new_state_id + + + + script_name + + + + title + Install Business Template Action + + + trigger_type + 1 + + + + + + + + + + + + permissions + + + Modify portal content + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/reinstall.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/reinstall.xml new file mode 100644 index 0000000000000000000000000000000000000000..d0fe70ef5aa0534d4c3e4236377522821fc1c922 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/reinstall.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + + + + actbox_url + + + + after_script_name + reinstall + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + reinstall + + + new_state_id + installable + + + script_name + + + + title + Reinstall Business Template + + + trigger_type + 2 + + + + + + + + + + + + permissions + + + Modify portal content + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/reinstall_action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/reinstall_action.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4585f8d9f529a2ebf9c3272eadcb3fb1ed6cecd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/transitions/reinstall_action.xml @@ -0,0 +1,79 @@ + + + + + + + + + + actbox_category + workflow + + + actbox_icon + + + + actbox_name + Reinstall Business Template V2 + + + actbox_url + %(content_url)s/Base_viewWorkflowActionDialog?workflow_action=reinstall_action + + + after_script_name + + + + description + + + + guard + + AAAAAAAAAAI= + + + + id + reinstall_action + + + new_state_id + + + + script_name + + + + title + Reinstall Business Template Action + + + trigger_type + 1 + + + + + + + + + + + + permissions + + + Modify portal content + + + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb12bef805f190ec50e023368d6ee5c6c990b816 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables.xml @@ -0,0 +1,28 @@ + + + + + + + + + + _mapping + + + + + + _objects + + + + + + id + variables + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/action.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/action.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb5af22d393b9d5705b4db17eab482f3c69afa35 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/action.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Transition id + + + for_catalog + 0 + + + for_status + 1 + + + id + action + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + transition/getId|nothing + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/actor.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/actor.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd10331a7a0afa069e0ae18222e2c7b7fd2045fd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/actor.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Name of the user who performed transition + + + for_catalog + 0 + + + for_status + 1 + + + id + actor + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + user/getIdOrUserName + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/comment.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/comment.xml new file mode 100644 index 0000000000000000000000000000000000000000..fda919ee8613b8374150500ddfd080ca5d68d7bd --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/comment.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Comment about transition + + + for_catalog + 0 + + + for_status + 1 + + + id + comment + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + python:state_change.kwargs.get(\'comment\', \'\') + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/error_message.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/error_message.xml new file mode 100644 index 0000000000000000000000000000000000000000..535863de2a26221cff2a356674852ea83bcee061 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/error_message.xml @@ -0,0 +1,48 @@ + + + + + + + + + + default_expr + + + + + + default_value + + + + description + Error message if validation failed + + + for_catalog + 0 + + + for_status + 1 + + + id + error_message + + + info_guard + + + + + + update_always + 1 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/history.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/history.xml new file mode 100644 index 0000000000000000000000000000000000000000..44306b76d7460536661dc87f7786d58d071917d2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/history.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Provides access to workflow history + + + for_catalog + 0 + + + for_status + 0 + + + id + history + + + info_guard + + + + + + update_always + 0 + + + + + + + + + + + + text + state_change/getHistory + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/portal_type.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/portal_type.xml new file mode 100644 index 0000000000000000000000000000000000000000..89576a7a56ae4e16ceb1cf44e2f9ff9e2ff85f3f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/portal_type.xml @@ -0,0 +1,48 @@ + + + + + + + + + + default_expr + + + + + + default_value + + + + description + Portal type (used as filter for worklists) + + + for_catalog + 1 + + + for_status + 0 + + + id + portal_type + + + info_guard + + + + + + update_always + 0 + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/time.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/time.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d2d8d7e22159b7b4db1fe60eea58cb239a5105a --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/variables/time.xml @@ -0,0 +1,61 @@ + + + + + + + + + + default_expr + + AAAAAAAAAAI= + + + + default_value + + + + description + Transition timestamp + + + for_catalog + 0 + + + for_status + 1 + + + id + time + + + info_guard + + + + + + update_always + 1 + + + + + + + + + + + + text + state_change/getDateTime + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/worklists.xml b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/worklists.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3432aa051eac2d67ec0692a384adb38d1b6bac8 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/WorkflowTemplateItem/portal_workflow/business_template_availability_workflow/worklists.xml @@ -0,0 +1,22 @@ + + + + + + + + + + _mapping + + + + + + id + worklists + + + + + diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/copyright_list b/product/ERP5/bootstrap/erp5_business_package/bt/copyright_list new file mode 100644 index 0000000000000000000000000000000000000000..3b265520a1fe981603f75b98f24f0e744f0af202 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/copyright_list @@ -0,0 +1 @@ +Copyright (c) 2001-2017 Nexedi SA \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/description b/product/ERP5/bootstrap/erp5_business_package/bt/description new file mode 100644 index 0000000000000000000000000000000000000000..566e4f0178695851e9bed051f654787b6a2da55c --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/description @@ -0,0 +1 @@ +Includes Business Manager portal_types, skins, component and live tests \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/license b/product/ERP5/bootstrap/erp5_business_package/bt/license new file mode 100644 index 0000000000000000000000000000000000000000..3a3e12bcad97e4b3bdd6a8bb499fd23a4bcb0819 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/license @@ -0,0 +1 @@ +GPL \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/maintainer_list b/product/ERP5/bootstrap/erp5_business_package/bt/maintainer_list new file mode 100644 index 0000000000000000000000000000000000000000..cb382916f994106f8270efad9188ae1f4b295d5b --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/maintainer_list @@ -0,0 +1 @@ +ayush \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_action_path_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_action_path_list new file mode 100644 index 0000000000000000000000000000000000000000..92c0c71e36a44da69f06578c90508947ecd394e0 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_action_path_list @@ -0,0 +1,10 @@ +Business Commit | build_items +Business Commit | install +Business Commit | view +Business Item | goto_path +Business Item | view +Business Snapshot | view +Business Template V2 | content_view +Commit Tool | create_snapshot +Commit Tool | view +portal_actions | commit_tool \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_extension_id_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_extension_id_list new file mode 100644 index 0000000000000000000000000000000000000000..c022056d0892b022aedb05c92ee17bd2005ff7f7 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_extension_id_list @@ -0,0 +1 @@ +extension.erp5.CommitUtils \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_format_version b/product/ERP5/bootstrap/erp5_business_package/bt/template_format_version new file mode 100644 index 0000000000000000000000000000000000000000..56a6051ca2b02b04ef92d5150c9ef600403cb1de --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_format_version @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_allowed_content_type_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_allowed_content_type_list new file mode 100644 index 0000000000000000000000000000000000000000..c285f30facec37d91d16f1fc035dc5739ecd6064 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_allowed_content_type_list @@ -0,0 +1,3 @@ +Business Commit | Business Item +Commit Tool | Business Commit +Commit Tool | Business Snapshot \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_base_category_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_base_category_list new file mode 100644 index 0000000000000000000000000000000000000000..fa7f8db57bfc12a4e9738173bfa504a57cc53ca2 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_base_category_list @@ -0,0 +1,4 @@ +Business Commit | predecessor +Business Item | follow_up +Business Item | predecessor +Business Snapshot | predecessor \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_hidden_content_type_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_hidden_content_type_list new file mode 100644 index 0000000000000000000000000000000000000000..4c29a722dc1889e32e8637406e661bb7ec327d5c --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_hidden_content_type_list @@ -0,0 +1 @@ +Business Snapshot | Business Item \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_id_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_id_list new file mode 100644 index 0000000000000000000000000000000000000000..653ecdac365f501c1eb2a7191f1cc6fa53ad443e --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_id_list @@ -0,0 +1,5 @@ +Business Commit +Business Item +Business Snapshot +Business Template V2 +Commit Tool \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_property_sheet_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_property_sheet_list new file mode 100644 index 0000000000000000000000000000000000000000..3e1c5a7618adfd1806dedd949589185ab34c1a2e --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_property_sheet_list @@ -0,0 +1,5 @@ +Business Commit | BusinessCommit +Business Item | BusinessItem +Business Item | BusinessItemConstraint +Business Snapshot | BusinessCommit +Commit Tool | CommitTool \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_workflow_chain_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_workflow_chain_list new file mode 100644 index 0000000000000000000000000000000000000000..56fb7396487c93874ee2544eb01a14ad80bef538 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_portal_type_workflow_chain_list @@ -0,0 +1,6 @@ +Business Commit | business_commit_interaction_workflow +Business Commit | business_commit_validation_workflow +Business Item | business_item_interaction_workflow +Business Item | business_item_validation_workflow +Business Snapshot | business_snapshot_validation_workflow +Business Template V2 | business_template_availability_workflow \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_property_sheet_id_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_property_sheet_id_list new file mode 100644 index 0000000000000000000000000000000000000000..f764e4a0d466223f67fe1321c21ef64bb1e2a42c --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_property_sheet_id_list @@ -0,0 +1,3 @@ +BusinessTemplateV2 +BusinessItemConstraint +CommitTool \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_skin_id_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_skin_id_list new file mode 100644 index 0000000000000000000000000000000000000000..97c45335cacf275dba7326cb9979b68e24c8ddbf --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_skin_id_list @@ -0,0 +1 @@ +erp5_commit \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_test_id_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_test_id_list new file mode 100644 index 0000000000000000000000000000000000000000..6140751ac11346a016ebd64b0016178c8f237a2f --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_test_id_list @@ -0,0 +1 @@ +test.erp5.testPortalPatchItem \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_tool_id_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_tool_id_list new file mode 100644 index 0000000000000000000000000000000000000000..e4cae5cc3d10735abbbf27f32afe25a22b80eef3 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_tool_id_list @@ -0,0 +1 @@ +portal_commits \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/template_workflow_id_list b/product/ERP5/bootstrap/erp5_business_package/bt/template_workflow_id_list new file mode 100644 index 0000000000000000000000000000000000000000..b30f1cd661395b6b47c61daa2c61702bb6538c72 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/template_workflow_id_list @@ -0,0 +1,5 @@ +business_commit_interaction_workflow +business_commit_validation_workflow +business_item_interaction_workflow +business_snapshot_validation_workflow +business_template_availability_workflow \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/title b/product/ERP5/bootstrap/erp5_business_package/bt/title new file mode 100644 index 0000000000000000000000000000000000000000..9c395ab2b79ca9ebe24c62ca558074f3b0fc4ea7 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/title @@ -0,0 +1 @@ +erp5_business_package \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_business_package/bt/version b/product/ERP5/bootstrap/erp5_business_package/bt/version new file mode 100644 index 0000000000000000000000000000000000000000..8a9ecc2ea99d607e92feae1656ddbf6fdd82a2c1 --- /dev/null +++ b/product/ERP5/bootstrap/erp5_business_package/bt/version @@ -0,0 +1 @@ +0.0.1 \ No newline at end of file diff --git a/product/ERP5/bootstrap/erp5_core/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml b/product/ERP5/bootstrap/erp5_core/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml index 221a4ad480222a9aaf7faf96125c5c9e19945a4d..2dd0d28083ae0fb090644a01327abe7eaae285d4 100644 --- a/product/ERP5/bootstrap/erp5_core/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml +++ b/product/ERP5/bootstrap/erp5_core/PortalTypeAllowedContentTypeTemplateItem/allowed_content_types.xml @@ -116,6 +116,7 @@ Business Template + Business Template V2 Trash Bin diff --git a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/TemplateTool_viewBusinessTemplateList/listbox.xml b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/TemplateTool_viewBusinessTemplateList/listbox.xml index 28332122c2bf05162fd751375e2924f0772d6999..0907ff06d9cdebc85cbbab05fcc8eb3b4e3d393d 100644 --- a/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/TemplateTool_viewBusinessTemplateList/listbox.xml +++ b/product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/TemplateTool_viewBusinessTemplateList/listbox.xml @@ -149,6 +149,10 @@ modification_date Modification Date + + portal_type + Portal Type + @@ -168,6 +172,10 @@ Business Template Business Template + + Business Template V2 + Business Template V2 + @@ -191,12 +199,16 @@ description Description + + portal_type + Portal Type + selection_name - business_template_selection + template_tool_selection sort diff --git a/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_allowed_content_type_list b/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_allowed_content_type_list index b96d28f3c77ee990a31bea6623104ee921925399..c6d4dd70838b3a9db996a2812c59a9501e2abe62 100644 --- a/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_allowed_content_type_list +++ b/product/ERP5/bootstrap/erp5_core/bt/template_portal_type_allowed_content_type_list @@ -60,5 +60,6 @@ Property Sheet | TALES Constraint Simulation Movement | Applied Rule Simulation Tool | Applied Rule Template Tool | Business Template +Template Tool | Business Template V2 Trash Tool | Trash Bin Types Tool | Base Type diff --git a/product/ERP5/interfaces/commit.py b/product/ERP5/interfaces/commit.py new file mode 100644 index 0000000000000000000000000000000000000000..221355bef502fd44f28f8ede16bd257ef3d69ae2 --- /dev/null +++ b/product/ERP5/interfaces/commit.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SA and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## +""" +Products.ERP5.interfaces.commit +""" + +from zope.interface import Interface + +class ICommit(Interface): + """Commit interface specification for ERP5 objects + + ICommitObject defines the set of function which helps in commiting any ERP5 + object or its property to Business Commit. + """ + + def getLatestDraftBusinessCommit(): + """ + Returns the lastest draft commit available where the current object + can be added + """ + + def createBusinessItem(layer=1, sign=1): + """ + Creates a Business Item object with the path of the current object inside + the latest Business Commit. + + layer -- Priority of the Business Item + sign -- Sign of the Business Item + + NOTE: It will still be needed to add the follow_up Business Template to + properly add the Business Item in Business Commit + """ + + def createBusinessPropertyItem(layer=1, sign=1): + """ + Creates a Business Property Item object with the path of the property for + the ERP5 object specified. + + + layer -- Priority of the Business Item + sign -- Sign of the Business Item + + NOTE: It will still be needed to add the follow_up Business Template to + properly add the Business Item in Business Commit + """ diff --git a/product/ERP5Type/Base.py b/product/ERP5Type/Base.py index 1e4c150ab76c44dd3656e1ef71fbe35b720c7c93..2affe3e29b360d54e9ba4059b63781313965be75 100644 --- a/product/ERP5Type/Base.py +++ b/product/ERP5Type/Base.py @@ -86,6 +86,7 @@ from Products.ERP5Type.Accessor.TypeDefinition import asDate from Products.ERP5Type.Message import Message from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod, super_user +from Products.ERP5Type.mixin.json_representable import JSONRepresentableMixin from zope.interface import classImplementsOnly, implementedBy @@ -675,7 +676,8 @@ class Base( CopyContainer, ActiveObject, OFS.History.Historical, ERP5PropertyManager, - PropertyTranslatableBuiltInDictMixIn + PropertyTranslatableBuiltInDictMixIn, + JSONRepresentableMixin, ): """ This is the base class for all ERP5 Zope objects. @@ -787,6 +789,13 @@ class Base( CopyContainer, pformat(rev1.__dict__), pformat(rev2.__dict__))) + def _delPropValue(self, property_name): + if self.hasProperty(property_name): + value = None + if property_name.endswith('_list'): + value = [] + self._setPropValue(property_name, value) + def _aq_dynamic(self, id): # ahah! disabled, thanks to portal type classes return None diff --git a/product/ERP5Type/Core/Folder.py b/product/ERP5Type/Core/Folder.py index 1778954894e86629b10edde68172ea9ca25d6880..e98fcd4c378bb121f6fab63969011b6fd486eb35 100644 --- a/product/ERP5Type/Core/Folder.py +++ b/product/ERP5Type/Core/Folder.py @@ -49,6 +49,8 @@ from Products.ERP5Type.Utils import sortValueList from Products.ERP5Type import Permissions from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Accessor import Base as BaseAccessor +from Products.ERP5Type.mixin.json_representable import JSONRepresentableMixin + try: from Products.CMFCore.CMFBTreeFolder import CMFBTreeFolder except ImportError: @@ -69,6 +71,7 @@ except ImportError: pass from DateTime import DateTime from random import randint +import uuid import os from zLOG import LOG, WARNING import warnings @@ -276,6 +279,12 @@ class FolderMixIn(ExtensionClass.Base): my_id = self._generateRandomId() return "%s.%03d-%s" %(current_date, node_number, my_id) + def _generateUniversalUniqueId(self): + """ + Generates a version 1 Universally Unique Identifier (UUID). + """ + return str(uuid.uuid1()) + # Getter defines to address migration of a site to ZODB Property Sheets, # otherwise installing erp5_property_sheets fails in generateNewId() as # getIdGenerator accessor does not exist yet @@ -562,7 +571,8 @@ HBTREE_HANDLER = 2 InitializeClass(FolderMixIn) -class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): +class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn, + JSONRepresentableMixin,): """ A Folder is a subclass of Base but not of XMLObject. Folders are not considered as documents and are therefore @@ -624,6 +634,9 @@ class Folder(CopyContainer, CMFBTreeFolder, CMFHBTreeFolder, Base, FolderMixIn): Title = Base.Title _setPropValue = Base._setPropValue _propertyMap = Base._propertyMap # are there any others XXX ? + # Required while Business Manager installation. Better to rely on properties + # from property sheet than on the attributes + _delPropValue = Base._delPropValue PUT_factory = None # XXX Prevent inheritance from PortalFolderBase description = None diff --git a/product/ERP5Type/ERP5Type.py b/product/ERP5Type/ERP5Type.py index af097c7f984cbd3e434d2f2edf4339c57abb0148..986d2b36cb64ceaa42a553466ec4aa1a6e4bd6de 100644 --- a/product/ERP5Type/ERP5Type.py +++ b/product/ERP5Type/ERP5Type.py @@ -226,6 +226,12 @@ class ERP5TypeInformation(XMLObject, # Declarative properties property_sheets = ( PropertySheet.BaseType, ) + _properties = ( + { 'id' : 'type_workflow', + 'type' : 'multiple selection', + 'mode' : 'w' }, + ) + acquire_local_roles = False property_sheet_list = () base_category_list = () @@ -330,6 +336,72 @@ class ERP5TypeInformation(XMLObject, # Acquisition editing interface # + def getTypeFilterContentType(self): + return + + def getTypeInitScriptId(self): + return + + security.declareProtected(Permissions.ModifyPortalContent, + 'getTypeWorkflowList') + def getTypeWorkflowList(self): + """Getter for 'type_workflow_list' property""" + pw = self.getPortalObject().portal_workflow + cbt = pw._chains_by_type + id = self.getId() + if cbt is not None and cbt.has_key(id): + workflow_list = list(cbt[id]) + else: + workflow_list = None + return workflow_list + + def hasTypeWorkflowList(self): + """ + Always return True. Overriden as general accessor is generated after the + use of this function while installing Business Manager + """ + return True + + security.declareProtected(Permissions.ModifyPortalContent, + 'setTypeWorkflowList') + def _setTypeWorkflowList(self, type_workflow_list): + """Override Setter for 'type_workflow' property""" + # We use setter to update the value for Workflow chain during the + # installation of Business Manager. This way, we would be able to + # modify workflow chain without the need of saving anything in + # type_workflow_list property. + portal = self.getPortalObject() + pw = portal.portal_workflow + cbt = pw._chains_by_type + # Create empty chains dict if it is empty + if cbt is None: + cbt = {} + id = self.getId() + + # If the type_workflow_list is empty, delete the key from workflow chains + if not type_workflow_list: + cbt[id] = [] + pw._chains_by_type = cbt + + # If type_workflow_list is '(Default)', don't do/update anything + elif type_workflow_list[0] != '(Default)': + + # If there is already key existing in cbt, then update it + if cbt is not None and cbt.has_key(id): + workflow_list = list(cbt[id]) + + if not workflow_list: + cbt[id] = sorted(type_workflow_list) + + # If the value in cbt is '(Default)', then update it only after removing + # default value + elif workflow_list[0] != '(Default)': + type_workflow_list = type_workflow_list.extend(workflow_list) + cbt[id] = sorted(type_workflow_list) + + # Update the chains dictionary for portal_workflow + pw._chains_by_type = cbt + security.declarePrivate('_guessMethodAliases') def _guessMethodAliases(self): """ Override this method to disable Method Aliases in ERP5. diff --git a/product/ERP5Type/Tool/PropertySheetTool.py b/product/ERP5Type/Tool/PropertySheetTool.py index bcfc8d4d02dd35ff536b3a104eaed0834520b735..08568a0de1b4a7a62e2b9e69c1d090dbd2af9771 100644 --- a/product/ERP5Type/Tool/PropertySheetTool.py +++ b/product/ERP5Type/Tool/PropertySheetTool.py @@ -63,17 +63,15 @@ class PropertySheetTool(BaseTool): bt_name = 'erp5_property_sheets' from Products.ERP5.ERP5Site import ERP5Generator ERP5Generator.bootstrap(self, bt_name, 'PropertySheetTemplateItem', ( - 'BaseType', - 'BusinessTemplate', - 'Folder', - 'SimpleItem', - 'Version', - 'Comment', - # the following ones are required to upgrade an existing site - 'Reference', - 'BaseCategory', - 'SQLIdGenerator', - )) + 'BaseType', + 'BusinessTemplate', + 'Folder', + 'SimpleItem', + 'Version', + 'Comment', + 'Reference', + 'BaseCategory', + 'SQLIdGenerator',)) def install(): from ZPublisher.BaseRequest import RequestContainer from Products.ERP5Type.Globals import get_request diff --git a/product/ERP5Type/Tool/TypesTool.py b/product/ERP5Type/Tool/TypesTool.py index 178cbe7411cc8e08abe36e612535f325403c7095..0ea0ffb38a3492e46c4303e590676e18f9ee988d 100644 --- a/product/ERP5Type/Tool/TypesTool.py +++ b/product/ERP5Type/Tool/TypesTool.py @@ -125,15 +125,10 @@ class TypesTool(TypeProvider): def _bootstrap(self): from Products.ERP5.ERP5Site import ERP5Generator ERP5Generator.bootstrap(self, 'erp5_core', 'PortalTypeTemplateItem', ( - 'Business Template', - 'Standard Property', - 'Acquired Property', - # the following ones are required to upgrade an existing site - 'Category Property', - # the following is needed to bootstrap Catalog Tool and default catalog - 'Catalog Tool', - )) - ERP5Generator.bootstrap_allow_type(self, 'Catalog Tool') + 'Business Template', + 'Standard Property', + 'Acquired Property', + 'Category Property')) def listContentTypes(self, container=None): """List content types from all providers diff --git a/product/ERP5Type/interfaces/json_representable.py b/product/ERP5Type/interfaces/json_representable.py new file mode 100644 index 0000000000000000000000000000000000000000..96c797d55fabdfa29fecf853bd592f0b0e9c3374 --- /dev/null +++ b/product/ERP5Type/interfaces/json_representable.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SA and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from zope.interface import Interface + +class IJSONRepresentable(Interface): + """ + An interface for objects that can be converted to JSON + and back to an ERP5 object. + + This can be useful if we want to use JSON as much + as possible in ERP5 in the future and ensure + that certain objects (not all) can be converted to JSON + back and forth + """ + + def asJSON(): + """ + Returns a JSON representation based on + propertysheets and portal properties + """ + + def fromJSON(): + """ + Updates an object based on a JSON representation + """ diff --git a/product/ERP5Type/interfaces/patchable.py b/product/ERP5Type/interfaces/patchable.py new file mode 100644 index 0000000000000000000000000000000000000000..2ebd4487da74933ec85185c3e5503b4a9dca33be --- /dev/null +++ b/product/ERP5Type/interfaces/patchable.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SA and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +from zope.interface import Interface + +class IPatchable(Interface): + """ + An interface for objects that can be patched. This is useful + to raise an exception for some objects that are not meant to be + supported by BusinessTemplatePatchItem + """ + + def patch(patch, path=None, unified_diff_selection=None): + """ + Apply a PortalPatch or PortalPatchOperation to an object + + unified_diff_selection -- a selection of lines in the unified diff + that will be applied + + path -- optional path in case one wants to patch only some properties + """ diff --git a/product/ERP5Type/mixin/json_representable.py b/product/ERP5Type/mixin/json_representable.py new file mode 100644 index 0000000000000000000000000000000000000000..02e7b257c507fa05e90cbfa1dc885b5c3834e139 --- /dev/null +++ b/product/ERP5Type/mixin/json_representable.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SA and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import json +import xmltodict +import zope.interface +from OFS import XMLExportImport +from StringIO import StringIO +from AccessControl import ClassSecurityInfo +from Products.ERP5Type.interfaces.json_representable import IJSONRepresentable +from Products.ERP5Type import Permissions +from Products.ERP5Type.Globals import InitializeClass + +class JSONRepresentableMixin: + """ + An implementation for IJSONRepresentable + """ + + # Declarative Security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + zope.interface.implements(IJSONRepresentable) + + security.declareProtected(Permissions.AccessContentsInformation, 'asJSON') + def asJSON(self): + """ + Generate a JSON representable content for ERP5 object + + Currently we use `XMLExportImport` to first convert the object to its XML + respresentation and then use xmltodict to convert it to dict and JSON + format finally + """ + dict_value = self._asDict() + # Convert the XML to json representation + return json.dumps(dict_value) + + security.declareProtected(Permissions.AccessContentsInformation, 'asDict') + def _asDict(self): + """ + Gets the dict representation of the object + """ + # Use OFS exportXML to first export to xml + f = StringIO() + XMLExportImport.exportXML(self._p_jar, self._p_oid, f) + + # Get the value of exported XML + xml_value = f.getvalue() + return xmltodict.parse(xml_value) + + def fromJSON(self, val): + """ + Updates an object, based on a JSON representation + """ + dict_value = json.loads(val) + + # Convert the dict_value to XML representation + xml_value = xmltodict.unparse(dict_value) + + f = StringIO(xml_value) + return XMLExportImport.importXML(self._p_jar, f) + +InitializeClass(JSONRepresentableMixin) diff --git a/product/ERP5Type/mixin/patchable.py b/product/ERP5Type/mixin/patchable.py new file mode 100644 index 0000000000000000000000000000000000000000..75a9840df7b82ee97586d0805b4d6a49cbaac531 --- /dev/null +++ b/product/ERP5Type/mixin/patchable.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2017 Nexedi SA and Contributors. All Rights Reserved. +# Ayush Tiwari +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + + +import zope.interface +from Products.ERP5Type.interfaces.patchable import IPatchable +from AccessControl import ClassSecurityInfo +from Products.ERP5Type import Permissions +from Products.ERP5Type.Globals import InitializeClass + +class PatchableMixin: + """ + An implementation of IPatchable + """ + + zope.interface.implements(IPatchable) + + # Declarative Security + security = ClassSecurityInfo() + security.declareObjectProtected(Permissions.AccessContentsInformation) + + security.declareProtected(Permissions.AccessContentsInformation, + 'patch') + def patch(patch, path=None, unified_diff_selection=None): + pass + +InitializeClass(PatchableMixin) diff --git a/product/ERP5Type/tests/ERP5TypeTestCase.py b/product/ERP5Type/tests/ERP5TypeTestCase.py index 9647fc76f9caf33ddd4d462f992a944abe43dc45..f7cb0aed80123efb5ea583c4ae6a9a073cefaf0c 100644 --- a/product/ERP5Type/tests/ERP5TypeTestCase.py +++ b/product/ERP5Type/tests/ERP5TypeTestCase.py @@ -1067,6 +1067,12 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin): if not quiet: ZopeTestCase._print('Adding %s business template ... ' % bt_title) bt = template_tool.download(url) + # If the bt is Business Manager, update the installation state + if bt.getPortalType() == 'Business Manager': + template_tool.updateInstallationState([bt]) + ZopeTestCase._print('(imported in %.3fs) ' % (time.time() - start)) + continue + if not quiet: ZopeTestCase._print('(imported in %.3fs) ' % (time.time() - start)) # For unit test, we accept installing business templates with @@ -1185,6 +1191,7 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin): self._installBusinessTemplateList(business_template_list, light_install=light_install, quiet=quiet) + self._recreateCatalog() self._updateTranslationTable() self._updateConversionServerConfiguration() @@ -1202,7 +1209,6 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin): if hot_reindexing: setattr(app,'isIndexable', 1) portal.portal_catalog.manage_hotReindexAll() - portal.portal_types.resetDynamicDocumentsOnceAtTransactionBoundary() self.tic(not quiet) diff --git a/product/ZSQLCatalog/SQLCatalog.py b/product/ZSQLCatalog/SQLCatalog.py index dfef42fdefcc7c26ca3fc2590d3b47c39d1d22d9..e79f65b4920d1cc957ec3153603ae4b0416238c1 100644 --- a/product/ZSQLCatalog/SQLCatalog.py +++ b/product/ZSQLCatalog/SQLCatalog.py @@ -1100,8 +1100,8 @@ class Catalog(Folder, ), ) - security.declarePrivate('isIndexable') - def isIndexable(self): + security.declarePrivate('isIndexingRequired') + def isIndexingRequired(self): """ This is required to check in many methods that the site root and zope root are indexable @@ -1109,8 +1109,8 @@ class Catalog(Folder, zope_root = self.getZopeRoot() site_root = self.getSiteRoot() # XXX-JPS - Why don't we use getPortalObject here ? - root_indexable = int(getattr(zope_root, 'isIndexable', 1)) - site_indexable = int(getattr(site_root, 'isIndexable', 1)) + root_indexable = int(getattr(zope_root, 'isIndexingRequired', 1)) + site_indexable = int(getattr(site_root, 'isIndexingRequired', 1)) if not (root_indexable and site_indexable): return False return True @@ -1157,7 +1157,7 @@ class Catalog(Folder, Similar problems may happen with relations and acquisition of uid values (ex. order_uid) with the risk of graph loops """ - if not self.getPortalObject().isIndexable(): + if not self.getPortalObject().isIndexingRequired(): return None with global_reserved_uid_lock: @@ -1322,7 +1322,8 @@ class Catalog(Folder, if idxs not in (None, []): LOG('ZSLQCatalog.SQLCatalog:catalogObjectList', WARNING, 'idxs is ignored in this function and is only provided to be compatible with CMFCatalogAware.reindexObject.') - if not self.getPortalObject().isIndexable(): + + if not self.getPortalObject().isIndexingRequired(): return object_path_dict = {} @@ -1507,7 +1508,7 @@ class Catalog(Folder, """ Set the path as deleted """ - if not self.getPortalObject().isIndexable(): + if not self.getPortalObject().isIndexingRequired(): return None if uid is None and path is not None: @@ -1540,7 +1541,7 @@ class Catalog(Folder, XXX Add filter of methods """ - if not self.getPortalObject().isIndexable(): + if not self.getPortalObject().isIndexingRequired(): return None if uid is None and path is not None: