From e489380e50647d91a08b35f3ed24341e6212d520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com> Date: Sun, 22 Jan 2023 06:48:37 +0100 Subject: [PATCH] BusinessTemplate: make portal type role export stable with > 10 roles This sort was based on the id of the role definition but this did not work when the type definition had more than 10 documents, because: >>> sorted(['1', '2', '10']) ['1', '10', '2'] This switches to an approach of converting the id to integer, with a fallback in case the id generator is customized. --- .../test.erp5.testBusinessTemplate.py | 55 +++++++++++++++++++ product/ERP5/Document/BusinessTemplate.py | 10 +++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testBusinessTemplate.py b/bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testBusinessTemplate.py index 36f4dee213..b3dacce472 100644 --- a/bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testBusinessTemplate.py +++ b/bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testBusinessTemplate.py @@ -159,6 +159,8 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): if 'Geek Object' in self.getTypeTool().objectIds(): self.getTypeTool().manage_delObjects(['Geek Object', 'Geek Module']) + if 'Dummy Type' in self.getTypeTool().objectIds(): + self.getTypeTool().manage_delObjects(['Dummy Type']) if 'geek_module' in self.getPortal().objectIds(): self.getPortal().manage_delObjects(['geek_module']) if 'geek_workflow' in self.getWorkflowTool().objectIds(): @@ -6555,6 +6557,59 @@ class TestBusinessTemplate(BusinessTemplateMixin): self.assertNotEqual(None, self.portal.portal_actions.getActionInfo('object_view/test_global_action')) + def test_role_information_stable_export(self): + dummy_type = self.portal.portal_types.newContent( + portal_type='Base Type', + id='Dummy Type', + type_class='Folder' + ) + + for i in range(20): + dummy_type.newContent( + portal_type='Role Information', + title='Dummy Role Definition', + description='Role %s' % i, + role_name_list=('Assignee', ), + role_base_category_list=('group',), + role_category_list=('group/g1',)) + + bt = self.portal.portal_templates.newContent( + portal_type='Business Template', + title='test_bt_%s' % self.id(), + template_portal_type_id_list=('Dummy Type',), + template_portal_type_role_list=('Dummy Type', )) + self.tic() + bt.build() + self.tic() + export_dir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, export_dir) + bt.export(path=export_dir, local=True) + + with open(os.path.join(export_dir, 'PortalTypeRolesTemplateItem', 'Dummy%20Type.xml')) as f: + role_content = f.read() + self.tic() + new_bt = self.portal.portal_templates.download(url='file://%s' % export_dir) + + self.portal.portal_types.manage_delObjects(['Dummy Type']) + self.tic() + new_bt.install() + + dummy_type = self.portal.portal_types['Dummy Type'] + self.assertEqual( + [rd.getRoleNameList() for rd in dummy_type.contentValues(portal_type='Role Information')], + [['Assignee']] * 20 + ) + + # rebuild and check the output is same + bt.build() + self.tic() + export_dir = tempfile.mkdtemp() + self.addCleanup(shutil.rmtree, export_dir) + bt.export(path=export_dir, local=True) + + with open(os.path.join(export_dir, 'PortalTypeRolesTemplateItem', 'Dummy%20Type.xml')) as f: + self.assertEqual(f.read(), role_content) + def test_indexation_of_updated_path_item(self): """Tests indexation on updated paths item. They should keep their uid and still be available to catalog diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py index ec047cb55a..7ce227aaa9 100644 --- a/product/ERP5/Document/BusinessTemplate.py +++ b/product/ERP5/Document/BusinessTemplate.py @@ -3462,7 +3462,15 @@ class PortalTypeRolesTemplateItem(BaseTemplateItem): type_role_dict[k] = v if 'id' in type_role_dict: type_role_list.append(type_role_dict) - type_role_list.sort(key=lambda x: (x.get('title'), x['object_id'],)) + + def sort_key(o): + try: + int_id = int(o['object_id']) + except ValueError: + # When the container does not use numerical ids + int_id = obj[o['object_id']].getCreationDate() + return (o.get('title'), int_id) + type_role_list.sort(key=sort_key) # Function to generate XML Code Manually def generateXml(self, path=None): -- 2.30.9