def test_content_category_changed_default_values(self): """While content_category is changed on an element, the default values for fields to_print/confidential/to_sign/signed are reapplied with new content_category default values if it was still the default vlue of the original content_category.""" category_group = self.portal.config['group-1'] category_group.to_be_printed_activated = True category_group.confidentiality_activated = True category_group.signed_activated = True category11 = self.portal.config['group-1']['category-1-1'] category11_id = calculate_category_id(category11) obj = api.content.create( id='file2', type='File', file=self.file, container=self.portal, content_category=category11_id) self.assertFalse(obj.confidential) self.assertFalse(obj.to_sign) self.assertFalse(obj.signed) self.assertIsNone(obj.to_print) # now enable everything on category-1-2 and use it category12 = self.portal.config['group-1']['category-1-2'] category12.to_print = False category12.confidential = True category12.to_sign = True category12.signed = True category12_id = calculate_category_id(category12) adapted_obj = IconifiedCategorization(obj) setattr(adapted_obj, 'content_category', category12_id) notify(ObjectModifiedEvent(obj)) # changed to True on obj an in parent's categorized_elements parent_cat_elements = obj.aq_parent.categorized_elements[obj.UID()] self.assertTrue(obj.confidential) self.assertTrue(parent_cat_elements['confidential']) self.assertTrue(obj.to_sign) self.assertTrue(parent_cat_elements['to_sign']) self.assertTrue(obj.signed) self.assertTrue(parent_cat_elements['signed']) # to_print could not be set to False because not printable self.assertIsNone(obj.to_print) self.assertIsNone(parent_cat_elements['to_print']) # enable conversion and back to category11 category11.to_print = True gsettings = GlobalSettings(self.portal) gsettings.auto_layout_file_types = CONVERTABLE_TYPES.keys() # set to_print to False, aka the default value of category12 obj.to_print = False setattr(adapted_obj, 'content_category', category11_id) notify(ObjectModifiedEvent(obj)) self.assertTrue(obj.to_print) self.assertTrue(parent_cat_elements['to_print']) # if original content_category does not exist, it does not fail # but default values are not reapplied obj.content_category = 'unkown_content_category' setattr(adapted_obj, 'content_category', category12_id) notify(ObjectModifiedEvent(obj)) self.assertEqual(obj.content_category, category12_id)
def test_ws_getItemInfosWithAnnexesTypes(self): """ Test that getting an item with an annex_type return only the annexes with the corresponding annexTypeId attribute. """ cfg = self.meetingConfig self.changeUser('pmCreator1') self.failUnless( len(self.portal.portal_catalog(portal_type='MeetingItemPma')) == 0) # prepare data for a default item req = self._prepareCreationData() # add one annex data = { 'title': 'My annex 1', 'filename': 'smallTestFile.pdf', 'file': 'smallTestFile.pdf' } req._creationData._annexes = [self._prepareAnnexInfo(**data)] # create the item newItem, reponse = self._createItem(req) financial_annex_type_id = calculate_category_id( cfg.annexes_types.item_annexes.get('financial-analysis')) item_annex_type_id = calculate_category_id( cfg.annexes_types.item_annexes.get('item-annex')) allowed_annexes_types = [financial_annex_type_id, item_annex_type_id] # get informations about the item, by default 'allowed_annexes_types' is empty resp = self._getItemInfos(newItem.UID(), showAnnexes=True, toBeDeserialized=False) # we have 1 annex self.assertEqual(len(resp._itemInfo[0]._annexes), 1) # the returned annex is the one created self.assertEqual(resp._itemInfo[0]._annexes[0]._title, 'My annex 1') self.assertEqual(resp._itemInfo[0]._annexes[0]._filename, 'smallTestFile.pdf') # filter on 'item_annex_type' annex type allowed_annexes_types = [financial_annex_type_id] resp = self._getItemInfos(newItem.UID(), showAnnexes=True, allowed_annexes_types=allowed_annexes_types, toBeDeserialized=False) # we have 1 annex self.assertEqual(len(resp._itemInfo[0]._annexes), 1) # the returned annex is the one created self.assertEqual(resp._itemInfo[0]._annexes[0]._title, 'My annex 1') self.assertIn(resp._itemInfo[0]._annexes[0]._annexTypeId, allowed_annexes_types) # filter on 'financial_annex_type_id' annex type allowed_annexes_types = [item_annex_type_id] resp = self._getItemInfos(newItem.UID(), showAnnexes=True, allowed_annexes_types=allowed_annexes_types, toBeDeserialized=False) # we have 0 annex self.assertEqual(len(resp._itemInfo[0]._annexes), 0)
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 test_content_category_confidential_on_creation(self): """ """ category_group = self.portal.config['group-1'] category = self.portal.config['group-1']['category-1-1'] content_category_id = calculate_category_id(category) category_group.confidentiality_activated = True # set to False category.confidential = False file2 = api.content.create( id='file2', type='File', file=self.file, container=self.portal, content_category=content_category_id) self.assertFalse(file2.confidential) # set to True category.confidential = True file3 = api.content.create( id='file3', type='File', file=self.file, container=self.portal, content_category=content_category_id) self.assertTrue(file3.confidential)
def migrate_annex(self): qi = self.context.portal_quickinstaller if not qi.isProductInstalled('imio.annex'): qi.installProduct('imio.annex') self.runProfileSteps('imio.project.pst', steps=['typeinfo'], run_dependencies=False) brains = self.catalog(object_provides=IProjectSpace.__identifier__) for brain in brains: pst_obj = brain.getObject() behaviour = ISelectableConstrainTypes(pst_obj) behaviour.setConstrainTypesMode(1) behaviour.setLocallyAllowedTypes(['strategicobjective', 'annex', ]) behaviour.setImmediatelyAddableTypes(['strategicobjective', 'annex', ]) portal = api.portal.get() configure_iconified_category(portal) annexTypeId = calculate_category_id(portal.categorization.annexes.get('annexes-pst')) brains = self.catalog(object_provides=IFile.__identifier__) for brain in brains: file_obj = brain.getObject() parent = file_obj.aq_parent if parent.portal_type in ['pstprojectspace', 'strategicobjective', 'operationalobjective', 'pstaction', 'pstsubaction', 'task']: annexId = file_obj.id api.content.delete(obj=parent[annexId]) api.content.create( container=parent, type='annex', id=annexId, title=file_obj.Title(), description=file_obj.Description(), content_category=annexTypeId, file=file_obj.file, ) transaction.commit()
def test_content_category_to_print_on_creation(self): """ """ category_group = self.portal.config['group-1'] category = self.portal.config['group-1']['category-1-1'] content_category_id = calculate_category_id(category) category_group.to_be_printed_activated = True # enable conversion gsettings = GlobalSettings(self.portal) gsettings.auto_layout_file_types = CONVERTABLE_TYPES.keys() # set to False category.to_print = False file2 = api.content.create( id='file2', type='File', file=self.file, container=self.portal, content_category=content_category_id) self.assertFalse(file2.to_print) # set to True category.to_print = True file3 = api.content.create( id='file3', type='File', file=self.file, container=self.portal, content_category=content_category_id) self.assertTrue(file3.to_print)
def __call__(self, context): terms = [] categories = self._get_categories(context) for category in categories: category_id = utils.calculate_category_id(category) terms.append(SimpleVocabulary.createTerm( category_id, category_id, category.Title(), )) subcategories = self._get_subcategories(context, category) for subcategory in subcategories: subcategory_id = utils.calculate_category_id(subcategory.getObject()) terms.append(SimpleVocabulary.createTerm( subcategory_id, subcategory_id, subcategory.Title, )) return SimpleVocabulary(terms)
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 test_table_render_special_chars(self): """Special chars used in : - element's title; - category title; - subcategory title.""" category = api.content.create( type='ContentCategory', title='Category \xc3\xa0', icon=self.icon, container=self.portal.config['group-1'], ) subcategory = api.content.create( type='ContentSubcategory', title='Subcategory \xc3\xa0', icon=self.icon, container=category, ) document = api.content.create( type='Document', title='Document \xc3\xa0', container=self.portal, content_category=utils.calculate_category_id(category), to_print=False, confidential=False, ) document2 = api.content.create( type='Document', title='Document \xc3\xa0', container=self.portal, content_category=utils.calculate_category_id(subcategory), to_print=False, confidential=False, ) view = self.portal.restrictedTraverse('@@iconifiedcategory') result = view() self.assertTrue(category.title in result) self.assertTrue(subcategory.title in result) self.assertTrue(document.title in result) self.assertTrue(document2.title in result)
def __call__(self, *args, **kwargs): self.request.response.setHeader('Content-Type', 'text/css') content = [] css = (u".{0} {{ padding-left: 1.4em; background: " u"transparent url('{1}') no-repeat top left; " u"background-size: contain; }}") if utils.has_config_root(self.context) is False: return '' categories = utils.get_categories(self.context) for category in categories: obj = category._unrestrictedGetObject() category_id = utils.calculate_category_id(obj) url = u'{0}/@@download'.format(obj.absolute_url()) content.append(css.format(utils.format_id_css(category_id), url)) return ' '.join(content)
def test_content_category_not_set_if_not_activated(self): """ """ category_group = self.portal.config['group-1'] category = self.portal.config['group-1']['category-1-1'] content_category_id = calculate_category_id(category) category_group.to_be_printed_activated = False category_group.confidentiality_activated = False category.to_print = True category.confidential = True obj = api.content.create( id='file2', type='File', file=self.file, container=self.portal, content_category=content_category_id) self.assertFalse(obj.to_print) self.assertFalse(obj.confidential)
def test_content_category_to_sign_signed_on_creation(self): """ """ category_group = self.portal.config['group-1'] category = self.portal.config['group-1']['category-1-1'] content_category_id = calculate_category_id(category) category_group.signed_activated = True # set to False both attributes category.to_sign = False category.signed = False file2 = api.content.create( id='file2', type='File', file=self.file, container=self.portal, content_category=content_category_id) self.assertFalse(file2.to_sign) self.assertFalse(file2.signed) # set True for to_sign, False for signed category.to_sign = True category.signed = False file3 = api.content.create( id='file3', type='File', file=self.file, container=self.portal, content_category=content_category_id) self.assertTrue(file3.to_sign) self.assertFalse(file3.signed) # set True for both attributes category.to_sign = True category.signed = True file4 = api.content.create( id='file4', type='File', file=self.file, container=self.portal, content_category=content_category_id) self.assertTrue(file4.to_sign) self.assertTrue(file4.signed)
def test_restapi_add_item_with_annexes(self): """When creating an item, we may add annexes as __children__.""" cfg = self.meetingConfig self.changeUser("pmManager") endpoint_url = "{0}/@item".format(self.portal_url) json = { "config_id": cfg.getId(), "proposingGroup": self.developers.getId(), "title": "My item", "__children__": [ { "@type": "annex", "title": "My annex", "content_category": "item-annex", "file": { "data": "123456", "encoding": "ascii", "filename": "file.txt", }, }, ], } response = self.api_session.post(endpoint_url, json=json) transaction.begin() self.assertEqual(response.status_code, 201, response.content) pmFolder = self.getMeetingFolder() item = pmFolder.objectValues()[-1] self.assertEqual(item.Title(), json["title"]) annex = get_annexes(item)[0] self.assertEqual(annex.title, json["__children__"][0]["title"]) self.assertEqual( annex.content_category, calculate_category_id( cfg.annexes_types.item_annexes.get("item-annex")), ) self.assertEqual(annex.file.filename, json["__children__"][0]["file"]["filename"]) self.assertEqual(annex.file.size, 6) self.assertEqual(annex.file.contentType, "text/plain")
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 test_content_category_to_print_only_set_if_convertible_when_conversion_enabled(self): """ """ category_group = self.portal.config['group-1'] category = self.portal.config['group-1']['category-1-1'] content_category_id = calculate_category_id(category) category_group.to_be_printed_activated = True # set to True category.to_print = True file2 = api.content.create( id='file2', type='File', file=self.file, container=self.portal, content_category=content_category_id) # enable conversion gsettings = GlobalSettings(self.portal) gsettings.auto_layout_file_types = CONVERTABLE_TYPES.keys() file2.file.contentType = 'text/unknown' notify(ObjectModifiedEvent(file2)) self.assertIsNone(file2.to_print)
def _manage_after_scan_change_annex_type_to(self, the_file): """Change annex annex_type if defined in annex_type.after_scan_change_annex_type_to.""" old_annex_type = get_category_object(the_file, the_file.content_category) after_scan_change_annex_type_to = old_annex_type.after_scan_change_annex_type_to # can not query on 'None' if not after_scan_change_annex_type_to: return brains = api.content.find(UID=old_annex_type.after_scan_change_annex_type_to) if not brains: return to_annex_type = brains[0].getObject() the_file.content_category = calculate_category_id(to_annex_type) # for items, the annex_type can move from item_annex type to item_decision_annex type # and the other way round, in this case, the annex portal_type changed if the_file.aq_parent.portal_type.startswith('MeetingItem'): old_annex_type_group = old_annex_type.get_category_group() to_annex_type_group = to_annex_type.get_category_group() if old_annex_type_group != to_annex_type_group: new_portal_type = 'annex' if to_annex_type_group.getId() == 'item_decision_annexes': new_portal_type = 'annexDecision' the_file.portal_type = new_portal_type
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_ws_getItemInfosWithAnnexesRequest(self): """ Test that getting an item with a given UID returns valuable informations and linked annexes """ cfg = self.meetingConfig self.changeUser('pmCreator1') self.failUnless( len(self.portal.portal_catalog(portal_type='MeetingItemPga')) == 0) # prepare data for a default item req = self._prepareCreationData() # add one annex data = { 'title': 'My annex 1', 'filename': 'smallTestFile.pdf', 'file': 'smallTestFile.pdf' } req._creationData._annexes = [self._prepareAnnexInfo(**data)] # create the item newItem, reponse = self._createItem(req) newItemUID = newItem.UID() # get informations about the item, by default 'showAnnexes' is False resp = self._getItemInfos(newItemUID) expected = """<ns1:getItemInfosResponse xmlns:ns1="http://ws4pm.imio.be" """ \ """xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" """ \ """xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" """ \ """xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" """ \ """xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <itemInfo xsi:type="ns1:ItemInfo"> <UID>{0}</UID> <id>{1}</id> <title>My new item title</title> <creator>pmCreator1</creator> <creation_date>{2}</creation_date> <modification_date>{3}</modification_date> <category>development</category> <description><p>Description</p></description> <detailedDescription><p>Detailed description</p></detailedDescription> <decision><p>Décision</p></decision> <preferredMeeting/> <preferred_meeting_date>1950-01-01T00:00:00.006Z</preferred_meeting_date> <review_state>itemcreated</review_state> <meeting_date>1950-01-01T00:00:00.006Z</meeting_date> <absolute_url>http://nohost/plone/Members/pmCreator1/mymeetings/plonegov-assembly/{4}</absolute_url> <externalIdentifier/> <extraInfos/> </itemInfo> </ns1:getItemInfosResponse> """.format(newItemUID, newItem.getId(), gDateTime.get_formatted_content(gDateTime(), localtime(newItem.created())), gDateTime.get_formatted_content(gDateTime(), localtime(newItem.modified())), newItem.getId()) # annexes are not shown by default self.assertEqual(expected, resp) # now with 'showAnnexes=True' financial_annex_type_id = calculate_category_id( cfg.annexes_types.item_annexes.get('financial-analysis')) item_annex_type_id = calculate_category_id( cfg.annexes_types.item_annexes.get('item-annex')) resp = self._getItemInfos(newItemUID, showAnnexes=True) expected = """<ns1:getItemInfosResponse xmlns:ns1="http://ws4pm.imio.be" """ \ """xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" """ \ """xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" """ \ """xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" """ \ """xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <itemInfo xsi:type="ns1:ItemInfo"> <UID>{0}</UID> <id>{1}</id> <title>My new item title</title> <creator>pmCreator1</creator> <creation_date>{2}</creation_date> <modification_date>{3}</modification_date> <category>development</category> <description><p>Description</p></description> <detailedDescription><p>Detailed description</p></detailedDescription> <decision><p>Décision</p></decision> <preferredMeeting/> <preferred_meeting_date>1950-01-01T00:00:00.006Z</preferred_meeting_date> <review_state>itemcreated</review_state> <meeting_date>1950-01-01T00:00:00.006Z</meeting_date> <absolute_url>http://nohost/plone/Members/pmCreator1/mymeetings/plonegov-assembly/{4}</absolute_url> <externalIdentifier/> <extraInfos/> <annexes xsi:type="ns1:AnnexInfo"> <id>smalltestfile.pdf</id> <title>My annex 1</title> <annexTypeId>{5}</annexTypeId> <filename>smallTestFile.pdf</filename> <file> {6}</file> </annexes> </itemInfo> </ns1:getItemInfosResponse> """.format(newItemUID, newItem.getId(), gDateTime.get_formatted_content(gDateTime(), localtime(newItem.created())), gDateTime.get_formatted_content(gDateTime(), localtime(newItem.modified())), newItem.getId(), financial_annex_type_id, base64.encodestring(get_annexes(newItem)[0].file.data)) # one annex is shown self.assertEqual(expected, resp) # now check with several (2) annexes... afile = open( os.path.join(os.path.dirname(__file__), 'mediumTestFile.odt')) annex_file = afile.read() afile.close() api.content.create( title='My BeautifulTestFile title', type='annex', file=namedfile.NamedBlobFile( annex_file, filename=safe_unicode(u'myBeautifulTestFile.odt')), container=newItem, content_category=item_annex_type_id, to_print=False, confidential=False) resp = self._getItemInfos(newItemUID, showAnnexes=True) expected = """<ns1:getItemInfosResponse xmlns:ns1="http://ws4pm.imio.be" """ \ """xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" """ \ """xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" """ \ """xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" """ \ """xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <itemInfo xsi:type="ns1:ItemInfo"> <UID>{0}</UID> <id>{1}</id> <title>My new item title</title> <creator>pmCreator1</creator> <creation_date>{2}</creation_date> <modification_date>{3}</modification_date> <category>development</category> <description><p>Description</p></description> <detailedDescription><p>Detailed description</p></detailedDescription> <decision><p>Décision</p></decision> <preferredMeeting/> <preferred_meeting_date>1950-01-01T00:00:00.006Z</preferred_meeting_date> <review_state>itemcreated</review_state> <meeting_date>1950-01-01T00:00:00.006Z</meeting_date> <absolute_url>http://nohost/plone/Members/pmCreator1/mymeetings/plonegov-assembly/{4}</absolute_url> <externalIdentifier/> <extraInfos/> <annexes xsi:type="ns1:AnnexInfo"> <id>{5}</id> <title>My annex 1</title> <annexTypeId>{6}</annexTypeId> <filename>smallTestFile.pdf</filename> <file> {7}</file> </annexes> <annexes xsi:type="ns1:AnnexInfo"> <id>{8}</id> <title>My BeautifulTestFile title</title> <annexTypeId>{9}</annexTypeId> <filename>myBeautifulTestFile.odt</filename> <file> {10}</file> </annexes> </itemInfo> </ns1:getItemInfosResponse> """.format(newItemUID, newItem.getId(), gDateTime.get_formatted_content(gDateTime(), localtime(newItem.created())), gDateTime.get_formatted_content(gDateTime(), localtime(newItem.modified())), newItem.getId(), get_annexes(newItem)[0].id, financial_annex_type_id, base64.encodestring(get_annexes(newItem)[0].file.data), get_annexes(newItem)[1].id, item_annex_type_id, base64.encodestring(get_annexes(newItem)[1].file.data)) # 2 annexes are shown self.assertEqual(expected, resp)