def mayEvaluateCompleteness(self): '''Completeness can be evaluated by the finance precontroller.''' item = self.getSelf() if item.isDefinedInTool(): return False # finances advice asked? finance_org_uid = finance_group_uid() finance_org_cec_uid = finance_group_cec_uid() if finance_org_uid not in item.adviceIndex and \ finance_org_cec_uid not in item.adviceIndex: return False # bypass for Managers tool = api.portal.get_tool('portal_plonemeeting') if tool.isManager(realManagers=True): return True # relevant state? cfg = tool.getMeetingConfig(item) if item.query_state() not in finances_give_advice_states(cfg): return False # current user is pre-controller for asked advice? userGroups = tool.get_plone_groups_for_user() if '%s_financialprecontrollers' % finance_org_uid not in userGroups and \ '%s_financialprecontrollers' % finance_org_cec_uid not in userGroups: return False return True
def _will_ask_completeness_eval_again(self): ''' ''' res = False if finance_group_uid() in self.context.adviceIndex or \ finance_group_cec_uid() in self.context.adviceIndex: res = super(MeetingItemPROVHainautWorkflowActions, self)._will_ask_completeness_eval_again() return res
def test_CompletenessEvaluationAskedAgain(self): """When item is sent for second+ time to the finances, completeness is automatically set to asked again except for finance_group_no_cec_uid.""" self.changeUser('dgen') item_df1 = self.create('MeetingItem', optionalAdvisers=((finance_group_uid() + '__rowid__unique_id_002', ))) item_df2 = self.create('MeetingItem', optionalAdvisers=((finance_group_cec_uid(), ))) item_df3 = self.create( 'MeetingItem', optionalAdvisers=((finance_group_no_cec_uid(), ))) for tr in [ 'proposeToValidationLevel1', 'proposeToValidationLevel2', 'wait_advices_from_proposedToValidationLevel2' ]: self.do(item_df1, tr) self.do(item_df2, tr) self.do(item_df3, tr) self.assertEqual(item_df1.getCompleteness(), 'completeness_not_yet_evaluated') self.assertEqual(item_df2.getCompleteness(), 'completeness_not_yet_evaluated') self.assertEqual(item_df3.getCompleteness(), 'completeness_evaluation_not_required') # incomplete, return item_df1.setCompleteness('completeness_incomplete') item_df2.setCompleteness('completeness_incomplete') self.changeUser('dfin') self.do(item_df1, 'backTo_proposedToValidationLevel2_from_waiting_advices') self.do(item_df2, 'backTo_proposedToValidationLevel2_from_waiting_advices') self.do(item_df3, 'backTo_proposedToValidationLevel2_from_waiting_advices') # ask again self.changeUser('dgen') self.assertEqual(item_df1.getCompleteness(), 'completeness_incomplete') self.assertEqual(item_df2.getCompleteness(), 'completeness_incomplete') # manipulate completeness, like if we changed from DF3 to DF2 item_df2.setCompleteness('completeness_evaluation_not_required') self.assertEqual(item_df3.getCompleteness(), 'completeness_evaluation_not_required') self.do(item_df1, 'wait_advices_from_proposedToValidationLevel2') self.do(item_df2, 'wait_advices_from_proposedToValidationLevel2') self.do(item_df3, 'wait_advices_from_proposedToValidationLevel2') self.assertEqual(item_df1.getCompleteness(), 'completeness_evaluation_asked_again') self.assertEqual(item_df2.getCompleteness(), 'completeness_evaluation_asked_again') self.assertEqual(item_df3.getCompleteness(), 'completeness_evaluation_not_required')
def _adviceDelayMayBeStarted(self, org_uid): """Delay is started when advice no more at controllers states.""" res = True if org_uid == finance_group_uid(): item = self.getSelf() adviceObj = item.getAdviceObj(org_uid) if not adviceObj or adviceObj.query_state() in [ 'advicecreated', 'proposed_to_financial_controller' ]: res = False if res: res = super(CustomMeetingItem, self)._adviceDelayMayBeStarted(org_uid) return res
def _setupFinancesGroup(self): '''Configure finances group.''' self._addPrincipalToGroup('pmAdviser2', '{0}_advisers'.format(finance_group_uid())) # respective _financesXXX groups self._addPrincipalToGroup('pmAdviser2', '{0}_financialprecontrollers'.format(finance_group_uid())) self._addPrincipalToGroup('pmAdviser2', '{0}_financialcontrollers'.format(finance_group_uid())) self._addPrincipalToGroup('pmAdviser2', '{0}_financialeditors'.format(finance_group_uid())) self._addPrincipalToGroup('pmAdviser2', '{0}_financialreviewers'.format(finance_group_uid())) self._addPrincipalToGroup('pmAdviser2', '{0}_financialmanagers'.format(finance_group_uid()))
def getCustomAdviceMessageFor(self, advice): '''If we are on a finance advice that is still not giveable because the item is not 'complete', we display a clear message.''' item = self.getSelf() finance_org_uids = (finance_group_uid(), finance_group_cec_uid()) if advice['id'] in finance_org_uids and \ not advice['advice_addable']: finance_org = get_organization(advice['id']) tool = api.portal.get_tool('portal_plonemeeting') cfg = tool.getMeetingConfig(item) # item in state giveable but item not complete if item.query_state() in finance_org.get_item_advice_states(cfg): if not self._is_complete(): return { 'displayDefaultComplementaryMessage': False, 'displayAdviceReviewState': True, 'customAdviceMessage': translate( 'finance_advice_not_giveable_because_item_not_complete', domain="PloneMeeting", context=item.REQUEST, default= "Advice is still not giveable because item is not considered complete." ) } # delay still not started when advice created/proposed_to_controller if not item.adapted()._adviceDelayMayBeStarted(advice['id']): return { 'displayDefaultComplementaryMessage': False, 'displayAdviceReviewState': True, 'customAdviceMessage': translate('finance_advice_delay_still_not_started', domain="PloneMeeting", context=item.REQUEST, default="Advice delay is still not started.") } return { 'displayDefaultComplementaryMessage': True, 'displayAdviceReviewState': True, 'customAdviceMessage': None }
def get_extra_adviser_infos(self): ''' ''' infos = {} infos[finance_group_uid()] = { 'portal_type': 'meetingadvicefinances', 'base_wf': 'meetingadvicefinances_workflow', 'wf_adaptations': ['add_advicecreated_state'] } infos[finance_group_cec_uid()] = { 'portal_type': 'meetingadvicefinancescec', 'base_wf': 'meetingadvicefinancesmanager_workflow', 'wf_adaptations': ['add_advicecreated_state'] } infos[finance_group_no_cec_uid()] = { 'portal_type': 'meetingadvicefinancesnocec', 'base_wf': 'meetingadvicefinanceseditor_workflow', 'wf_adaptations': [] } return infos
def _configureFinancesAdvice(self, cfg): """ """ # add finances group self._createFinancesGroup() # put users in finances group self._setupFinancesGroup() # configure customAdvisers for 'meeting-config-college' # turn FINANCE_GROUP_ID into relevant org UID customAdvisers = deepcopy(provhainaut_import_data.collegeMeeting.customAdvisers) for customAdviser in customAdvisers: customAdviser['org'] = finance_group_uid() cfg.setCustomAdvisers(customAdvisers) # configure usedAdviceTypes cfg.setUsedAdviceTypes(('positive', 'positive_with_remarks', 'negative', 'nil', 'positive_finance', 'positive_with_remarks_finance', 'negative_finance', 'not_given_finance'))
def test_FinancesAdvicesWorkflow(self): """ Test finances advices workflow. """ def _check_date(item, modified_date, volatile_date): '''Check that item modified date was updated.''' new_modified_date = item.modified() self.assertNotEqual(modified_date, new_modified_date) new_volatile_date = get_cachekey_volatile( 'Products.PloneMeeting.MeetingItem.modified') self.assertNotEqual(volatile_date, new_volatile_date) return new_modified_date, new_volatile_date cfg = self.meetingConfig self.changeUser('dgen') gic1_uid = cfg.getOrderedGroupsInCharge()[0] item = self.create('MeetingItem', groupsInCharge=(gic1_uid, )) item_uid = item.UID() self.assertEqual(self.transitions(item), ['proposeToValidationLevel1']) # ask finances advice fin_group_uid = finance_group_uid() item.setOptionalAdvisers((fin_group_uid + '__rowid__unique_id_002', )) item._update_after_edit() # advice still not askable, askable as level2 or level3 self.assertEqual(self.transitions(item), ['proposeToValidationLevel1']) self.do(item, 'proposeToValidationLevel1') self.assertEqual(self.transitions(item), ['backToItemCreated', 'proposeToValidationLevel2']) self.do(item, 'proposeToValidationLevel2') self.assertEqual(self.transitions(item), [ 'backToProposedToValidationLevel1', 'proposeToValidationLevel3', 'wait_advices_from_proposedToValidationLevel2' ]) self.do(item, 'wait_advices_from_proposedToValidationLevel2') # a MeetingManager is able to send back but not a normal user self.assertEqual(self.transitions(item), [ 'backTo_proposedToValidationLevel2_from_waiting_advices', 'backTo_proposedToValidationLevel3_from_waiting_advices', 'backTo_validated_from_waiting_advices' ]) # but a self._addPrincipalToGroup('bourgmestre', self.dirgen_creators) self._addPrincipalToGroup('bourgmestre', self.dirgen_level1reviewers) self._addPrincipalToGroup('bourgmestre', self.dirgen_level2reviewers) self._addPrincipalToGroup('bourgmestre', self.dirgen_level3reviewers) self.changeUser('bourgmestre') self.assertTrue(self.hasPermission("View", item)) self.assertEqual(self.transitions(item), []) # give advice self.changeUser('dfin') self.assertEqual(self.transitions(item), [ 'backTo_proposedToValidationLevel2_from_waiting_advices', 'backTo_proposedToValidationLevel3_from_waiting_advices' ]) # advice may be taken over self.assertTrue(item.adapted().mayTakeOver()) # advice giveable when item complete self.assertFalse(item.adviceIndex[fin_group_uid]['advice_addable']) self.assertTrue(item.adapted().mayEvaluateCompleteness()) # we will check that item modified date is invalidated when advice changed # this is responsible for updating collections counter in faceted portlet volatile_date = get_cachekey_volatile( 'Products.PloneMeeting.MeetingItem.modified') item_modified = item.modified() item.setCompleteness('completeness_complete') item._update_after_edit() item_modified, volatile_date = _check_date(item, item_modified, volatile_date) advice_portal_type = item._advicePortalTypeForAdviser(fin_group_uid) advice = self.addAdvice(item, advice_group=fin_group_uid, advice_type='positive_finance', advice_portal_type=advice_portal_type) # item modified date was updated item_modified, volatile_date = _check_date(item, item_modified, volatile_date) self.assertTrue(advice.advice_hide_during_redaction) self.assertEqual(self.transitions(advice), ['proposeToFinancialController']) # once advice given but hidden during redaction, item may no more be sent back self.assertEqual(self.transitions(item), []) # financial controller self.do(advice, 'proposeToFinancialController') self.assertEqual(self.transitions(item), []) self.assertEqual(self.transitions(advice), ['backToAdviceCreated', 'proposeToFinancialEditor']) # indexAdvisers is correctly reindexed advice_index_value = "delay__{0}_proposed_to_financial_controller".format( fin_group_uid) self.assertTrue( self.catalog(UID=item_uid, indexAdvisers=[advice_index_value])) # item modified date was updated item_modified, volatile_date = _check_date(item, item_modified, volatile_date) # financial editor self.do(advice, 'proposeToFinancialEditor') self.assertEqual(self.transitions(advice), [ 'backToProposedToFinancialController', 'proposeToFinancialReviewer' ]) # indexAdvisers is correctly reindexed advice_index_value = "delay__{0}_proposed_to_financial_editor".format( fin_group_uid) self.assertTrue( self.catalog(UID=item_uid, indexAdvisers=[advice_index_value])) # item modified date was updated item_modified, volatile_date = _check_date(item, item_modified, volatile_date) # financial reviewer self.do(advice, 'proposeToFinancialReviewer') self.assertEqual(self.transitions(item), []) self.assertEqual(self.transitions(advice), [ 'backToProposedToFinancialController', 'backToProposedToFinancialEditor', 'proposeToFinancialManager' ]) # indexAdvisers is correctly reindexed advice_index_value = "delay__{0}_proposed_to_financial_reviewer".format( fin_group_uid) self.assertTrue( self.catalog(UID=item_uid, indexAdvisers=[advice_index_value])) # item modified date was updated item_modified, volatile_date = _check_date(item, item_modified, volatile_date) # financial manager self.do(advice, 'proposeToFinancialManager') self.assertEqual(self.transitions(item), []) self.assertEqual(self.transitions(advice), [ 'backToProposedToFinancialController', 'backToProposedToFinancialReviewer', 'signFinancialAdvice' ]) # indexAdvisers is correctly reindexed advice_index_value = "delay__{0}_proposed_to_financial_manager".format( fin_group_uid) self.assertTrue( self.catalog(UID=item_uid, indexAdvisers=[advice_index_value])) # item modified date was updated item_modified, volatile_date = _check_date(item, item_modified, volatile_date) # sign advice self.do(advice, 'signFinancialAdvice') self.assertEqual(self.transitions(item), [ 'backTo_proposedToValidationLevel2_from_waiting_advices', 'backTo_proposedToValidationLevel3_from_waiting_advices', 'backTo_validated_from_waiting_advices' ]) self.assertEqual(self.transitions(advice), ['backToProposedToFinancialManager']) self.assertFalse(advice.advice_hide_during_redaction) # indexAdvisers is correctly reindexed advice_index_value = "delay__{0}_financial_advice_signed".format( fin_group_uid) self.assertTrue( self.catalog(UID=item_uid, indexAdvisers=[advice_index_value])) # item modified date was updated item_modified, volatile_date = _check_date(item, item_modified, volatile_date) # validate item self.do(item, 'backTo_validated_from_waiting_advices') self.assertEqual(item.query_state(), 'validated') # indexAdvisers is correctly reindexed advice_index_value = "delay__{0}_advice_given".format(fin_group_uid) self.assertTrue( self.catalog(UID=item_uid, indexAdvisers=[advice_index_value])) # item modified date was updated item_modified, volatile_date = _check_date(item, item_modified, volatile_date)