def test_get_vocab(self): vocab = get_vocab(self.portal, 'plone.app.vocabularies.PortalTypes') self.assertTrue(isinstance(vocab, SimpleVocabulary)) vocab = get_vocab(None, 'plone.app.vocabularies.PortalTypes', only_factory=True) self.assertTrue(isinstance(vocab, PortalTypesVocabulary))
def __init__(self, context, request): super(PSTExportAsXML, self).__init__(context, request) self.ploneview = getMultiAdapter((context, request), name='plone') self.plan_vocab = get_vocab( self.context, 'imio.project.core.content.project.plan_vocabulary') self.manager_vocab = get_vocab( self.context, 'imio.project.core.content.project.manager_vocabulary') self.repr_resp_vocab = get_vocab( self.context, 'imio.project.pst.content.operational.representative_responsible_vocabulary' )
def test_pm_CreatorsForFacetedVocabulary(self): '''Test the "Products.PloneMeeting.vocabularies.creatorsforfacetedvocabulary" vocabulary, especially because it is cached.''' cfg = self.meetingConfig self.changeUser('pmCreator1') pmFolder = self.getMeetingFolder() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.creatorsforfacetedfiltervocabulary", only_factory=True) # once get, it is cached self.assertEqual(len(vocab(pmFolder)), 3) # if a new pmFolder is created, then the cache is cleaned # get pmFolder for user 'pmManager' self.changeUser('pmManager') pmFolder = self.getMeetingFolder() # cache was cleaned self.assertEqual(len(vocab(pmFolder)), 4) cfg.setUsersHiddenInDashboardFilter(('pmCreator1', )) cfg.at_post_edit_script() # cache was cleaned and pmCreator is not in the list anymore self.assertEqual(len(vocab(pmFolder)), 3) cfg.setUsersHiddenInDashboardFilter(()) cfg.at_post_edit_script() # cache was cleaned and pmCreator is back in the list self.assertEqual(len(vocab(pmFolder)), 4)
def test_pm_AdviceTypesVocabulary(self): '''Test the "Products.PloneMeeting.vocabularies.advicetypesvocabulary" vocabulary, especially because it is cached.''' cfg = self.meetingConfig self.changeUser('siteadmin') cfg.setUsedAdviceTypes(('positive', 'negative')) pmFolder = self.getMeetingFolder() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.advicetypesvocabulary", only_factory=True) # once get, it is cached self.assertEqual(sorted([term.token for term in vocab(pmFolder)]), [ 'asked_again', 'considered_not_given_hidden_during_redaction', 'hidden_during_redaction', 'negative', 'not_given', 'positive' ]) # change the MeetingConfig.usedAdvicesTypes cfg.setUsedAdviceTypes(('positive', )) # cached self.assertEqual(sorted([term.token for term in vocab(pmFolder)]), [ 'asked_again', 'considered_not_given_hidden_during_redaction', 'hidden_during_redaction', 'negative', 'not_given', 'positive' ]) cfg.at_post_edit_script() # cache invalidated self.assertEqual(sorted([term.token for term in vocab(pmFolder)]), [ 'asked_again', 'considered_not_given_hidden_during_redaction', 'hidden_during_redaction', 'not_given', 'positive' ])
def test_pm_ItemClassifiersVocabulary(self): '''Test the "Products.PloneMeeting.vocabularies.classifiersvocabulary" vocabulary, especially because it is cached. It relies on the categoriesvocabulary.''' self.changeUser('siteadmin') pmFolder = self.getMeetingFolder() cfg = self.meetingConfig cfg.setUseGroupsAsCategories(False) vocab = get_vocab( cfg, "Products.PloneMeeting.vocabularies.classifiersvocabulary", only_factory=True) # once get, it is cached terms = vocab(pmFolder) # every existing categories are shown, no matter it is disabled nbOfCategories = len( cfg.getCategories(catType='classifiers', onlySelectable=False)) self.assertEqual(len(terms), nbOfCategories) # here we make sure it is cached by changing a category title # manually without using the processForm way classifier1 = cfg.classifiers.classifier1 classifier1.title = u'New title' terms = vocab(pmFolder) classifier1_id = classifier1.getId() self.assertNotEquals(terms.by_token[classifier1_id].title, cfg.categories.development.title) # right correctly edit the category, the vocabulary is invalidated notify(ObjectModifiedEvent(classifier1)) terms = vocab(pmFolder) self.assertEqual(terms.by_token[classifier1_id].title, cfg.classifiers.classifier1.title) # if we add/remove a category, then the cache is cleaned too # add a classifier newClassifier = self.create('meetingcategory', id='newclassifier', title='New classifier', is_classifier=True) # cache was cleaned, the new value is available terms = vocab(pmFolder) self.assertEqual([term.title for term in vocab(pmFolder)], [ u'Classifier 2', u'Classifier 3', u'New classifier', u'New title' ]) # disable a classifier self._disableObj(newClassifier) self.assertEqual([term.title for term in vocab(pmFolder)], [ u'Classifier 2', u'Classifier 3', u'New title', u'New classifier (Inactive)' ]) # term.value is the classifier id self.assertEqual( [term.value for term in vocab(pmFolder)], ['classifier2', 'classifier3', 'classifier1', 'newclassifier']) # remove a classifier self.portal.restrictedTraverse('@@delete_givenuid')( newClassifier.UID()) # cache was cleaned self.assertEqual([term.title for term in vocab(pmFolder)], [u'Classifier 2', u'Classifier 3', u'New title'])
def _add_finance_advice(item, newItem, last_transition): if item['toDiscuss'] and \ item['category'] in ['affaires-juridiques', 'remboursement'] and \ last_transition == 'prevalidate': finance_group = finance_group_uid() if finance_group: finance_advice_id = '{0}__rowid__unique_id_002'.format( finance_group) optional_advisers = get_vocab( newItem, 'Products.PloneMeeting.vocabularies.itemoptionaladvicesvocabulary' ) if finance_advice_id not in optional_advisers: _memos.clear() finance_group = finance_group_uid() finance_advice_id = '{0}__rowid__unique_id_002'.format( finance_group) newItem.setOptionalAdvisers((finance_advice_id, )) newItem.updateLocalRoles() wfTool.doActionFor(newItem, 'wait_advices_from_prevalidated') newItem.setCompleteness('completeness_complete') newItem.updateLocalRoles() with api.env.adopt_user('dfin'): advice = createContentInContainer( newItem, 'meetingadvicefinances', **{ 'advice_group': finance_group, 'advice_type': u'positive_finance', 'advice_comment': RichTextValue(u'Mon commentaire') }) wfTool.doActionFor(advice, 'proposeToFinancialEditor') wfTool.doActionFor(advice, 'proposeToFinancialReviewer') wfTool.doActionFor(advice, 'proposeToFinancialManager') wfTool.doActionFor(advice, 'signFinancialAdvice') return True return False
def _turn_ids_into_uids(self, data): # turn annex_type id into content_category calculated id content_category = data.get("content_category", None) annex_type = None # get selectable categories if data["@type"] == "annexDecision": self.request.set('force_use_item_decision_annexes_group', True) vocab = get_vocab(self.context, 'collective.iconifiedcategory.categories') # when content_category provided, it must exist if content_category is not None: annex_group = get_annexes_config(self.context, data["@type"], annex_group=True) # get given content_category or the first one annex_type = annex_group.get(content_category) if not annex_type: raise BadRequest(ANNEX_CONTENT_CATEGORY_ERROR % content_category) annex_type_value = calculate_category_id(annex_type) if annex_type_value not in vocab: raise BadRequest(ANNEX_CONTENT_CATEGORY_ERROR % content_category) else: # use the default annex_type, the first selectable if not vocab._terms: raise BadRequest(ANNEX_NO_CONTENT_CATEGORY_AVAILABLE_ERROR) annex_type_value = vocab._terms[0].token data["content_category"] = annex_type_value # cleanup if data["@type"] == "annexDecision": self.request.set('force_use_item_decision_annexes_group', False) return data
def render(self): used_vote_terms = get_vocab( self.context, "Products.PloneMeeting.vocabularies.usedvotevaluesvocabulary") self.used_vote_values = [term.token for term in used_vote_terms._terms] self.groups = _build_voting_groups(self.context) return self.template()
def showAddAnnex(self): """ """ portal_types = api.portal.get_tool('portal_types') annexTypeInfo = portal_types['annex'] vocab = get_vocab(self.context, 'collective.iconifiedcategory.categories') show = annexTypeInfo in self.context.allowedContentTypes() and len(vocab) return vocab, show
def test_pm_MeetingDatesVocabularyMCAware(self): '''Test that "Products.PloneMeeting.vocabularies.meetingdatesvocabulary" vocabulary, is MeetingConfig aware, especially because it is cached.''' cfg = self.meetingConfig cfg2 = self.meetingConfig2 self.changeUser('pmManager') pmFolder = self.getMeetingFolder() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.meetingdatesvocabulary", only_factory=True) # create Meetings in cfg1 self.create('Meeting') self.create('Meeting', date=datetime(2015, 5, 6)) # create Meetings in cfg2 self.setMeetingConfig(cfg2.getId()) self.create('Meeting') self.create('Meeting', date=datetime(2016, 5, 6)) self.setMeetingConfig(cfg.getId()) pmFolder = self.getMeetingFolder() terms_cfg1 = [term.token for term in vocab(pmFolder)] self.setMeetingConfig(cfg2.getId()) pmFolder = self.getMeetingFolder() terms_cfg2 = [term.token for term in vocab(pmFolder)] self.assertNotEqual(terms_cfg1, terms_cfg2)
def test_pm_ListCategoriesOfOtherMCs(self): '''Test the vocabulary of the 'category_mapping_when_cloning_to_other_mc' field.''' cfg = self.meetingConfig cfg2 = self.meetingConfig2 # use special chars in MC title to check for unicodeDecodeErrors cfg.setTitle("héhé") cfg2.setTitle("hàhà") # by default, items of meetingConfig can be sent to meetingConfig2 # as meetingConfig2 use categories, it will appear in a category of meetingConfig aCatInMC = cfg.categories.development vocab_factory = get_vocab( None, u"Products.PloneMeeting.content.category." "category_mapping_when_cloning_to_other_mc_vocabulary", only_factory=True) self.assertEqual(len(vocab_factory(aCatInMC)), 8) # disabled categories are also returned self.assertFalse(cfg2.categories.marketing.enabled) self.assertTrue("{0}.marketing".format(cfg2.getId()) in vocab_factory(aCatInMC)) # only terms of cfg2 self.assertFalse([term for term in vocab_factory(aCatInMC) if cfg2.getId() not in term.token]) # but as meetingConfig does not use categories, a category of meetingConfig2 will not see it aCatInMC2 = cfg2.categories.deployment self.assertEqual(len(vocab_factory(aCatInMC2)), 0) # activate categories in both meetingConfigs cfg.setUseGroupsAsCategories(False) # still not enough... self.assertEqual(len(vocab_factory(aCatInMC2)), 0) # ... we must also specify that elements of self.meetingConfig2 can be sent to self.meetingConfig cfg2.setMeetingConfigsToCloneTo( ({'meeting_config': '%s' % cfg.getId(), 'trigger_workflow_transitions_until': NO_TRIGGER_WF_TRANSITION_UNTIL}, )) self.assertEqual(len(vocab_factory(aCatInMC2)), 3) # only terms of cfg self.assertFalse([term for term in vocab_factory(aCatInMC2) if cfg.getId() not in term.token])
def handleSaveRemoveAdviceInheritance(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return advice_infos = self._advice_infos(data) if not advice_infos.mayRemoveInheritedAdvice(): raise Unauthorized # if 'ask_localy', check if advice_id may be asked locally, if it is not the case # return a portal message but do not remove the inherited advice advice_asked_locally = False if data['inherited_advice_action'] == 'ask_locally': if self.context.showOptionalAdvisers(): advisers_vocab = get_vocab( self.context, self.context.getField( 'optionalAdvisers').vocabulary_factory, **{ 'include_selected': False, 'include_not_selectable_values': False }) if data['advice_uid'] in advisers_vocab: optionalAdvisers = list( self.context.getOptionalAdvisers(computed=True)) if data['advice_uid'] not in optionalAdvisers: optionalAdvisers.append(data['advice_uid']) self.context.setOptionalAdvisers(optionalAdvisers) advice_asked_locally = True if not advice_asked_locally: api.portal.show_message(message=_( 'remove_advice_inheritance_ask_locally_not_configured'), request=self.request, type='warning') self.request.RESPONSE.redirect(self.context.absolute_url()) return del self.context.adviceIndex[data['advice_uid']] self.context.update_local_roles() if advice_asked_locally: api.portal.show_message(message=_( 'remove_advice_inheritance_removed_and_asked_locally'), request=self.request) else: api.portal.show_message( message=_('remove_advice_inheritance_removed'), request=self.request) # in case an adviser removed inherited advice and may not # see the item anymore, we redirect him to a viewable place cleanMemoize( self.context, prefixes=['borg.localrole.workspace.checkLocalRolesAllowed']) url = findViewableURL(self.context, self.request) self.request.RESPONSE.redirect(url) # add logging message to fingerpointing log extras = 'object={0} advice_uid={1} inherited_advice_action={2}'.format( repr(self.context), data['advice_uid'], data['inherited_advice_action']) fplog('remove_advice_inheritance', extras=extras) return
def showAddAnnexDecision(self): """ """ portal_types = api.portal.get_tool('portal_types') annexTypeInfo = portal_types['annexDecision'] self.request.set('force_use_item_decision_annexes_group', True) vocab = get_vocab(self.context, 'collective.iconifiedcategory.categories') self.request.set('force_use_item_decision_annexes_group', False) show = annexTypeInfo in self.context.allowedContentTypes() and len(vocab) return vocab, show
def test_pm_AskedAdvicesVocabularyMCAware(self): '''Test the "Products.PloneMeeting.vocabularies.askedadvicesvocabulary" vocabulary, is MeetingConfig aware, especially because it is cached.''' self.changeUser('siteadmin') cfg = self.meetingConfig cfg2 = self.meetingConfig2 customAdvisers = [{ 'row_id': 'unique_id_000', 'org': self.developers_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '2', 'delay_label': '' }, { 'row_id': 'unique_id_123', 'org': self.vendors_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '5', 'delay_label': '' }, { 'row_id': 'unique_id_456', 'org': self.vendors_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '10', 'delay_label': '' }, { 'row_id': 'unique_id_789', 'org': self.vendors_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '20', 'delay_label': '' }] cfg.setCustomAdvisers(customAdvisers) customAdvisers = [{ 'row_id': 'unique_id_999', 'org': self.developers_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '20', 'delay_label': '' }] cfg2.setCustomAdvisers(customAdvisers) pmFolder = self.getMeetingFolder() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.askedadvicesvocabulary", only_factory=True) terms_cfg1 = [term.token for term in vocab(pmFolder)] self.setMeetingConfig(cfg2.getId()) pmFolder = self.getMeetingFolder() terms_cfg2 = [term.token for term in vocab(pmFolder)] self.assertNotEqual(terms_cfg1, terms_cfg2)
def test_pm_AdviceTypesVocabularyMCAware(self): '''Test the "Products.PloneMeeting.vocabularies.advicetypesvocabulary" vocabulary, is MeetingConfig aware, especially because it is cached.''' cfg = self.meetingConfig cfg2 = self.meetingConfig2 self.changeUser('siteadmin') cfg.setUsedAdviceTypes(('positive', 'negative')) cfg2.setUsedAdviceTypes(('positive', )) vocab = get_vocab( cfg, "Products.PloneMeeting.vocabularies.advicetypesvocabulary", only_factory=True) pmFolder = self.getMeetingFolder() terms_cfg1 = [term.token for term in vocab(pmFolder)] self.setMeetingConfig(cfg2.getId()) pmFolder = self.getMeetingFolder() terms_cfg2 = [term.token for term in vocab(pmFolder)] self.assertNotEqual(terms_cfg1, terms_cfg2)
def test_pm_CreatorsVocabulary(self): '''Test the "Products.PloneMeeting.vocabularies.creatorsvocabulary" vocabulary, especially because it is cached.''' self.changeUser('pmCreator1') pmFolder = self.getMeetingFolder() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.creatorsvocabulary", only_factory=True) # once get, it is cached self.assertEqual(len(vocab(pmFolder)), 3) # if a new pmFolder is created, then the cache is cleaned # get pmFolder for user 'pmManager' self.changeUser('pmManager') pmFolder = self.getMeetingFolder() # cache was cleaned self.assertEqual(len(vocab(pmFolder)), 4)
def test_pm_PMConditionAwareCollectionVocabulary(self): """Test the 'conditionawarecollectionvocabulary' essentially because it is cached. """ # test with 2 members having same groups # as pmCreator1 self.changeUser('pmCreator1') creator1_groups = self.member.getGroups() pmFolder = self.getMeetingFolder() searches = self.meetingConfig.searches searchAllItems = searches.searches_items.searchallitems vocab_name = "Products.PloneMeeting.vocabularies.conditionawarecollectionvocabulary" vocab = get_vocab(pmFolder, vocab_name, only_factory=True) self.assertTrue("/pmCreator1/" in vocab(searchAllItems, pmFolder)._terms[0].title[1]) # as pmCreator1b self.changeUser('pmCreator1b') creator1_groups = self.member.getGroups() creator1b_groups = self.member.getGroups() self.assertEqual(creator1_groups, creator1b_groups) self.assertTrue("/pmCreator1b/" in vocab(searchAllItems, pmFolder)._terms[0].title[1]) # invalidated if a collection is edited self.assertEqual( vocab(searchAllItems, pmFolder)._terms[0].title[0], u'My items') searchMyItems = searches.searches_items.searchmyitems searchMyItems.setTitle(u'My items edited') notify(ObjectModifiedEvent(searchMyItems)) self.assertEqual( vocab(searchAllItems, pmFolder)._terms[0].title[0], u'My items edited') # invalidated when user groups changed # make pmCreator1b no more a creator vocab_values = get_vocab_values(searchAllItems, vocab_name, **{'real_context': pmFolder}) self._removePrincipalFromGroups(self.member.id, [self.developers_creators]) no_group_vocab_values = get_vocab_values(searchAllItems, vocab_name, **{'real_context': pmFolder}) self.assertNotEqual(vocab_values, no_group_vocab_values) self._addPrincipalToGroup(self.member.id, self.developers_observers) observer_vocab_values = get_vocab_values(searchAllItems, vocab_name, **{'real_context': pmFolder}) self.assertNotEqual(no_group_vocab_values, observer_vocab_values)
def test_pm_ItemCategoriesVocabularyMCAware(self): '''Test that "Products.PloneMeeting.vocabularies.categoriesvocabulary" vocabulary, is MeetingConfig aware, especially because it is cached.''' self.changeUser('siteadmin') pmFolder = self.getMeetingFolder() cfg = self.meetingConfig cfg.setUseGroupsAsCategories(False) vocab = get_vocab( cfg, "Products.PloneMeeting.vocabularies.categoriesvocabulary", only_factory=True) terms_cfg1 = [term.token for term in vocab(pmFolder)] # now in cfg2 cfg2 = self.meetingConfig2 self.setMeetingConfig(cfg2.getId()) cfg2.setUseGroupsAsCategories(False) pmFolder = self.getMeetingFolder() terms_cfg2 = [term.token for term in vocab(pmFolder)] self.assertNotEqual(terms_cfg1, terms_cfg2)
def test_pm_DisabledCollectionsAreIgnored(self): """If a DashboardCollection is disabled in the MeetingConfig, it is not displayed in the vocabulary.""" searches = self.meetingConfig.searches searchAllItems = searches.searches_items.searchallitems searchAllItems_path = searchAllItems.absolute_url_path() self.changeUser('pmCreator1') pmFolder = self.getMeetingFolder() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.conditionawarecollectionvocabulary", only_factory=True) self.assertTrue( searchAllItems_path in vocab(searches, real_context=pmFolder)) # disable it then test again self.changeUser('siteadmin') self._disableObj(searchAllItems, notify_event=True) self.changeUser('pmCreator1') self.assertFalse( searchAllItems_path in vocab(searches, real_context=pmFolder))
def test_pm_MeetingDatesVocabulary(self): '''Test the "Products.PloneMeeting.vocabularies.meetingdatesvocabulary" vocabulary, especially because it is cached.''' self._removeConfigObjectsFor(self.meetingConfig) self.changeUser('pmManager') pmFolder = self.getMeetingFolder() # create a meeting meeting = self.create('Meeting', date=datetime(2015, 5, 5)) meetingUID = meeting.UID() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.meetingdatesvocabulary", only_factory=True) # once get, it is cached vocab(pmFolder) self.assertEqual([term.token for term in vocab(pmFolder)._terms], [ITEM_NO_PREFERRED_MEETING_VALUE, meetingUID]) # if we add/remove/edit a meeting, then the cache is cleaned # add a meeting meeting2 = self.create('Meeting', date=datetime(2015, 6, 6)) meeting2UID = meeting2.UID() # cache was cleaned self.assertEqual( [term.token for term in vocab(pmFolder)._terms], [ITEM_NO_PREFERRED_MEETING_VALUE, meeting2UID, meetingUID]) # edit a meeting self.assertEqual( vocab(pmFolder).by_token[meetingUID].title, u'05/05/2015') meeting.date = datetime(2015, 7, 7) meeting._update_after_edit() # cache was cleaned self.assertEqual( vocab(pmFolder).by_token[meetingUID].title, u'07/07/2015') # remove a meeting self.portal.restrictedTraverse('@@delete_givenuid')(meeting.UID()) # cache was cleaned self.assertEqual([term.token for term in vocab(pmFolder)._terms], [ITEM_NO_PREFERRED_MEETING_VALUE, meeting2UID])
def test_pm_validate_category_mapping_when_cloning_to_other_mc(self): '''Test the 'category_mapping_when_cloning_to_other_mc' constraint. It just validates that we can not define more than one value for the same meetingConfig.''' dev_cat = self.meetingConfig.categories.development constraint = IMeetingCategory['category_mapping_when_cloning_to_other_mc'].constraint dev_cat_vocab = get_vocab( dev_cat, u"Products.PloneMeeting.content.category." u"category_mapping_when_cloning_to_other_mc_vocabulary") values = dev_cat_vocab.by_token.keys() # one value is ok self.assertTrue(constraint([values[0]])) # but not 2 for the same meetingConfig... error_msg = translate('error_can_not_select_several_cat_for_same_mc', domain='PloneMeeting', context=self.request) with self.assertRaises(Invalid) as cm: constraint(values) self.assertEqual(cm.exception.message, error_msg) # simulate a third meetingConfig, select one single value of existing meetingConfig2 and # one of unexisting meetingConfig3, the validation is ok... self.assertTrue(constraint([values[0], 'meeting-config-dummy.category_name']))
def secret_votes_default(context): """Default values for secret votes.""" res = [] vote_number = vote_number_default() item_votes = context.get_item_votes( vote_number=vote_number, ignored_vote_values=[NOT_VOTABLE_LINKED_TO_VALUE]) used_vote_terms = get_vocab( context, "Products.PloneMeeting.vocabularies.usedvotevaluesvocabulary", vote_number=vote_number) usedVoteValues = [ term.token for term in used_vote_terms._terms if term.token != NOT_ENCODED_VOTE_VALUE ] for usedVoteValue in usedVoteValues: data = { 'vote_value_id': usedVoteValue, 'vote_value': usedVoteValue, 'vote_count': item_votes['votes'].get(usedVoteValue) or 0 } res.append(data) return res
def test_pm_ProposingGroupsForFacetedVocabulary(self): '''Test that vocabulary "Products.PloneMeeting.vocabularies.proposinggroupsforfacetedfiltervocabulary" relies on MeetingConfig.groupsHiddenInDashboardFilter.''' cfg = self.meetingConfig self.changeUser('siteadmin') pmFolder = self.getMeetingFolder() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.proposinggroupsforfacetedfiltervocabulary", only_factory=True) # by default when MeetingConfig.groupsHiddenInDashboardFilter is empty, every groups are returned self.assertEqual(cfg.getGroupsHiddenInDashboardFilter(), ()) self.assertEqual([term.title for term in vocab(pmFolder)], [u'Developers', u'Vendors', u'End users (Inactive)']) # now define values in MeetingConfig.groupsHiddenInDashboardFilter cfg.setGroupsHiddenInDashboardFilter((self.vendors_uid, )) cfg.at_post_edit_script() self.assertEqual([term.title for term in vocab(pmFolder)], [u'Developers', u'End users (Inactive)']) # select "End users" self._select_organization(self.endUsers_uid) self.assertEqual([term.title for term in vocab(pmFolder)], [u'Developers', u'End users'])
def test_pm_AskedAdvicesVocabularyWithWrongContext(self): '''Test the "Products.PloneMeeting.vocabularies.askedadvicesvocabulary" vocabulary, when receiving wrong context, may occur during site install or DashboardCollection edit.''' self.changeUser('pmManager') item = self.create('MeetingItem') meeting = self.create('Meeting') cfg = self.meetingConfig vocab = get_vocab( cfg, "Products.PloneMeeting.vocabularies.askedadvicesvocabulary", only_factory=True) # working context pmFolder = self.getMeetingFolder() self.assertEqual(len(vocab(pmFolder)), 2) self.assertEqual(len(vocab(cfg)), 2) self.assertEqual(len(vocab(item)), 2) self.assertEqual(len(vocab(meeting)), 2) # do not fail on weird context self.assertEqual(len(vocab(self.portal)), 0) self.assertEqual(len(vocab(self.portal.contacts)), 0) self.assertEqual(len(vocab(self.app)), 0) self.request['PUBLISHED'] = None self.assertEqual(len(vocab(None)), 0)
def test_pm_ProposingGroupsVocabularies(self): '''Test proposingGroup related cached vocabularies.''' self.changeUser('siteadmin') pmFolder = self.getMeetingFolder() vocab1 = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.proposinggroupsvocabulary", only_factory=True) vocab2 = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.everyorganizationsacronymsvocabulary", only_factory=True) vocab3 = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.proposinggroupsforfacetedfiltervocabulary", only_factory=True) vocab4 = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.associatedgroupsvocabulary", only_factory=True) # once get, it is cached self.assertEqual(len(vocab1(pmFolder)), 3) # contains My organization and external organizations self.assertEqual(len(vocab2(pmFolder)), 6) self.assertEqual(len(vocab3(pmFolder)), 3) # when nothing in config, just displays the orgs selected in plonegroup self.assertEqual(len(vocab4(pmFolder)), 2) # if we add/remove/edit an organozation, then the cache is cleaned # add an organization new_org = self.create('organization', title='NewOrg', acronym='N.O.') new_org_uid = new_org.UID() self._select_organization(new_org_uid) # cache was cleaned self.assertEqual(len(vocab1(pmFolder)), 4) self.assertEqual(len(vocab2(pmFolder)), 7) self.assertEqual(len(vocab3(pmFolder)), 4) self.assertEqual(len(vocab4(pmFolder)), 3) # edit a group self.assertEqual( vocab1(pmFolder).by_token[new_org_uid].title, new_org.Title()) self.assertEqual( vocab2(pmFolder).by_token[new_org_uid].title, new_org.acronym) self.assertEqual( vocab3(pmFolder).by_token[new_org_uid].title, new_org.Title()) self.assertEqual( vocab4(pmFolder).by_token[new_org_uid].title, new_org.Title()) new_org.title = u'Modified title' new_org.acronym = u'Modified acronym' notify(ObjectModifiedEvent(new_org)) # cache was cleaned self.assertEqual( vocab1(pmFolder).by_token[new_org_uid].title, new_org.Title()) self.assertEqual( vocab2(pmFolder).by_token[new_org_uid].title, new_org.acronym) self.assertEqual( vocab3(pmFolder).by_token[new_org_uid].title, new_org.Title()) self.assertEqual( vocab4(pmFolder).by_token[new_org_uid].title, new_org.Title()) # remove an organization (unselect it first) self._select_organization(new_org_uid, remove=True) self.portal.restrictedTraverse('@@delete_givenuid')(new_org_uid) # cache was cleaned self.assertEqual(len(vocab1(pmFolder)), 3) self.assertEqual(len(vocab2(pmFolder)), 6) self.assertEqual(len(vocab3(pmFolder)), 3) self.assertEqual(len(vocab4(pmFolder)), 2) # activate "End users" self.assertEqual([term.title for term in vocab1(pmFolder)], [u'Developers', u'Vendors', u'End users (Inactive)']) self.assertEqual([term.title for term in vocab2(pmFolder)], [ u'None', u'Devel', u'Devil', u'EndUsers', u'OrgOutside1', u'OrgOutside2' ]) self.assertEqual([term.title for term in vocab3(pmFolder)], [u'Developers', u'Vendors', u'End users (Inactive)']) self.assertEqual([term.title for term in vocab4(pmFolder)], [u'Developers', u'Vendors']) self._select_organization(self.endUsers_uid) self.assertEqual([term.title for term in vocab1(pmFolder)], [u'Developers', u'End users', u'Vendors']) self.assertEqual([term.title for term in vocab2(pmFolder)], [ u'None', u'Devel', u'Devil', u'EndUsers', u'OrgOutside1', u'OrgOutside2' ]) self.assertEqual([term.title for term in vocab3(pmFolder)], [u'Developers', u'End users', u'Vendors']) self.assertEqual([term.title for term in vocab4(pmFolder)], [u'Developers', u'End users', u'Vendors'])
def test_pm_GroupsInChargeVocabulary(self): '''Test the "Products.PloneMeeting.vocabularies.groupsinchargevocabulary" vocabulary, especially because it is cached.''' cfg = self.meetingConfig cfg.setUseGroupsAsCategories(False) self._enableField('classifier') self.changeUser('siteadmin') org1 = self.create('organization', id='org1', title='Org 1', acronym='Org1') org1_uid = org1.UID() org2 = self.create('organization', id='org2', title='Org 2', acronym='Org2') org2_uid = org2.UID() org3 = self.create('organization', id='org3', title='Org 3', acronym='Org3') org3_uid = org3.UID() vocab = get_vocab( org1, "Products.PloneMeeting.vocabularies.groupsinchargevocabulary", only_factory=True) # for now, no group in charge meetingFolder = self.getMeetingFolder() self.assertEqual(len(vocab(meetingFolder)), 0) # define some group in charge, vocabulary is invalidated when an org is modified self.vendors.groups_in_charge = (org1_uid, ) notify(ObjectModifiedEvent(self.vendors)) self.developers.groups_in_charge = (org2_uid, ) notify(ObjectModifiedEvent(self.developers)) self.assertEqual([term.title for term in vocab(meetingFolder)], ['Org 1', 'Org 2']) # create an new org with a groupInCharge directly org4 = self.create('organization', id='org4', title='Org 4', acronym='Org4', groups_in_charge=(org3_uid, )) org4_uid = org4.UID() self._select_organization(org4_uid) self.assertEqual([term.title for term in vocab(meetingFolder)], ['Org 1', 'Org 2', 'Org 3']) # change a group in charge self.vendors.groups_in_charge = (org4_uid, ) notify(ObjectModifiedEvent(self.vendors)) self.assertEqual([term.title for term in vocab(meetingFolder)], ['Org 2', 'Org 3', 'Org 4']) # unselect a group in charge self.vendors.groups_in_charge = () notify(ObjectModifiedEvent(self.vendors)) self.assertEqual([term.title for term in vocab(meetingFolder)], ['Org 2', 'Org 3']) # category, creating an organization invalidates the vocabulary cache org5 = self.create('organization', id='org5', title='Org 5', acronym='Org5') org5_uid = org5.UID() # an already used cfg.categories.development.groups_in_charge = [org3_uid] # already existing no more used cfg.categories.research.groups_in_charge = [org4_uid] # new cfg.categories.events.groups_in_charge = [org5_uid] self.assertEqual([term.title for term in vocab(meetingFolder)], ['Org 2', 'Org 3', 'Org 4', 'Org 5']) # classifier, creating an organization invalidates the vocabulary cache org6 = self.create('organization', id='org6', title='Org 6', acronym='Org6') org6_uid = org6.UID() # already existing cfg.classifiers.classifier1.groups_in_charge = [org5_uid] # new cfg.classifiers.classifier2.groups_in_charge = [org6_uid] self.assertEqual([term.title for term in vocab(meetingFolder)], ['Org 2', 'Org 3', 'Org 4', 'Org 5', 'Org 6'])
def vote_counts(self): """Returns informations regarding votes count.""" data = [] counts = [] for vote_number in range(len(self.item_votes)): sub_counts = [] total_votes = self.context.getVoteCount('any_votable', vote_number) number_of_votes_msg = translate('number_of_voters', domain='PloneMeeting', context=self.request) res = [ u'<span title="{0}">{1}</span>'.format(number_of_votes_msg, total_votes) ] formated_total_votes = total_votes pattern = u'<span class="vote_value_{0}" title="{1}">{2}</span>' # specify how much voted for this vote if secret if self.votesAreSecret: voted = self.context.getVoteCount('any_voted', vote_number) formated_total_votes = "{0} / {1}".format(voted, total_votes) sub_counts.append((number_of_votes_msg, formated_total_votes, 'vote_value_number_of_voters')) # compute votes not encoded for first secret vote # taking into account linked votes if self.votesAreSecret: linked_vote_numbers = _get_linked_item_vote_numbers( self.context, self.meeting, vote_number) or [0] if not linked_vote_numbers or vote_number == min( linked_vote_numbers): total_voted = 0 for linked_vote_number in linked_vote_numbers: total_voted += self.context.getVoteCount( 'any_voted', linked_vote_number) translated_used_vote_value = translate( 'vote_value_not_yet', domain='PloneMeeting', context=self.request) count = total_votes - total_voted res.append( pattern.format("not_yet", translated_used_vote_value, count)) sub_counts.append((translated_used_vote_value, count, 'vote_value_not_yet')) used_vote_terms = get_vocab( self.context, "Products.PloneMeeting.vocabularies.usedvotevaluesvocabulary", vote_number=vote_number) usedVoteValues = [term.token for term in used_vote_terms._terms] for usedVoteValue in usedVoteValues: translated_used_vote_value = translate( 'vote_value_{0}'.format(usedVoteValue), domain='PloneMeeting', context=self.request) count = self.context.getVoteCount(usedVoteValue, vote_number) res.append( pattern.format(usedVoteValue, translated_used_vote_value, count)) sub_counts.append((translated_used_vote_value, count, 'vote_value_' + usedVoteValue)) votes = u" / ".join(res) data.append(votes) counts.append(sub_counts) return data, counts
def _extra_include(self, result): """ """ extra_include = self._get_asked_extra_include() if "categories" in extra_include: categories = self.context.getCategories(onlySelectable=False) result["extra_include_categories"] = [] for category in categories: serializer = self._get_serializer(category, "categories") result["extra_include_categories"].append(serializer()) result["extra_include_categories_items_total"] = len(categories) if "classifiers" in extra_include: classifiers = self.context.getCategories(catType='classifiers', onlySelectable=False) result["extra_include_classifiers"] = [] for classifier in classifiers: serializer = self._get_serializer(classifier, "classifiers") result["extra_include_classifiers"].append(serializer()) result["extra_include_classifiers_items_total"] = len(classifiers) if "pod_templates" in extra_include: pod_templates = [ obj for obj in self.context.podtemplates.objectValues() if getattr(obj, 'enabled', False) ] result["extra_include_pod_templates"] = [] for pod_template in pod_templates: serializer = self._get_serializer(pod_template, "pod_templates") result["extra_include_pod_templates"].append(serializer()) result["extra_include_pod_templates_items_total"] = len( pod_templates) if "searches" in extra_include: collections = [ obj for obj in self.context.searches.searches_items.objectValues() if (obj.portal_type == 'DashboardCollection' and obj.enabled) ] result["extra_include_searches"] = [] for collection in collections: serializer = self._get_serializer(collection, "searches") result["extra_include_searches"].append(serializer()) result["extra_include_searches_items_total"] = len(collections) if "proposing_groups" in extra_include: orgs = self.context.getUsingGroups(theObjects=True) result["extra_include_proposing_groups"] = [] for org in orgs: serializer = self._get_serializer(org, "proposing_groups") result["extra_include_proposing_groups"].append(serializer()) result["extra_include_proposing_groups_items_total"] = len(orgs) if "associated_groups" in extra_include: vocab = get_vocab( self.context, 'Products.PloneMeeting.vocabularies.associatedgroupsvocabulary' ) org_uids = [term.value for term in vocab._terms] orgs = uuidsToObjects(org_uids, ordered=True) result["extra_include_associated_groups"] = [] for org in orgs: serializer = self._get_serializer(org, "associated_groups") result["extra_include_associated_groups"].append(serializer()) result["extra_include_associated_groups_items_total"] = len(orgs) if "groups_in_charge" in extra_include: vocab = get_vocab( self.context, 'Products.PloneMeeting.vocabularies.groupsinchargevocabulary') org_uids = [term.value for term in vocab._terms] orgs = uuidsToObjects(org_uids, ordered=True) result["extra_include_groups_in_charge"] = [] for org in orgs: serializer = self._get_serializer(org, "groups_in_charge") result["extra_include_groups_in_charge"].append(serializer()) result["extra_include_groups_in_charge_items_total"] = len(orgs) return result
def test_MayChangeDelayTo(self): """Method MeetingItem.mayChangeDelayTo is made to control the 'available_on' of customAdvisers used for finance advice (5, 10 or 20 days). - 10 days is the only advice selectable thru the item edit form; - the delay '5' must be changed using the change delay widdget; - the delay '20' is reserved to finance advisers.""" cfg = self.meetingConfig self.changeUser('siteadmin') self._configureFinancesAdvice(cfg) # put users in finances group self._setupFinancesGroup() self.changeUser('pmCreator1') item = self.create('MeetingItem') # by default, only the 10 days delay is selectable optional_advisers = get_vocab( item, 'Products.PloneMeeting.vocabularies.itemoptionaladvicesvocabulary') self.assertEqual([term.token for term in optional_advisers], [ 'not_selectable_value_delay_aware_optional_advisers', '{0}__rowid__unique_id_002'.format(finance_group_uid()), 'not_selectable_value_non_delay_aware_optional_advisers', self.developers_uid, self.vendors_uid ]) # select the 10 days delay item.setOptionalAdvisers( ('%s__rowid__unique_id_002' % finance_group_uid(), )) item.at_post_edit_script() self.assertEqual(item.adviceIndex[finance_group_uid()]['delay'], '10') # Managers, are also required to use change delay widget for 5/20 delays self.changeUser('pmManager') self.assertFalse(item.adapted().mayChangeDelayTo(5)) self.assertTrue(item.adapted().mayChangeDelayTo(10)) self.assertFalse(item.adapted().mayChangeDelayTo(20)) # user having 'Modify portal content' may select 10 but not others self.changeUser('pmCreator1') self.assertFalse(item.adapted().mayChangeDelayTo(5)) self.assertTrue(item.adapted().mayChangeDelayTo(10)) self.assertFalse(item.adapted().mayChangeDelayTo(20)) # may select 5 if using change delay widget # aka 'managing_available_delays' is found in the REQUEST self.request.set('managing_available_delays', True) self.assertTrue(item.adapted().mayChangeDelayTo(5)) self.assertTrue(item.adapted().mayChangeDelayTo(10)) self.assertFalse(item.adapted().mayChangeDelayTo(20)) # change to 5 days item.setOptionalAdvisers( ('{0}__rowid__unique_id_003'.format(finance_group_uid()), )) item.at_post_edit_script() self.assertEqual(item.adviceIndex[finance_group_uid()]['delay'], '5') # could back to 10 days self.assertTrue(item.adapted().mayChangeDelayTo(5)) self.assertTrue(item.adapted().mayChangeDelayTo(10)) self.assertFalse(item.adapted().mayChangeDelayTo(20)) # Managers have bypass when using change delay widget self.changeUser('pmManager') self.assertTrue(item.adapted().mayChangeDelayTo(5)) self.assertTrue(item.adapted().mayChangeDelayTo(10)) self.assertTrue(item.adapted().mayChangeDelayTo(20)) # now, when item is 'wait_advices_from_prevalidated', finance advisers # may select the 20 days delay self.changeUser('pmReviewer1') self.proposeItem(item) self.do(item, 'wait_advices_from_prevalidated') self.changeUser('pmFinController') # may change to 20 self.assertFalse(item.adapted().mayChangeDelayTo(5)) self.assertFalse(item.adapted().mayChangeDelayTo(10)) self.assertTrue(item.adapted().mayChangeDelayTo(20)) # change to 20 days item.setOptionalAdvisers( ('{0}__rowid__unique_id_004'.format(finance_group_uid()), )) item.at_post_edit_script() self.assertEqual(item.adviceIndex[finance_group_uid()]['delay'], '20') # once to 20, may back to 10 self.assertFalse(item.adapted().mayChangeDelayTo(5)) self.assertTrue(item.adapted().mayChangeDelayTo(10)) self.assertTrue(item.adapted().mayChangeDelayTo(20)) # if item no more waiting finances advice, finances may not # change delay anymore self.do(item, 'backTo_proposed_to_refadmin_from_waiting_advices') self.assertFalse(item.adapted().mayChangeDelayTo(5)) self.assertFalse(item.adapted().mayChangeDelayTo(10)) self.assertFalse(item.adapted().mayChangeDelayTo(20)) # if advice delay is set to 20, user have edit rights may not change it anymore self.changeUser('pmRefAdmin1') self.assertFalse(item.adapted().mayChangeDelayTo(5)) self.assertFalse(item.adapted().mayChangeDelayTo(10)) self.assertFalse(item.adapted().mayChangeDelayTo(20)) # only a Manager will be able to change that delay now self.changeUser('pmManager') self.assertTrue(item.adapted().mayChangeDelayTo(5)) self.assertTrue(item.adapted().mayChangeDelayTo(10)) self.assertTrue(item.adapted().mayChangeDelayTo(20))
def test_pm_AskedAdvicesVocabulary(self): '''Test the "Products.PloneMeeting.vocabularies.askedadvicesvocabulary" vocabulary, especially because it is cached.''' self.changeUser('siteadmin') cfg = self.meetingConfig customAdvisers = [{ 'row_id': 'unique_id_000', 'org': self.developers_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '2', 'delay_label': '' }, { 'row_id': 'unique_id_123', 'org': self.vendors_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '5', 'delay_label': '' }, { 'row_id': 'unique_id_456', 'org': self.vendors_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '10', 'delay_label': '' }, { 'row_id': 'unique_id_789', 'org': self.vendors_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '20', 'delay_label': '' }] cfg.setCustomAdvisers(customAdvisers) pmFolder = self.getMeetingFolder() vocab = get_vocab( pmFolder, "Products.PloneMeeting.vocabularies.askedadvicesvocabulary", only_factory=True) # we have 4 delay-aware advisers and 2 adviser groups selectable as optional delayAdvisers = [ adviser for adviser in cfg.getCustomAdvisers() if adviser['delay'] ] self.assertEqual(len(delayAdvisers), 4) self.assertEqual(len(get_organizations(not_empty_suffix='advisers')), 2) # once get, it is cached, it includes customAdvisers and MeetingConfig.selectableAdvisers self.assertEqual(len(vocab(pmFolder)), 6) # if we select a new organization, then the cache is cleaned # add an organization new_org = self.create('organization', title='New organization', acronym='N.G.') new_org_uid = new_org.UID() cfg.setSelectableAdvisers(cfg.getSelectableAdvisers() + (new_org_uid, )) # cache was cleaned self.assertEqual(len(vocab(pmFolder)), 7) # edit an organization new_org_term_id = 'real_org_uid__{0}'.format(new_org_uid) self.assertEqual( vocab(pmFolder).by_token[new_org_term_id].title, 'New organization (Inactive)') new_org.title = u'Modified title' notify(ObjectModifiedEvent(new_org)) # cache was cleaned self.assertEqual( vocab(pmFolder).by_token[new_org_term_id].title, 'Modified title (Inactive)') # select the organization, cache is cleaned self._select_organization(new_org_uid) self.assertEqual( vocab(pmFolder).by_token[new_org_term_id].title, 'Modified title') # remove an organization # first need to unselect it self._select_organization(new_org_uid, remove=True) self.portal.restrictedTraverse('@@delete_givenuid')(new_org_uid) # cache was cleaned self.assertEqual(len(vocab(pmFolder)), 6) # if we add/remove/edit a customAdviser, then the cache is cleaned # add a customAdviser customAdvisers.append({ 'row_id': 'unique_id_999', 'org': self.vendors_uid, 'gives_auto_advice_on': '', 'for_item_created_from': '2012/01/01', 'delay': '11', 'delay_label': 'New delay' }) cfg.setCustomAdvisers(customAdvisers) cfg.at_post_edit_script() self.assertEqual(len(vocab(pmFolder)), 7) self.assertTrue( 'delay_row_id__unique_id_999' in vocab(pmFolder).by_token) # delay is displayed in customAdviser title self.assertTrue('11 day(s)' in vocab( pmFolder).by_token['delay_row_id__unique_id_999'].title) # edit a customAdviser customAdvisers[-1]['delay'] = '12' cfg.setCustomAdvisers(customAdvisers) cfg.at_post_edit_script() self.assertTrue('12 day(s)' in vocab( pmFolder).by_token['delay_row_id__unique_id_999'].title) # remove a customAdviser customAdvisers = customAdvisers[:-1] cfg.setCustomAdvisers(customAdvisers) cfg.at_post_edit_script() self.assertEqual(len(vocab(pmFolder)), 6) # power advisers are taken into account by the vocabulary cfg.setPowerAdvisersGroups([self.endUsers_uid]) cfg.at_post_edit_script() self.assertEqual(len(vocab(pmFolder)), 7)