From 96e782dcb96f4405b0ff32cdff31e61e3db21deb Mon Sep 17 00:00:00 2001
From: Kazuhiko Shiozaki <kazuhiko@nexedi.com>
Date: Tue, 21 Apr 2009 05:27:34 +0000
Subject: [PATCH] support removal of allowed_content_type, hidden_content_type,
 property_sheet and base_category for portal type in Business Templates.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@26534 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/Document/BusinessTemplate.py  | 25 ++++++--
 product/ERP5/tests/testBusinessTemplate.py | 66 +++++++++++++++++++++-
 2 files changed, 84 insertions(+), 7 deletions(-)

diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py
index 2fa6b6c844..b0c01544a1 100644
--- a/product/ERP5/Document/BusinessTemplate.py
+++ b/product/ERP5/Document/BusinessTemplate.py
@@ -1660,6 +1660,7 @@ class PortalTypeAllowedContentTypeTemplateItem(BaseTemplateItem):
   name = 'Allowed Content Type'
   xml_tag = 'allowed_content_type_list'
   class_property = 'allowed_content_types'
+  business_template_class_property = '_portal_type_allowed_content_type_item'
 
   def build(self, context, **kw):
     types_tool = self.getPortalObject().portal_types
@@ -1762,7 +1763,13 @@ class PortalTypeAllowedContentTypeTemplateItem(BaseTemplateItem):
     pt = p.unrestrictedTraverse('portal_types')
     update_dict = kw.get('object_to_update')
     force = kw.get('force')
-    for key in self._objects.keys():
+    installed_bt = kw.get('installed_bt')
+    if installed_bt is not None:
+      old_objects = getattr(installed_bt,
+                            self.business_template_class_property)._objects
+    else:
+      old_objects = {}
+    for key in set(self._objects.keys()).union(set(old_objects.keys())):
       if update_dict.has_key(key) or force:
         if not force:
           action = update_dict[key]
@@ -1774,13 +1781,18 @@ class PortalTypeAllowedContentTypeTemplateItem(BaseTemplateItem):
         except AttributeError:
           LOG("portal types not found : ", 100, portal_id)
           continue
-        property_list = self._objects[key]
+        property_list = self._objects.get(key, [])
+        old_property_list = old_objects.get(key, ())
         object_property_list = getattr(portal_type, self.class_property, ())
         if len(object_property_list) > 0:
           # merge differences between portal types properties
-          # only add new, do not remove
+          # for example:
+          # * current value : [A,B,C]
+          # * in new BT : [A,D]
+          # * in old BT : [A,B]
+          # -> [A,D,C] i.e. C is merged but B is not merged
           for id in object_property_list:
-            if id not in property_list:
+            if id not in property_list and id not in old_property_list:
               property_list.append(id)
         setattr(portal_type, self.class_property, tuple(property_list))
 
@@ -1813,6 +1825,7 @@ class PortalTypeHiddenContentTypeTemplateItem(PortalTypeAllowedContentTypeTempla
   name = 'Hidden Content Type'
   xml_tag = 'hidden_content_type_list'
   class_property = 'hidden_content_type_list'
+  business_template_class_property = '_portal_type_hidden_content_type_item'
 
 
 class PortalTypePropertySheetTemplateItem(PortalTypeAllowedContentTypeTemplateItem):
@@ -1820,6 +1833,7 @@ class PortalTypePropertySheetTemplateItem(PortalTypeAllowedContentTypeTemplateIt
   name = 'Property Sheet'
   xml_tag = 'property_sheet_list'
   class_property = 'property_sheet_list'
+  business_template_class_property = '_portal_type_property_sheet_item'
 
 
 class PortalTypeBaseCategoryTemplateItem(PortalTypeAllowedContentTypeTemplateItem):
@@ -1827,6 +1841,7 @@ class PortalTypeBaseCategoryTemplateItem(PortalTypeAllowedContentTypeTemplateIte
   name = 'Base Category'
   xml_tag = 'base_category_list'
   class_property = 'base_category_list'
+  business_template_class_property = '_portal_type_base_category_item'
 
 
 class CatalogMethodTemplateItem(ObjectTemplateItem):
@@ -4777,7 +4792,7 @@ Business Template is a set of definitions, such as skins, portal types and categ
         for item_name in self._item_name_list:
           item = getattr(self, item_name, None)
           if item is not None:
-            item.install(self, force=force, object_to_update=object_to_update, trashbin=trashbin)
+            item.install(self, force=force, object_to_update=object_to_update, trashbin=trashbin, installed_bt=installed_bt)
 
       # update catalog if necessary
       if force and self.isCatalogUpdatable():
diff --git a/product/ERP5/tests/testBusinessTemplate.py b/product/ERP5/tests/testBusinessTemplate.py
index bee59df3c0..d7afe83a41 100644
--- a/product/ERP5/tests/testBusinessTemplate.py
+++ b/product/ERP5/tests/testBusinessTemplate.py
@@ -329,10 +329,38 @@ class TestBusinessTemplate(ERP5TypeTestCase, LogInterceptor):
     module_type.filter_content_types = 1
     module_type.allowed_content_types = ('Geek Object',)
     module_type.hidden_content_type_list = ('Geek Object',)
+    module_type.base_category_list = ('destination',)
+    module_type.property_sheet_list = ('Version',)
     sequence.edit(module_ptype_id=module_type.getId(),
           module_ptype_filter_content_types=module_type.filter_content_types,
           module_ptype_allowed_content_types=module_type.allowed_content_types,
-          module_ptype_hidden_content_type_list=module_type.hidden_content_type_list)
+          module_ptype_hidden_content_type_list=module_type.hidden_content_type_list,
+          module_ptype_base_category_list=module_type.base_category_list,
+          module_ptype_property_sheet_list=module_type.property_sheet_list)
+
+  def stepModifyPortalTypeInBusinessTemplate(self, sequence=None, sequence_list=None, **kw):
+    """
+    Modify Portal Type
+    * remove Geek Object and add Geek Module in allowed_content_type
+    * empty hidden_content_type
+    * remove 'destination' and add 'source' in base_category_list
+    * empty property_sheet_list
+    """
+    pt = self.getTypeTool()
+    module_type = pt._getOb('Geek Module', None)
+    self.failUnless(module_type is not None)
+    module_type.allowed_content_types = list(module_type.allowed_content_types) + ['Geek Module']
+    module_type.base_category_list = list(module_type.base_category_list) + ['source']
+    bt = sequence.get('current_bt', None)
+    self.failUnless(bt is not None)
+    bt.edit(template_portal_type_allowed_content_type=('Geek Module | Geek Module',),
+            template_portal_type_hidden_content_type=(),
+            template_portal_type_base_category=('Geek Module | source',),
+            template_portal_type_property_sheet=())
+    sequence.edit(module_ptype_allowed_content_types=('Geek Module',),
+                  module_ptype_hidden_content_type_list=(),
+                  module_ptype_base_category_list=('source',),
+                  module_ptype_property_sheet_list=())
 
   def stepAddPortalTypeToBusinessTemplate(self, sequence=None, sequence_list=None, **kw):
     """
@@ -397,6 +425,10 @@ class TestBusinessTemplate(ERP5TypeTestCase, LogInterceptor):
         sequence.get('module_ptype_hidden_content_type_list'))
     self.assertEquals(module_type.filter_content_types,
         sequence.get('module_ptype_filter_content_types'))
+    self.assertEquals(module_type.base_category_list,
+        sequence.get('module_ptype_base_category_list'))
+    self.assertEquals(module_type.property_sheet_list,
+        sequence.get('module_ptype_property_sheet_list'))
     object_type = pt._getOb(object_id, None)
     self.failUnless(object_type is not None)
 
@@ -2386,7 +2418,11 @@ class TestBusinessTemplate(ERP5TypeTestCase, LogInterceptor):
       prop_type = prop['type']
       pid = prop['id']
       if pid in ('id', 'uid', 'rid', 'sid', 'id_group', 'last_id',
-                'install_object_list_list', 'title', 'version', 'description'):
+                 'install_object_list_list', 'title', 'version', 'description',
+                 'template_portal_type_allowed_content_type_list',
+                 'template_portal_type_hidden_content_type_list',
+                 'template_portal_type_property_sheet_list',
+                 'template_portal_type_base_category_list'):
           continue
       if prop_type == 'text' or prop_type == 'string':
         prop_dict[pid] = ''
@@ -2540,6 +2576,32 @@ class TestBusinessTemplate(ERP5TypeTestCase, LogInterceptor):
                        CheckNoTrashBin \
                        CheckSkinsLayers \
                        CheckPortalTypeExists \
+                       CreateSecondBusinessTemplate \
+                       UseSecondBusinessTemplate \
+                       AddPortalTypeToBusinessTemplate \
+                       FillPortalTypesFields \
+                       ModifyPortalTypeInBusinessTemplate \
+                       CheckModifiedBuildingState \
+                       CheckNotInstalledInstallationState \
+                       BuildBusinessTemplate \
+                       CheckBuiltBuildingState \
+                       CheckNotInstalledInstallationState \
+                       CheckObjectPropertiesInBusinessTemplate \
+                       SaveBusinessTemplate \
+                       CheckBuiltBuildingState \
+                       CheckNotInstalledInstallationState \
+                       RemoveBusinessTemplate \
+                       RemoveAllTrashBins \
+                       ImportBusinessTemplate \
+                       UseImportBusinessTemplate \
+                       CheckBuiltBuildingState \
+                       CheckNotInstalledInstallationState \
+                       InstallBusinessTemplate \
+                       Tic \
+                       CheckInstalledInstallationState \
+                       CheckBuiltBuildingState \
+                       CheckSkinsLayers \
+                       CheckPortalTypeExists \
                        UninstallBusinessTemplate \
                        CheckBuiltBuildingState \
                        CheckNotInstalledInstallationState \
-- 
2.30.9