def addAnnex(self, context, annexType=None, annexTitle=None, relatedTo=None, to_print=False, confidential=False, to_sign=False, signed=False, publishable=False, annexFile=None): '''Adds an annex to p_item. If no p_annexType is provided, self.annexFileType is used. If no p_annexTitle is specified, the predefined title of the annex type is used.''' if annexType is None: if context.getTagName() == 'MeetingItem': if not relatedTo: annexType = self.annexFileType elif relatedTo == 'item_decision': annexType = self.annexFileTypeDecision elif context.portal_type.startswith('meetingadvice'): annexType = self.annexFileTypeAdvice elif context.getTagName() == 'Meeting': annexType = self.annexFileTypeMeeting # get complete annexType id that is like # 'meeting-config-id-annexes_types_-_item_annexes_-_financial-analysis' if relatedTo == 'item_decision': context.REQUEST.set('force_use_item_decision_annexes_group', True) annexes_config_root = get_config_root(context) if relatedTo == 'item_decision': context.REQUEST.set('force_use_item_decision_annexes_group', False) annexTypeId = calculate_category_id(annexes_config_root.get(annexType)) annexContentType = 'annex' if relatedTo == 'item_decision': annexContentType = 'annexDecision' theAnnex = createContentInContainer( container=context, portal_type=annexContentType, title=annexTitle or 'Annex', file=self._annex_file_content(annexFile=annexFile), content_category=annexTypeId, to_print=to_print, confidential=confidential, to_sign=to_sign, signed=signed, publishable=publishable) # need to commit the transaction so the stored blob is correct # if not done, accessing the blob will raise 'BlobError: Uncommitted changes' transaction.commit() return theAnnex
def _enable_annex_config(self, obj, param="confidentiality", related_to=None, enable=True): """p_fct possible values are : - confidentiality (default); - to_be_printed; - signed; - publishable.""" if related_to == 'item_decision': self.request.set('force_use_item_decision_annexes_group', True) annexes_config_root = get_config_root(obj) if related_to == 'item_decision': self.request.set('force_use_item_decision_annexes_group', False) annex_group = get_group(annexes_config_root, obj) attr_name = "{0}_activated".format(param) setattr(annex_group, attr_name, enable)
def add_annex( self, context, path, annex_type=None, annex_title=None, to_print=False, confidential=False, ): """Adds an annex to p_item. If no p_annexType is provided, self.annexFileType is used. If no p_annexTitle is specified, the predefined title of the annex type is used.""" # _path = self._check_file_exists(path) if annex_type is None: annex_type = "annexe" # get complete annexType id that is like # 'meeting-config-id-annexes_types_-_item_annexes_-_financial-analysis' annexes_config_root = get_config_root(context) annex_type_id = calculate_category_id( annexes_config_root.get(annex_type)) annex_portal_type = "annex" file_ext = path[path.rindex("."):].lower() content_type = content_types[file_ext] the_annex = createContentInContainer( container=context, portal_type=annex_portal_type, title=annex_title or "Annex", file=self._annex_file_content(path), content_category=annex_type_id, content_type=content_type, contentType=content_type, to_print=to_print, confidential=confidential, ) return the_annex
def addDemoData(context): ''' ''' if isNotMeetingCommunesDemoProfile(context): return site = context.getSite() tool = api.portal.get_tool('portal_plonemeeting') cfg = tool.objectValues('MeetingConfig')[0] wfTool = api.portal.get_tool('portal_workflow') pTool = api.portal.get_tool('plone_utils') mTool = api.portal.get_tool('portal_membership') # first we need to be sure that our IPoneMeetingLayer is set correctly # https://dev.plone.org/ticket/11673 from zope.event import notify from zope.traversing.interfaces import BeforeTraverseEvent notify(BeforeTraverseEvent(site, site.REQUEST)) # we will create elements for some users, make sure their personal # area is correctly configured # first make sure the 'Members' folder exists members = mTool.getMembersFolder() if members is None: _createObjectByType('Folder', site, id='Members') mTool.createMemberArea('agentPers') mTool.createMemberArea('agentInfo') mTool.createMemberArea('agentCompta') # create 5 meetings : 2 passed, 1 current and 2 future today = datetime.now() dates = [ today - timedelta(days=13), today - timedelta(days=6), today + timedelta(days=1), today + timedelta(days=8), today + timedelta(days=15) ] # items dict here : the key is the user we will create the item for # we use item templates so content is created for the demo items = { 'agentPers': ( { 'templateId': 'template3', 'title': u'Engagement temporaire d\'un informaticien', 'budgetRelated': True, 'review_state': 'validated', }, { 'templateId': 'template2', 'title': u'Contrôle médical de Mr Antonio', 'budgetRelated': False, 'review_state': 'proposed', }, { 'templateId': 'template2', 'title': u'Contrôle médical de Mlle Debbeus', 'budgetRelated': False, 'review_state': 'proposed', }, { 'templateId': 'template2', 'title': u'Contrôle médical de Mme Hanck', 'budgetRelated': False, 'review_state': 'validated', }, { 'templateId': 'template4', 'title': u'Prestation réduite Mme Untelle, instritutrice maternelle', 'budgetRelated': False, 'review_state': 'validated', }, ), 'agentInfo': ( { 'templateId': 'template5', 'title': u'Achat nouveaux serveurs', 'budgetRelated': True, 'review_state': 'validated', }, { 'templateId': 'template5', 'title': u'Marché public, contestation entreprise Untelle SA', 'budgetRelated': False, 'review_state': 'validated', }, ), 'agentCompta': ( { 'templateId': 'template5', 'title': u'Présentation budget 2014', 'budgetRelated': True, 'review_state': 'validated', }, { 'templateId': 'template5', 'title': u'Plainte de Mme Daise, taxe immondice', 'budgetRelated': False, 'review_state': 'validated', }, { 'templateId': 'template5', 'title': u'Plainte de Mme Uneautre, taxe piscine', 'budgetRelated': False, 'review_state': 'proposed', }, ), 'dgen': ( { 'templateId': 'template1', 'title': u'Tutelle CPAS : point 1 BP du 15 juin', 'budgetRelated': False, 'review_state': 'created', }, { 'templateId': 'template5', 'title': u'Tutelle CPAS : point 2 BP du 15 juin', 'budgetRelated': False, 'review_state': 'proposed', }, { 'templateId': 'template5', 'title': u'Tutelle CPAS : point 16 BP du 15 juin', 'budgetRelated': True, 'review_state': 'validated', }, ), } # login as 'dgen' mTool.createMemberArea('dgen') for cfg in tool.objectValues('MeetingConfig'): # cleanMemoize so ToolPloneMeeting.getMeetingConfig returns the correct MeetingConfig cleanMemoize(site) secrFolder = tool.getPloneMeetingFolder(cfg.getId(), 'dgen') # build attendees and signatories passed to Meeting._doUpdateContacts # attendees OrderedDict([('uid1', 'attendee'), ('uid2', 'attendee'), ('uid3', 'absent')]) # signatories {'uid1': '1'} attendees = OrderedDict() signatories = {} for hp_uid in cfg.getOrderedContacts(): attendees[hp_uid] = 'attendee' signatories = {attendees.keys()[1]: '1', attendees.keys()[0]: '2'} # create meetings for date in dates: meetingId = secrFolder.invokeFactory(cfg.getMeetingTypeName(), id=date.strftime('%Y%m%d'), date=date) meeting = getattr(secrFolder, meetingId) pTool.changeOwnershipOf(meeting, 'dgen') meeting._do_update_contacts(attendees=attendees, signatories=signatories) # -13 meeting is closed if date == today - timedelta(days=13): wfTool.doActionFor(meeting, 'freeze') wfTool.doActionFor(meeting, 'decide') wfTool.doActionFor(meeting, 'close') # -6 meeting is frozen if date == today - timedelta(days=6): wfTool.doActionFor(meeting, 'freeze') wfTool.doActionFor(meeting, 'decide') meeting.reindexObject() for item in meeting.get_items(): pTool.changeOwnershipOf(item, 'dgen') # create items for userId in items: userFolder = tool.getPloneMeetingFolder(cfg.getId(), userId) for item in items[userId]: # get the template then clone it template = getattr( tool.getMeetingConfig(userFolder).itemtemplates, item['templateId']) with api.env.adopt_user(username=userId): tool.invalidateAllCache() newItem = template.clone( newOwnerId=userId, destFolder=userFolder, newPortalType=cfg.getItemTypeName()) newItem.setTitle(item['title']) newItem.setBudgetRelated(item['budgetRelated']) if item['review_state'] == 'proposed': wfTool.doActionFor(newItem, 'propose') if item['review_state'] == 'validated': wfTool.doActionFor(newItem, 'validate') # add annexe and advice for one item in College if item['templateId'] == 'template3' and cfg.id == 'meeting-config-college': cpt = 1 annexes_config_root = get_config_root(newItem) for annexType in ('annexe', 'annexe', 'annexeBudget', 'annexeCahier'): annex_title = u'CV Informaticien N°2016-%s' % (cpt) annex_file = namedfile.NamedBlobFile( 'Je suis le contenu du fichier', filename=u'CV-0%s.txt' % (cpt)) annexTypeId = calculate_category_id( annexes_config_root.get(annexType)) annex_id = normalize_name(site.REQUEST, annex_title) api.content.create(container=newItem, id=annex_id, type='annex', title=annex_title, file=annex_file, content_category=annexTypeId, to_print=False, confidential=False) cpt += 1 newItem.setOptionalAdvisers( ('{0}__rowid__unique_id_003'.format( org_id_to_uid('dirfin')), org_id_to_uid('informatique'))) newItem.at_post_create_script() createContentInContainer( newItem, 'meetingadvice', **{ 'advice_group': org_id_to_uid('informatique'), 'advice_type': u'positive', 'advice_comment': RichTextValue(SAMPLE_TEXT), 'advice_observations': RichTextValue() }) if item['templateId'] == 'template5' and cfg.id == 'meeting-config-college': newItem.setOptionalAdvisers((org_id_to_uid('dirgen'), )) newItem.at_post_create_script() createContentInContainer( newItem, 'meetingadvice', **{ 'advice_group': org_id_to_uid('dirgen'), 'advice_type': u'negative', 'advice_comment': RichTextValue(SAMPLE_TEXT), 'advice_observations': RichTextValue(SAMPLE_TEXT) }) newItem.reindexObject() # adapt some parameters for config cfg.setAnnexToPrintMode('enabled_for_info')
def test_pm_AnnexToPrintBehaviourWhenCloned(self): """When cloning an item with annexes, to the same or another MeetingConfig, the 'toPrint' field is kept depending on MeetingConfig.keepOriginalToPrintOfClonedItems. If it is True, the original value is kept, if it is False, it will use the MeetingConfig.annexToPrintDefault value.""" cfg = self.meetingConfig cfg2 = self.meetingConfig2 cfg2Id = cfg2.getId() cfg.setKeepOriginalToPrintOfClonedItems(False) cfg2.setKeepOriginalToPrintOfClonedItems(False) self.changeUser('pmManager') meeting = self.create('Meeting', date=DateTime('2016/02/02')) item = self.create('MeetingItem') annex = self.addAnnex(item) annex_config = get_config_root(annex) annex_group = get_group(annex_config, annex) self.assertFalse(annex_group.to_be_printed_activated) self.assertFalse(annex.to_print) annex.to_print = True self.assertTrue(annex.to_print) # decide the item so we may add decision annex item.setDecision(self.decisionText) self.presentItem(item) self.decideMeeting(meeting) self.do(item, 'accept') self.assertEquals(item.queryState(), 'accepted') annexDec = self.addAnnex(item, relatedTo='item_decision') annexDec_config = get_config_root(annexDec) annexDec_group = get_group(annexDec_config, annexDec) self.assertFalse(annexDec_group.to_be_printed_activated) self.assertFalse(annexDec.to_print) annexDec.to_print = True self.assertTrue(annexDec.to_print) # clone item locally, as keepOriginalToPrintOfClonedItems is False # default values defined in the config will be used self.assertFalse(cfg.getKeepOriginalToPrintOfClonedItems()) clonedItem = item.clone() annexes = get_annexes(clonedItem, portal_types=['annex']) if not annexes: pm_logger.info('No annexes found on duplicated item clonedItem') cloneItemAnnex = annexes and annexes[0] annexesDec = get_annexes(clonedItem, portal_types=['annexDecision']) if not annexesDec: pm_logger.info( 'No decision annexes found on duplicated item clonedItem') cloneItemAnnexDec = annexesDec and annexesDec[0] self.assertFalse(cloneItemAnnex and cloneItemAnnex.to_print) self.assertFalse(cloneItemAnnexDec and cloneItemAnnexDec.to_print) # enable keepOriginalToPrintOfClonedItems # some plugins remove annexes/decision annexes on duplication # so make sure we test if an annex is there... self.changeUser('siteadmin') cfg.setKeepOriginalToPrintOfClonedItems(True) self.changeUser('pmManager') clonedItem2 = item.clone() annexes = get_annexes(clonedItem2, portal_types=['annex']) if not annexes: pm_logger.info('No annexes found on duplicated item clonedItem2') cloneItem2Annex = annexes and annexes[0] annexesDec = get_annexes(clonedItem2, portal_types=['annexDecision']) if not annexesDec: pm_logger.info( 'No decision annexes found on duplicated item clonedItem2') cloneItem2AnnexDec = annexesDec and annexesDec[0] self.assertTrue(cloneItem2Annex and cloneItem2Annex.to_print or True) self.assertTrue(cloneItem2AnnexDec and cloneItem2AnnexDec.to_print or True) # clone item to another MC and test again # cfg2.keepOriginalToPrintOfClonedItems is True self.assertFalse(cfg2.getKeepOriginalToPrintOfClonedItems()) item.setOtherMeetingConfigsClonableTo((cfg2Id, )) clonedToCfg2 = item.cloneToOtherMeetingConfig(cfg2Id) annexes = get_annexes(clonedToCfg2, portal_types=['annex']) if not annexes: pm_logger.info('No annexes found on duplicated item clonedToCfg2') clonedToCfg2Annex = annexes and annexes[0] annexesDec = get_annexes(clonedToCfg2, portal_types=['annexDecision']) if not annexesDec: pm_logger.info( 'No decision annexes found on duplicated item clonedToCfg2') self.assertFalse(clonedToCfg2Annex and clonedToCfg2Annex.to_print) # enable keepOriginalToPrintOfClonedItems self.changeUser('siteadmin') cfg2.setKeepOriginalToPrintOfClonedItems(True) self.deleteAsManager(clonedToCfg2.UID()) # send to cfg2 again self.changeUser('pmManager') clonedToCfg2Again = item.cloneToOtherMeetingConfig(cfg2Id) annexes = get_annexes(clonedToCfg2Again, portal_types=['annex']) if not annexes: pm_logger.info( 'No annexes found on duplicated item clonedToCfg2Again') clonedToCfg2AgainAnnex = annexes and annexes[0] annexesDec = get_annexes(clonedToCfg2Again, portal_types=['annexDecision']) if not annexesDec: pm_logger.info( 'No decision annexes found on duplicated item clonedToCfg2Again' ) self.assertTrue( clonedToCfg2AgainAnnex and clonedToCfg2AgainAnnex.to_print or True)