def setUp(self): self.portal = self.layer['portal'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.pw = self.portal.portal_workflow self.imw = self.pw['incomingmail_workflow'] self.imail = sub_create(self.portal['incoming-mail'], 'dmsincomingmail', datetime.now(), 'test', **{'title': u'test'}) api.group.create('abc_group_encoder', 'ABC group encoder') self.portal.portal_setup.runImportStepFromProfile( 'profile-imio.dms.mail:singles', 'imiodmsmail-im_n_plus_1_wfadaptation', run_dependencies=False) sva = IMServiceValidation() n_plus_2_params = { 'validation_level': 2, 'state_title': u'Valider par le chef de département', 'forward_transition_title': u'Proposer au chef de département', 'backward_transition_title': u'Renvoyer au chef de département', 'function_title': u'chef de département' } adapt_is_applied = sva.patch_workflow('incomingmail_workflow', **n_plus_2_params) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.IMServiceValidation', 'incomingmail_workflow', True, **n_plus_2_params) for uid in get_registry_organizations(): self.portal.acl_users.source_groups.addPrincipalToGroup( 'chef', "%s_n_plus_2" % uid)
def test_task_transition(self): # task = createContentInContainer(self.imail, 'task', id='t1') task = get_object(oid='courrier1', ptype='dmsincomingmail')['tache1'] # no assigned_user and no TaskServiceValidation self.assertIsNone(task.assigned_user) api.content.transition(task, transition='do_to_assign') self.assertEqual(api.content.get_state(task), 'to_do') # assigned_user and no TaskServiceValidation api.content.transition(task, transition='back_in_created2') task.assigned_user = '******' api.content.transition(task, transition='do_to_assign') self.assertEqual(api.content.get_state(task), 'to_do') # no assigned_user but TaskServiceValidation but no user in groups api.content.transition(task, transition='back_in_created2') task.assigned_user = None add_applied_adaptation( 'imio.dms.mail.wfadaptations.TaskServiceValidation', 'task_workflow', False) api.content.transition(task, transition='do_to_assign') self.assertEqual(api.content.get_state(task), 'to_do') # no assigned_user but TaskServiceValidation and user in groups api.content.transition(task, transition='back_in_created2') api.group.create(groupname='{}_n_plus_1'.format(task.assigned_group), groups=['chef']) api.content.transition(task, transition='do_to_assign') self.assertEqual(api.content.get_state(task), 'to_assign')
def test_state_group_index(self): dguid = self.pgof['direction-generale'].UID() imail = sub_create( self.portal['incoming-mail'], 'dmsincomingmail', datetime.now(), 'id1', **{ 'title': u'test', 'treating_groups': dguid, 'assigned_user': u'chef' }) indexer = state_group_index(imail) self.assertEqual(indexer(), 'created') api.content.transition(obj=imail, to_state='proposed_to_manager') self.assertEqual(indexer(), 'proposed_to_manager') api.content.transition(obj=imail, to_state='proposed_to_agent') self.assertEqual(indexer(), 'proposed_to_agent') task = createContentInContainer(imail, 'task', assigned_group=dguid) indexer = state_group_index(task) self.assertEqual(indexer(), 'created') # simulate adaptation add_applied_adaptation( 'imio.dms.mail.wfadaptations.TaskServiceValidation', 'task_workflow', False) api.group.create(groupname='{}_n_plus_1'.format(dguid), groups=['chef']) api.content.transition(obj=task, transition='do_to_assign') self.assertEqual(indexer(), 'to_assign') set_dms_config(['review_states', 'task'], OrderedDict([('to_assign', { 'group': '_n_plus_1', 'org': 'assigned_group' })])) self.assertEqual(indexer(), 'to_assign,%s' % dguid)
def om_n_plus_1_wfadaptation(context): """ Add n_plus_1 level in outgoingmail_workflow """ if not context.readDataFile("imiodmsmail_singles_marker.txt"): return logger.info('Apply n_plus_1 level on outgoingmail_workflow') site = context.getSite() n_plus_1_params = { 'validation_level': 1, 'state_title': u'À valider par le chef de service', 'forward_transition_title': u'Proposer au chef de service', 'backward_transition_title': u'Renvoyer au chef de service', 'function_title': u'N+1', 'validated_from_created': False } sva = OMServiceValidation() adapt_is_applied = sva.patch_workflow('outgoingmail_workflow', **n_plus_1_params) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.OMServiceValidation', 'outgoingmail_workflow', True, **n_plus_1_params) # Add users to activated groups if 'chef' in [u.id for u in api.user.get_users()]: for uid in get_registry_organizations(): site.acl_users.source_groups.addPrincipalToGroup( 'chef', "%s_n_plus_1" % uid)
def test_add_applied_adaptation(self): params = {'param1': 'foo', 'param2': 'bar'} add_applied_adaptation(u'adaptation1', u'workflow2', **params) self.assertIn( {u'workflow': u'workflow2', u'adaptation': u'adaptation1', u'parameters': u'{"param1": "foo", "param2": "bar"}' }, api.portal.get_registry_record(RECORD_NAME), ) with self.assertRaises(AdaptationAlreadyAppliedException): add_applied_adaptation(u'adaptation1', u'workflow1', **params)
def task_n_plus_1_wfadaptation(context): """ Add n_plus_1 level in task_workflow """ if not context.readDataFile("imiodmsmail_singles_marker.txt"): return logger.info('Apply n_plus_1 level on task_workflow') site = context.getSite() sva = TaskServiceValidation() adapt_is_applied = sva.patch_workflow('task_workflow', **{}) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.TaskServiceValidation', 'task_workflow', True, **{}) # Add users to activated groups if 'chef' in [u.id for u in api.user.get_users()]: for uid in get_registry_organizations(): site.acl_users.source_groups.addPrincipalToGroup( 'chef', "%s_n_plus_1" % uid)
def remove_service_chief(self): # remove collection logger.info('Modifying workflows') for folder in (self.imf['mail-searches'], self.omf['mail-searches']): if 'searchfor_proposed_to_service_chief' in folder: api.content.delete( obj=folder['searchfor_proposed_to_service_chief']) # clean dms config for ptype in ('dmsincomingmail', 'dmsoutgoingmail', 'task'): # i_e ok config = get_dms_config(['review_levels', ptype]) if '_validateur' in config: del config['_validateur'] set_dms_config(keys=['review_levels', ptype], value=config) config = get_dms_config(['review_states', ptype]) if 'proposed_to_service_chief' in config: del config['proposed_to_service_chief'] set_dms_config(keys=['review_states', ptype], value=config) def remove_localrole_validateur(dic1): for state1 in dic1: if 'validateur' in dic1[state1]: del dic1[state1]['validateur'] # clean local roles for ptype in ('dmsincomingmail', 'dmsoutgoingmail'): # i_e ok fti = getUtility(IDexterityFTI, name=ptype) lr = getattr(fti, 'localroles') lrg = lr['static_config'] if 'proposed_to_service_chief' in lrg: del lrg['proposed_to_service_chief'] remove_localrole_validateur(lrg) lrg = lr['treating_groups'] if 'proposed_to_service_chief' in lrg: del lrg['proposed_to_service_chief'] remove_localrole_validateur(lrg) lrg = lr['recipient_groups'] if 'proposed_to_service_chief' in lrg: del lrg['proposed_to_service_chief'] remove_localrole_validateur(lrg) lr._p_changed = True # on task fti = getUtility(IDexterityFTI, name='task') lr = getattr(fti, 'localroles') lrg = lr['assigned_group'] if 'validateur' in lrg['to_do']: remove_localrole_validateur(lrg) lrg = lr['parents_assigned_groups'] if 'validateur' in lrg['to_do']: remove_localrole_validateur(lrg) lr._p_changed = True # update registry lst = api.portal.get_registry_record( 'imio.actionspanel.browser.registry.IImioActionsPanelConfig.transitions' ) for entry in ('dmsincomingmail.back_to_service_chief|', 'dmsoutgoingmail.back_to_service_chief|'): if entry not in lst: break lst.remove(entry) else: api.portal.set_registry_record( 'imio.actionspanel.browser.registry.IImioActionsPanelConfig.transitions', lst) # update remark states for attr in ('imail_remark_states', 'omail_remark_states'): lst = (api.portal.get_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.{}'.format( attr)) or []) if 'proposed_to_service_chief' in lst: lst.remove('proposed_to_service_chief') api.portal.set_registry_record( 'imio.dms.mail.browser.settings.IImioDmsMailConfig.{}'. format(attr), lst) # Manage workflows and wfadaptations functions = get_registry_functions() if 'validateur' not in [fct['fct_id'] for fct in functions]: return # apply the following only once def remove_adaptation_from_registry(name): record = api.portal.get_registry_record(RECORD_NAME) api.portal.set_registry_record( RECORD_NAME, [d for d in record if d['adaptation'] != name]) # reset workflows self.runProfileSteps('imio.dms.mail', steps=['workflow']) # self.portal.portal_workflow.updateRoleMappings() # done later # Apply workflow adaptations if necessary applied_wfa = [dic['adaptation'] for dic in get_applied_adaptations()] n_plus_1_params = { 'validation_level': 1, 'state_title': u'À valider par le chef de service', 'forward_transition_title': u'Proposer au chef de service', 'backward_transition_title': u'Renvoyer au chef de service', 'function_title': u'N+1' } task_adapt = True for wkf, acr in (('incomingmail_workflow', 'IM'), ('outgoingmail_workflow', 'OM')): if u'imio.dms.mail.wfadaptations.{}SkipProposeToServiceChief'.format( acr) in applied_wfa: remove_adaptation_from_registry( u'imio.dms.mail.wfadaptations.{}SkipProposeToServiceChief'. format(acr)) task_adapt = False if acr == 'OM': folder = self.omf['mail-searches'] if folder['to_validate'].enabled: folder['to_validate'].enabled = False folder['to_validate'].reindexObject() else: logger.info( 'Applying {}ServiceValidation wf adaptation'.format(acr)) sva = getattr(wfadaptations, '{}ServiceValidation'.format(acr))() sva.reapply = True adapt_is_applied = sva.patch_workflow(wkf, **n_plus_1_params) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.{}ServiceValidation'. format(acr), wkf, True, **n_plus_1_params) # update task_workflow update_task_workflow(self.portal) if task_adapt: tsva = TaskServiceValidation() adapt_is_applied = tsva.patch_workflow('task_workflow', **{}) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.TaskServiceValidation', 'task_workflow', False) else: # update collections folder = self.portal['tasks']['task-searches'] for cid in ('to_assign', 'to_close'): if folder[cid].enabled: folder[cid].enabled = False folder[cid].reindexObject() invalidate_cachekey_volatile_for( 'collective.eeafaceted.collectionwidget.cachedcollectionvocabulary' ) # replace EmergencyZoneAdaptation im_workflow = self.wtool['incomingmail_workflow'] if u'imio.dms.mail.wfadaptations.EmergencyZone' in applied_wfa: state = im_workflow.states['proposed_to_manager'] state.title = u'À valider par le CZ'.encode('utf8') for tr, tit in (('back_to_manager', u'Renvoyer au CZ'), ('propose_to_manager', u'Proposer au CZ')): transition = im_workflow.transitions[tr] transition.title = tit.encode('utf8') logger.info('Removing EmergencyZone wf adaptation') remove_adaptation_from_registry( u'imio.dms.mail.wfadaptations.EmergencyZone') # redo OMToPrintAdaptation if u'imio.dms.mail.wfadaptations.OMToPrint' in applied_wfa: logger.info('Applying OMToPrint wf adaptation') tpa = OMToPrintAdaptation() tpa.patch_workflow('outgoingmail_workflow') # redo IMPreManagerValidation if u'imio.dms.mail.wfadaptations.IMPreManagerValidation' in applied_wfa: logger.info('Applying IMPreManagerValidation wf adaptation') params = [ dic['parameters'] for dic in get_applied_adaptations() if dic['adaptation'] == u'imio.dms.mail.wfadaptations.IMPreManagerValidation' ][0] remove_adaptation_from_registry( u'imio.dms.mail.wfadaptations.IMPreManagerValidation') del params['collection_title'] pmva = IMPreManagerValidation() adapt_is_applied = pmva.patch_workflow('incomingmail_workflow', **params) if adapt_is_applied: add_applied_adaptation( 'imio.dms.mail.wfadaptations.IMPreManagerValidation', 'incoming_mail', False, **params) # update wf history to replace review_state and correct history config = { 'dmsincomingmail': { 'wf': 'incomingmail_workflow', # i_e ok 'st': { 'proposed_to_service_chief': 'proposed_to_n_plus_1' }, 'tr': { 'propose_to_service_chief': 'propose_to_n_plus_1', 'back_to_service_chief': 'back_to_n_plus_1' } }, 'dmsoutgoingmail': { 'wf': 'outgoingmail_workflow', 'st': { 'proposed_to_service_chief': 'proposed_to_n_plus_1' }, 'tr': { 'propose_to_service_chief': 'propose_to_n_plus_1', 'back_to_service_chief': 'back_to_n_plus_1' } } } for pt in config: logger.info('Updating history and indexes of {} type'.format(pt)) for i, brain in enumerate(self.catalog(portal_type=pt), 1): obj = brain.getObject() if i % 10000 == 0: logger.info('On brain {}'.format(i)) # update history wfh = [] wkf = self.wtool[config[pt]['wf']] for status in obj.workflow_history.get(config[pt]['wf']): # replace old state by new one if status['review_state'] in config[pt]['st']: status['review_state'] = config[pt]['st'][ status['review_state']] # replace old transition by new one if status['action'] in config[pt]['tr']: status['action'] = config[pt]['tr'][status['action']] wfh.append(status) obj.workflow_history[config[pt]['wf']] = tuple(wfh) # update permissions and roles wkf.updateRoleMappingsFor(obj) # update state_group (use dms_config), permissions, state obj.reindexObject(idxs=[ 'allowedRolesAndUsers', 'review_state', 'state_group' ]) for child in obj.objectValues(): child.reindexObject(idxs=['allowedRolesAndUsers']) # migrate plone groups # First unregister group deletion handlers globalSiteManager.unregisterHandler(pg_group_deleted, (IGroupDeletedEvent, )) globalSiteManager.unregisterHandler(group_deleted, (IGroupDeletedEvent, )) globalSiteManager.unregisterHandler(group_assignment, (IPrincipalAddedToGroupEvent, )) globalSiteManager.unregisterHandler( group_unassignment, (IPrincipalRemovedFromGroupEvent, )) # move users from _validateur to _n_plus_1 for group in api.group.get_groups(): if group.id.endswith('_validateur'): org = group.id.split('_')[0] np1group = api.group.get('{}_n_plus_1'.format(org)) if np1group: for user in api.user.get_users(group=group): api.group.add_user(group=np1group, user=user) api.group.remove_user(group=group, user=user) api.group.delete(group=group) # register again group deletion handlers globalSiteManager.registerHandler(pg_group_deleted, (IGroupDeletedEvent, )) globalSiteManager.registerHandler(group_deleted, (IGroupDeletedEvent, )) globalSiteManager.registerHandler(group_assignment, (IPrincipalAddedToGroupEvent, )) globalSiteManager.registerHandler(group_unassignment, (IPrincipalRemovedFromGroupEvent, )) # remove validateur function functions = get_registry_functions() if 'validateur' in [fct['fct_id'] for fct in functions]: set_registry_functions( [fct for fct in functions if fct['fct_id'] != 'validateur'])