def __call__(self): submitted = self.request.form.get('import.submitted', False) if submitted: import_type = self.request.form.get('import_selection', False) import_file = self.request.form.get('import_file') path = '/'.join(self.context.getPhysicalPath()) if import_type == 'persons': # Call the persons import method imported = importCSVPersons(self.context, path, import_file) aux = _(u'%s successfuly imported persons') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/import_view?message=%s' % (status%imported,) return self.request.response.redirect(url) elif import_type == 'organizations': # Call the organizations import method imported = importCSVOrganizations(self.context, path, import_file) aux = _(u'%s successfuly imported organizations') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/import_view?message=%s' % (status%imported,) return self.request.response.redirect(url) else: pass return self.pt()
class GroupColumns(object): """ Provides the columns of a listing of groups """ translations = { 'title': _("listingheader_groups_name", default=u"Name"), 'members': _("listingheader_groups_members", default=u"Members") } def __init__(self, context): self.context = context def set_columns(self, columns): pass def get_columns(self): return ( 'title', 'members', ) def get_raw_columns(self): return ( ('title', True), ('members', True), ) def translate_column(self, column): """ Translates a column """ return self.translations.get(column, column)
class IAddressBook(Interface): """An address book""" sectors = schema.TextLine( title=_(u"Sectors"), required=False, description=_(u"Add here sectors and subsectors that will be used by " "organizations."), )
class GroupListView(AbstractListView): """ Lists groups """ implements(IViewView) template_id = 'groups' name = 'group' page_size = 20 error_msg = _('no_groups', default=u'There are no groups available') title = _('Groups')
class PersonListView(AbstractListView): """ Lists persons """ implements(IViewView) template_id = 'persons' name = 'person' page_size = 20 error_msg = _('no_persons', default=u'There are no persons available') title = _('Persons')
class ImportView(BrowserView): """ Import browser view """ pt = ViewPageTemplateFile('./templates/import.pt') labels = { 'person': _('label_persons', default=u'Persons'), 'organization': _('label_organizations', default=u'Organizations'), 'group': _(u'Groups') } def __init__(self, context, request): self.context = context self.request = request def __call__(self): self.errors = None self.message = None submitted = self.request.form.get('import.submitted', False) if submitted: import_type = self.request.form.get('import_selection', False) import_file = self.request.form.get('import_file') statusmessage = IStatusMessage(self.request) if not import_file: statusmessage.addStatusMessage( _(u'Please select a file to import'), 'error') else: # Call the import method handler = getAdapter(self.context, interface=IImport, name=import_type) imported = handler.importFile(import_file) self.errors = handler.errors() statusmessage.addStatusMessage(handler.successMsg(imported), 'info') return self.pt() @memoize def importFormats(self): return [{ 'value': name, 'title': self.labels.get(name.split('.')[0], name.split('.')[0]), 'format': adapter.title } for name, adapter in getAdapters((self.context, ), IImport) if len(name.split('.')) > 1]
class OrganizationListView(AbstractListView): """ Lists organizations """ implements(IViewView) template_id = 'organizations' name = 'organization' page_size = 20 error_msg = _('no_organizations', default=u'There are no organizations available') title = _('Organizations')
class IGroup(Interface): """Let you have several persons together""" # -*- schema definition goes here -*- persons = schema.Object( title=_(u"Persons"), required=False, description=_(u"The persons that belong to this group"), schema=IPerson, # specify the interface(s) of the addable types here )
def kssModifyState(self, country=None, search=0): """ This method is used to update the province drop down when adding a person or organization and also from the advanced search template that's why it has some ugly logic. Perhaps should be divided in two methods, one that gets called from the ct, and another one that gets called from the search template """ context = aq_inner(self.context) ksscore = self.getCommandSet('core') utility = zapi.getUtility(ICountriesStates) if not search and not country: # This is necessary for the inline edition country = context.getCountry() if country and country != '--': # I will be here if the country has -- selected, in which case # i should return all states possible results = TitledVocabulary.fromTitles(utility.states(country=country)) else: # I will be here if the country has something selected, in which # case i should return a filtered state list results = TitledVocabulary.fromTitles(utility.states()) if search: selector = ksscore.getHtmlIdSelector('form.state') result_html = u'<select name="form.state" id="form.state">' else: selector = ksscore.getHtmlIdSelector('state') result_html = u'<select name="state" id="state">' for i in results._terms: aux = _(i.value) value = zope.i18n.translate(aux, context=self.request) aux = _(i.title) title = zope.i18n.translate(aux, context=self.request) if not search and context.state == value: result_html += (u'<option value="%s" selected="True">%s' '</option>' % (value,title)) else: result_html += (u'<option value="%s">%s</option>' % (value,title)) result_html += u'</select>' # I replace the existing drop down ksscore.replaceHTML(selector, result_html) # and finally we render return self.render()
def __call__(self): self.request.set('disable_border', 1) # redirect on cancel if self.request.get('form.actions.label_cancel'): return self.request.response.redirect('%s/list_%ss' % (self.context.absolute_url(), self.name)) # redirect on import if self.request.get('form.button.import', None) is not None: parent = aq_inner(self.context) while not IAddressBook.providedBy(parent): parent = aq_parent(parent) if not _checkPermission(ModifyPortalContent, parent): raise Unauthorized return self.request.response.redirect('%s/import' % parent.absolute_url()) self.error = None self.quick = self.request.get('quicksearch', None) is not None mail = self.request.get('form.button.mailto', None) is not None export = self.request.get('form.button.export', None) is not None exportall = self.request.get('form.button.exportall', None) is not None exportsearch = self.request.get('form.button.exportsearch', None) is not None exportformat = self.request.get('form.exportformat', 'csv') advanced = self.request.get('form.button.advanced', None) is not None rows = self.table.rows() self.batch = Batch(rows, self.page_size, self.request.form.get('b_start', 0)) selection = self.get_selection() if (export or mail) and not selection: self.error = _(u'You need to select at least one person or organization') elif mail: self.mailto = self.get_mailto(selection) if not self.mailto.strip(): self.error = _(u'You need to select at least one person or organization that has an email') elif export or exportall or exportsearch: if exportsearch: selection = [row['object'] for row in rows] handler = queryAdapter(self.context, interface=IExport, name=exportformat) if handler is None: handler = queryAdapter(self.context, interface=IExport, name='%s.csv' % self.name) return handler.export(self.request, (export or exportsearch) and selection or None) elif advanced: return self.request.RESPONSE.redirect(self.advanced_url()) if self.error: statusmessage = IStatusMessage(self.request) statusmessage.addStatusMessage(self.error, 'error') return self.request.response.redirect(self.back_url()) return self.template()
class OrganizationVCardExport(AbstractTemplateExport): implements(IExport) title = _(u"Business Card (vCard)") contents = """N:%(title)s FN:%(title)s TITLE:%(sector)s ROLE:%(sub_sector)s TEL;TYPE=WORK:%(phone)s TEL;TYPE=WORK:%(phoneInternal)s TEL;TYPE=WORK,FAX:%(fax)s EMAIL;TYPE=WORK,PREF,INTERNET:%(email)s EMAIL;TYPE=WORK,INTERNET:%(email2)s EMAIL;TYPE=WORK,INTERNET:%(email3)s ADR;TYPE=WORK:;;%(address)s;%(extraAddress)s;%(city)s;%(state)s;%(zip)s;%(country)s LABEL;TYPE=WORK:%(address)s\\n%(extraAddress)s\\n%(city)s, %(state)s %(zip)s\\n%(country)s URL:%(web)s NOTE:%(text)s UID:%(UID)s REV:%(revision)s""" def export(self, request=None, objects=None): if not objects: if IOrganization.providedBy(self.context): objects = [self.context] else: search = getAdapter(self.context, interface=ISearch, name='organization') objects = search.search() return self._export( objects, len(objects) > 1 and 'organizations' or objects[0].getId(), request)
def __call__(self): self.errors = None self.message = None submitted = self.request.form.get('import.submitted', False) if submitted: import_type = self.request.form.get('import_selection', False) import_file = self.request.form.get('import_file') statusmessage = IStatusMessage(self.request) if not import_file: statusmessage.addStatusMessage( _(u'Please select a file to import'), 'error') else: # Call the import method handler = getAdapter(self.context, interface=IImport, name=import_type) imported = handler.importFile(import_file) self.errors = handler.errors() statusmessage.addStatusMessage(handler.successMsg(imported), 'info') return self.pt()
def __call__(self): submitted = self.request.form.get('import.submitted', False) if submitted: import_selection = self.request.form.get('import_selection', False) #print import_selection import_content_type = 'JubinStationPartner' # default if import_selection == 'restaurants': import_content_type = 'JubinRestaurantPartner' if import_selection == 'commerces': import_content_type = 'JubinCommercialPartner' import_file = self.request.form.get('import_file') path = '/'.join(self.context.getPhysicalPath()) # Call the organizations import method imported = importCSVPartners(self.context, path, import_file, import_content_type) aux = _(u'%s successfuly imported organizations') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/partner_import_view?message=%s' % (status%imported,) return self.request.response.redirect(url) return self.pt()
class GroupView(PersonListView): """ Displays information about a group """ error_msg = _('no_persons_in_group', default=u'There are no persons assigned to this group') @property def title(self): return self.context.Title()
def kssModifySector(self, sector=None, search=0): """ This method is used to update the sub sector drop down when adding an organization and also from the advanced search template that's why it has some ugly logic. Perhaps should be divided in two methods, one that gets called from the ct, and another one that gets called from the search template """ context = aq_inner(self.context) ksscore = self.getCommandSet('core') if search: # If i'm here means i'm inside the search template address_book = context else: # If i'm here means i'm inside some ct address_book = context.aq_parent if not sector: # This is necessary for the inline edition sector = context.getSector() if not sector or sector == '--': # If i'm here, means someone selected the -- sector, in which # case, i should return all sub sectors available sub_sectors = address_book.get_all_sub_sectors() else: # If i'm here, means someone selected some sector, in which case, # i should return a filtered sub sector list sub_sectors = address_book.get_sub_sectors(sector) results = TitledVocabulary.fromTitles([('--',_(u'(no value)'))] + zip(sub_sectors, sub_sectors)) if search: selector = ksscore.getHtmlIdSelector('form.sub_sector') # If i'm here means i'm inside the advanced search template # so i create the html needed for the sub sector drop down result_html = u'<select name="form.sub_sector" id="form.sub_sector" size="1">' else: selector = ksscore.getHtmlIdSelector('sub_sector') # If i'm here, means i'm inside some ct, then i create the html # for the drop down result_html = u'<select name="sub_sector" id="sub_sector">' for i in results._terms: if not search and context.sub_sector == i.value: result_html += (u'<option value="%s" selected="True">%s' '</option>' % (i.value,i.title)) else: result_html += (u'<option value="%s">%s</option>' % (i.value,i.title)) result_html += u'</select>' # replace the existing one ksscore.replaceHTML(selector, result_html) # And finally render return self.render()
class OrganizationView(PersonListView): """ Displays information about an organization """ error_msg = _('no_persons_in_organization', default=u'There are no persons in this organization') @property def title(self): return _('Persons part of ${organization}', mapping={'organization': safe_unicode(self.context.Title())})
def getLocalized(self, instance, **kwargs): month, day = self._split(instance) if not day or not month: return '' return _(u'date_format', default=u'${m}/${d}', mapping={ 'd': day, 'm': month })
def update(self): super(ContactsActionsViewlet, self).update() plone_utils = getToolByName(self.context, 'plone_utils') self.getIconFor = plone_utils.getIconFor self.actions = self.context_state.actions().get('contacts_actions', []) if ICustomizableView.providedBy(self.view) and \ self.view.customize_url() is not None: self.actions.append({'id': 'customize', 'title': _(u'customize_view', default=u'Customize view'), 'url': self.view.customize_url(), 'description': ''})
class FindOrganizationForm(PageForm): form_fields = form.FormFields(IOrganization).omit('email2', 'email3') form_fields['country'].custom_widget = CustomDropdownWidgetFactory form_fields['state'].custom_widget = CustomDropdownWidgetFactory form_fields['sector'].custom_widget = CustomDropdownWidgetFactory form_fields['sub_sector'].custom_widget = CustomDropdownWidgetFactory label = _('advanced_organizations_search', default=u'Advanced organizations search:') def __call__(self): self.request.set('disable_border', 1) # change the form action the point to the search page self.request.set('URL', '%s/search_organization' % self.context.absolute_url()) return super(FindOrganizationForm, self).__call__() @form.action(_('label_search_organizations', default=u'Search Organizations')) def action_search(self, action, data): pass @form.action(_('label_cancel', default=u'Cancel')) def action_cancel(self, action, data): pass
class FindPersonForm(PageForm): form_fields = form.FormFields(IPerson).omit('workEmail2', 'workEmail3', 'photo', 'organization', 'birthdate') form_fields['country'].custom_widget = CustomDropdownWidgetFactory form_fields['state'].custom_widget = CustomDropdownWidgetFactory label = _('advanced_persons_search', default=u'Advanced persons search:') def __call__(self): self.request.set('disable_border', 1) self.form_fields['firstName'].field.required = False self.form_fields['lastName'].field.required = False # change the form action the point to the search page self.request.set('URL', '%s/search_person' % self.context.absolute_url()) return super(FindPersonForm, self).__call__() @form.action(_('label_search_persons', default=u'Search Persons')) def action_search(self, action, data): pass @form.action(_('label_cancel', default=u'Cancel')) def action_cancel(self, action, data): pass
def __call__(self): submitted = self.request.form.get('import.submitted', False) if submitted: import_type = self.request.form.get('import_selection', False) import_file = self.request.form.get('import_file') path = '/'.join(self.context.getPhysicalPath()) if import_type == 'persons': # Call the persons import method imported = importCSVPersons(self.context, path, import_file) aux = _(u'%s successfuly imported persons') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/import_view' IStatusMessage(self.request).addStatusMessage((status%imported), type='info') return self.request.response.redirect(url) elif import_type == 'organizations': # Call the organizations import method imported = importCSVOrganizations(self.context, path, import_file) aux = _(u'%s successfuly imported organizations') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/import_view?message=%s' % (status%imported,) return self.request.response.redirect(url) else: pass return self.pt()
def __call__(self): self.contenttype = self.request.get('customize.type', False) cancelled = self.request.form.get('form.button.cancel', False) if cancelled or self.contenttype not in ('organization', 'person'): return self.redirect() self.columns = getAdapter(self.context, interface=ICustomizableColumns, name=self.contenttype) submitted = self.request.form.get('customize.submitted', False) if submitted: self.columns.set_columns(self.request.form.get('selected', [])) statusmessage = IStatusMessage(self.request) statusmessage.addStatusMessage(_(u'View successfully customized'), 'info') return self.redirect() return self.pt()
class PersonVCardExport(AbstractTemplateExport): implements(IExport) title = _(u"Business Card (vCard)") contents = """N:%(lastName)s;%(firstName)s FN:%(title)s NICKNAME:%(shortName)s ORG:%(organization)s TITLE:%(position)s ROLE:%(department)s BDAY:%(birthdate)s TEL;TYPE=WORK:%(workPhone)s TEL;TYPE=WORK:%(workPhoneInternal)s TEL;TYPE=WORK,FAX:%(workFax)s TEL;TYPE=WORK,CELL,MSG:%(workMobilePhone)s EMAIL;TYPE=WORK,PREF:%(workEmail)s EMAIL;TYPE=WORK:%(workEmail2)s EMAIL;TYPE=WORK:%(workEmail3)s TEL;TYPE=HOME:%(phone)s TEL;TYPE=HOME,CELL,MSG:%(mobilePhone)s EMAIL;TYPE=HOME,PREF:%(email)s ADR;TYPE=HOME:;;%(address)s;%(city)s;%(state)s;%(zip)s;%(country)s LABEL;TYPE=HOME:%(address)s\\n%(city)s, %(state)s %(zip)s\\n%(country)s %(photo)s URL:%(web)s NOTE:%(text)s UID:%(UID)s REV:%(revision)s""" def export(self, request=None, objects=None): if not objects: if IPerson.providedBy(self.context): objects = [self.context] else: search = getAdapter(self.context, interface=ISearch, name='person') objects = search.search() return self._export( objects, len(objects) > 1 and 'persons' or objects[0].getId(), request)
def __call__(self): self.errors = None self.message = None submitted = self.request.form.get('import.submitted', False) if submitted: import_type = self.request.form.get('import_selection', False) import_file = self.request.form.get('import_file') statusmessage = IStatusMessage(self.request) if not import_file: statusmessage.addStatusMessage(_(u'Please select a file to import'), 'error') else: # Call the import method handler = getAdapter(self.context, interface=IImport, name=import_type) imported = handler.importFile(import_file) self.errors = handler.errors() statusmessage.addStatusMessage(handler.successMsg(imported), 'info') return self.pt()
from collective.contacts.interfaces import IAddressBook from Products.CMFCore.interfaces import ISiteRoot from Acquisition import aq_parent PersonSchema = schemata.ATContentTypeSchema.copy() + atapi.Schema( ( # -*- Your Archetypes field definitions here ... -*- atapi.ComputedField("title", searchable=1, expression="context._compute_title()", accessor="Title"), atapi.StringField( name="shortName", storage=atapi.AnnotationStorage(), required=False, searchable=1, # default='', # schemata ='default', widget=atapi.StringWidget(label=_(u"Short Name"), description=_(u"Person's short name")), ), atapi.StringField( "firstName", storage=atapi.AnnotationStorage(), widget=atapi.StringWidget(label=_(u"First Name"), description=_(u"Person's first name")), searchable=1, required=True, ), atapi.StringField( "lastName", storage=atapi.AnnotationStorage(), widget=atapi.StringWidget(label=_(u"Last Name"), description=_(u"Person's last name")), searchable=1, required=True, ),
from Products.Archetypes import atapi from Products.ATContentTypes.content import base from Products.ATContentTypes.content import schemata from collective.contacts import contactsMessageFactory as _ from collective.contacts.interfaces import IOrganization from collective.contacts.config import PROJECTNAME from collective.contacts.content import DeprecatedATFieldProperty OrganizationSchema = schemata.ATContentTypeSchema.copy() + atapi.Schema( ( # -*- Your Archetypes field definitions here ... -*- atapi.StringField( "address", storage=atapi.AnnotationStorage(), widget=atapi.StringWidget(label=_(u"Address"), description=_(u"Organization's address")), required=False, searchable=1, ), atapi.StringField( "country", storage=atapi.AnnotationStorage(), widget=atapi.SelectionWidget(label=_(u"Country"), description=_(u"Organization's country")), vocabulary_factory="contacts.countries", required=False, searchable=1, ), atapi.StringField( "state", storage=atapi.AnnotationStorage(), widget=atapi.SelectionWidget(label=_(u"State"), description=_(u"Organization's state")),
def importFile(self, file): self._errors = [] LOG(PROJECTNAME, INFO, 'Starting the persons import process') portal_catalog = getToolByName(self.context, 'portal_catalog') # Now that we have all our configuration, we can start # First we set our results as an empty list, we will be loading # each user here results = [] # we first make sure the content is in utf8 reader = UnicodeReader(file) # Now we first load the headers headers = reader.next() rowLength = len(headers) if rowLength != len(self.fields): self._errors.append( _('import_error_format', default= u'Wrong file format. Export an existing address book as CSV to get a reference file.' )) return 0 for field in self.fields: if not field in headers: self._errors.append( _('import_error_format', default= u'Wrong file format. Export an existing address book as CSV to get a reference file.' )) return 0 counter = 0 # Now i have to continue loading the rest of the persons for row in reader: # We now check that we have consistency in our CSV if not len(row) == rowLength: self._errors.append( _('import_error_format', default= u'Wrong file format. Export an existing address book as CSV to get a reference file.' )) return 0 result = {} for j in range(rowLength): result[headers[j]] = row[j] # And now, i have a new user, i add it to the results results.append(result) counter += 1 path = '/'.join(self.context.getPhysicalPath()) LOG(PROJECTNAME, INFO, '%s persons to be added to %s.' % (counter, path)) counter = 0 # I now have all persons in my results, so i should start adding them to # the site search = getAdapter(self.context, interface=ISearch, name="organization") for person in results: organization = None if person['organization']: organization = search.search({'id': person['organization']}) if organization and len(organization) > 1: self._errors.append( _('import_error_multipleorganizations', default= u'There are ${number} organizations with the same id, ' 'I don\'t know with which one relate this person. ' 'You will have to load the person with id ${person_id} ' 'manually.', mapping={ 'number': len(organization), 'person_id': person['id'] })) LOG( PROJECTNAME, WARNING, 'There are %s organizations with the same id, ' 'I don\'t know with which one relate this person.' % len(organization)) LOG( PROJECTNAME, WARNING, 'You will have to load the person with id %s ' 'manually.' % person['id']) elif ((organization and len(organization) == 1) or not person['organization']): if self.context.get(person['id']): self._errors.append( _('import_error_personexists', default= u'There\'s already a person with this id here. ' 'You will have to load the person with id ${person_id} ' 'manually.', mapping={'person_id': person['id']})) LOG(PROJECTNAME, WARNING, 'There\'s already a person with this id here.') LOG( PROJECTNAME, WARNING, 'You will have to load the person with id ' '%s manually.' % person['id']) else: try: self.context.invokeFactory('Person', person['id']) new_person = self.context.get(person['id']) for attr in person.keys(): if attr != 'id' and attr != 'organization': setattr(new_person, attr, person[attr]) if (attr == 'organization' and person['organization'] != ''): new_person.setOrganization(organization[0]) counter += 1 portal_catalog.reindexObject(new_person) LOG(PROJECTNAME, INFO, 'Successfully added %s.' % person['id']) except: self._errors.append( _('import_error_person', default=u'There was an error while adding. ' 'You will have to load the person with id ${person_id} ' 'manually.', mapping={'person_id': person['id']})) LOG(PROJECTNAME, WARNING, 'There was an error while adding.') LOG( PROJECTNAME, WARNING, 'You will have to load the person with id ' '%s manually.' % person['id']) else: self._errors.append( _('import_error_noorganization', default= u'There\'s no organization with id ${organization_id} ' 'make sure it exists before adding persons. ' '${person_id} not added', mapping={ 'organization_id': person['organization'], 'person_id': person['id'] })) LOG( PROJECTNAME, WARNING, 'There\'s no organization with id %s, ' 'make sure it exists before adding persons. ' '%s not added' % (person['organization'], person['id'])) LOG(PROJECTNAME, INFO, 'Successfully added %s persons to %s.' % (counter, path)) return counter
def successMsg(self, imported): return _(u'Successfully imported ${number} persons', mapping={'number': imported})
def getLocalized(self, instance, **kwargs): month, day = self._split(instance) if not day or not month: return '' return _(u'date_format', default=u'${m}/${d}', mapping={'d': day, 'm': month})
from Products.ATContentTypes.content import base from Products.ATContentTypes.content import schemata from collective.contacts import contactsMessageFactory as _ from collective.contacts.interfaces import IOrganization from collective.contacts.config import PROJECTNAME OrganizationSchema = schemata.ATContentTypeSchema.copy() + atapi.Schema(( # -*- Your Archetypes field definitions here ... -*- atapi.StringField( 'address', storage=atapi.AnnotationStorage(), widget=atapi.StringWidget( label=_(u"Address"), description=_(u"Organization's address"), ), required=False, searchable=1, ), atapi.StringField( 'country', storage=atapi.AnnotationStorage(), widget=atapi.SelectionWidget( label=_(u"Country"), description=_(u"Organization's country"), ), vocabulary_factory='contacts.countries', required=False,
def title(self): return _('Persons part of ${organization}', mapping={'organization': safe_unicode(self.context.Title())})
def importCSVPartners(context, path, file, content_type): """ This function is used to import partners to a given path using a CSV file. """ aux = _("Starting the partners import process") msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) # First we set our results as an empty list, we will be loading # each user here results = [] portal_catalog = getToolByName(context, 'portal_catalog') # we first make sure the content is in utf8 reader = UnicodeReader(file) # Now we first load the headers headers = reader.next() rowLength = len(headers) counter = 0 # Now i have to continue loading the rest of the items for row in reader: # We now check that we have consistency in our CSV assert len(row) == rowLength result = {} for j in range(rowLength): result[headers[j]] = row[j] # And now, i have a new item, i add it to the results results.append(result) counter += 1 aux = _('${items_number} partners to be added to ${location}.',\ mapping={'items_number':counter, 'location':path}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) counter = 0 # I now have all items in my results, so i should start adding them to site for item in results: print item # title item_title = item['title'] if item.has_key('title_prefix'): # if there is a prefix such as 'Restaurant' or 'Hotel-restaurant' item_title = "%s %s" % (item['title_prefix'], item_title) # id item_id = '' if item.has_key('id'): item_id = normalize_name(item['id']) # we make sure we have a normalized string else: # use 'title' for that item_id = normalize_name(item_title) if context.get(item_id): aux = _("There's already an item with this id here.") msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the item with id ' '${item_id} manually.',\ mapping={'item_id': item_id}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) else: try: context.invokeFactory(content_type, item_id) obj = context.get(item_id) for attr in item.keys(): if attr == 'id': continue elif attr in ['title_prefix',]: # those we do not use directly continue elif attr == 'title': # case : use the value we already calculated (to take prefix into account) setattr(obj, 'title', item_title) elif attr == 'city': # case : city name needs to be normalized setattr(obj, attr, normalize_name(item[attr])) elif attr in ['sp95', 'sp98', 'shop', 'gaz', 'diesel', 'lavage']: # special case : boolean if item[attr] in ['x', 'X']: setattr(obj, attr, True) else: setattr(obj, attr, item[attr]) counter += 1 portal_catalog.reindexObject(obj) aux = _('Successfuly added ${item_id}.',\ mapping={'item_id': item_id}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) except: aux = _('There was an error while adding.') msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the item with id ' '${item_id} manually.',\ mapping={'item_id': item_id}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('Successfuly added ${items_number} items to ${location}.',\ mapping={'items_number':counter, 'location':path}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) return counter
from collective.contacts.config import PROJECTNAME from collective.contacts.interfaces import IAddressBook from Acquisition import aq_parent from Products.CMFCore.interfaces import ISiteRoot GroupSchema = schemata.ATContentTypeSchema.copy() + atapi.Schema( ( # -*- Your Archetypes field definitions here ... -*- atapi.ReferenceField( name="persons", storage=atapi.AnnotationStorage(), required=False, widget=ReferenceBrowserWidget( label=_(u"Persons"), description=_(u"The persons that belong to this group"), restrict_browsing_to_startup_directory=True, startup_directory_method="getAddressBookPath", ), searchable=1, relationship="group_person", allowed_types=("Person",), multiValued=True, ), ) ) # Set storage on fields copied from ATContentTypeSchema, making sure # they work well with the python bridge properties.
def importFile(self, file): self._errors = [] LOG(PROJECTNAME, INFO, 'Starting the persons import process') portal_catalog = getToolByName(self.context, 'portal_catalog') # Now that we have all our configuration, we can start # First we set our results as an empty list, we will be loading # each user here results = [] # we first make sure the content is in utf8 reader = UnicodeReader(file) # Now we first load the headers headers = reader.next() rowLength = len(headers) if rowLength != len(self.fields): self._errors.append(_('import_error_format', default=u'Wrong file format. Export an existing address book as CSV to get a reference file.')) return 0 for field in self.fields: if not field in headers: self._errors.append(_('import_error_format', default=u'Wrong file format. Export an existing address book as CSV to get a reference file.')) return 0 counter = 0 # Now i have to continue loading the rest of the persons for row in reader: # We now check that we have consistency in our CSV if not len(row) == rowLength: self._errors.append(_('import_error_format', default=u'Wrong file format. Export an existing address book as CSV to get a reference file.')) return 0 result = {} for j in range(rowLength): result[headers[j]] = row[j] # And now, i have a new user, i add it to the results results.append(result) counter += 1 path = '/'.join(self.context.getPhysicalPath()) LOG(PROJECTNAME, INFO, '%s persons to be added to %s.' % (counter, path)) counter = 0 # I now have all persons in my results, so i should start adding them to # the site search = getAdapter(self.context, interface=ISearch, name="organization") for person in results: organization = None if person['organization']: organization = search.search({'id': person['organization']}) if organization and len(organization)>1: self._errors.append(_('import_error_multipleorganizations', default=u'There are ${number} organizations with the same id, ' 'I don\'t know with which one relate this person. ' 'You will have to load the person with id ${person_id} ' 'manually.', mapping={'number': len(organization), 'person_id': person['id']})) LOG(PROJECTNAME, WARNING, 'There are %s organizations with the same id, ' 'I don\'t know with which one relate this person.' % len(organization)) LOG(PROJECTNAME, WARNING, 'You will have to load the person with id %s ' 'manually.' % person['id']) elif ((organization and len(organization)==1) or not person['organization']): if self.context.get(person['id']): self._errors.append(_('import_error_personexists', default=u'There\'s already a person with this id here. ' 'You will have to load the person with id ${person_id} ' 'manually.', mapping={'person_id': person['id']})) LOG(PROJECTNAME, WARNING, 'There\'s already a person with this id here.') LOG(PROJECTNAME, WARNING, 'You will have to load the person with id ' '%s manually.' % person['id']) else: try: self.context.invokeFactory('Person', person['id']) new_person = self.context.get(person['id']) for attr in person.keys(): if attr != 'id' and attr != 'organization': setattr(new_person, attr, person[attr]) if (attr == 'organization' and person['organization'] != ''): new_person.setOrganization(organization[0]) counter += 1 portal_catalog.reindexObject(new_person) LOG(PROJECTNAME, INFO, 'Successfully added %s.' % person['id']) except: self._errors.append(_('import_error_person', default=u'There was an error while adding. ' 'You will have to load the person with id ${person_id} ' 'manually.', mapping={'person_id': person['id']})) LOG(PROJECTNAME, WARNING, 'There was an error while adding.') LOG(PROJECTNAME, WARNING, 'You will have to load the person with id ' '%s manually.' % person['id']) else: self._errors.append(_('import_error_noorganization', default=u'There\'s no organization with id ${organization_id} ' 'make sure it exists before adding persons. ' '${person_id} not added', mapping={'organization_id': person['organization'], 'person_id': person['id']})) LOG(PROJECTNAME, WARNING, 'There\'s no organization with id %s, ' 'make sure it exists before adding persons. ' '%s not added' % (person['organization'], person['id'])) LOG(PROJECTNAME, INFO, 'Successfully added %s persons to %s.' % (counter, path)) return counter
def birthdaysummary(self, object, value): name = object.title if hasattr(self.context, 'REQUEST'): return translate(_(u'Birthday of ${name}', mapping={'name': name}), context=self.context.REQUEST) return u'Birthday of %s' % name
@indexer(IGroup) def members(obj): return len(obj.persons) GroupSchema = schemata.ATContentTypeSchema.copy() + atapi.Schema(( # -*- Your Archetypes field definitions here ... -*- atapi.ReferenceField( name='persons', storage=atapi.AnnotationStorage(), required=False, widget=ReferenceBrowserWidget( label=_(u"Persons"), description=_(u"The persons that belong to this group"), restrict_browsing_to_startup_directory=True, ), searchable=1, relationship='group_person', allowed_types=('Person', ), multiValued=True, ), )) # Set storage on fields copied from ATContentTypeSchema, making sure # they work well with the python bridge properties. GroupSchema['title'].storage = atapi.AnnotationStorage() GroupSchema['description'].storage = atapi.AnnotationStorage()
def importCSVOrganizations(context, path, file): """ This function is used to import organizations to a given path using a CSV file. """ aux = _("Starting the organizations import process") msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) # First we set our results as an empty list, we will be loading # each user here results = [] portal_catalog = getToolByName(context, 'portal_catalog') # we first make sure the content is in utf8 reader = UnicodeReader(file) # Now we first load the headers headers = reader.next() rowLength = len(headers) counter = 0 # Now i have to continue loading the rest of the persons for row in reader: # We now check that we have consistency in our CSV assert len(row) == rowLength result = {} for j in range(rowLength): result[headers[j]] = row[j] # And now, i have a new user, i add it to the results results.append(result) counter += 1 aux = _('${organizations_number} organizations to be added to ${location}.',\ mapping={'organizations_number':counter, 'location':path}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) counter = 0 # I now have all persons in my results, so i should start adding them to site for organization in results: if context.get(organization['id']): aux = _("There's already an organization with this id here.") msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the organization with id ' '${organization_id} manually.',\ mapping={'organization_id':organization['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) else: try: context.invokeFactory('Organization', organization['id']) new_organization = context.get(organization['id']) for attr in organization.keys(): if attr != 'id': setattr(new_organization, attr, organization[attr]) counter += 1 portal_catalog.reindexObject(new_organization) aux = _('Successfuly added ${organization_id}.',\ mapping={'organization_id':organization['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) except: aux = _('There was an error while adding.') msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the organization with id ' '${organization_id} manually.',\ mapping={'organization_id':organization['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('Successfuly added ${organizations_number} organizations to ${location}.',\ mapping={'organizations_number':counter, 'location':path}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) return counter
from collective.contacts import contactsMessageFactory as _ from collective.contacts.interfaces import IAddressBook from collective.contacts.config import PROJECTNAME from Products.Archetypes.interfaces import IObjectInitializedEvent, IObjectEditedEvent from zope.component import adapter import transaction AddressBookSchema = folder.ATFolderSchema.copy() + atapi.Schema(( # -*- Your Archetypes field definitions here ... -*- RecordsField( name='sectors', widget=RecordsWidget( description=_('Add here sectors and subsectors that will be used ' 'by organizations.'), visible={'view': 'invisible', 'edit': 'visible'}, label=_('Sectors'), ), required=False, ), )) # Set storage on fields copied from ATFolderSchema, making sure # they work well with the python bridge properties. AddressBookSchema['title'].storage = atapi.AnnotationStorage() AddressBookSchema['description'].storage = atapi.AnnotationStorage() AddressBookSchema['sectors'].subfields = ('sector', 'sub_sector') AddressBookSchema['sectors'].subfield_types = {
class IPerson(Interface): """Contact information of a person""" # -*- schema definition goes here -*- shortName = schema.TextLine( title=_(u"Short Name"), required=False, ) firstName = schema.TextLine( title=_(u"First Name"), required=True, ) lastName = schema.TextLine( title=_(u"Last Name"), required=True, ) birthdate = schema.TextLine( title=_(u"Date of birth"), required=False, ) organization = schema.Object( title=_(u"Organization"), required=False, schema= IOrganization, # specify the interface(s) of the addable types here ) position = schema.TextLine( title=_(u"Position"), required=False, ) department = schema.TextLine( title=_(u"Department"), required=False, ) workPhone = schema.TextLine( title=_(u"Work Phone Number"), required=False, ) workPhoneInternal = schema.TextLine( title=_(u"Internal Work Phone Number"), required=False, ) workMobilePhone = schema.TextLine( title=_(u"Work Mobile Phone Number"), required=False, ) workFax = schema.TextLine( title=_(u"Work Fax number"), required=False, ) workEmail = schema.TextLine( title=_(u"Work E-mail address"), required=False, ) workEmail2 = schema.TextLine( title=_(u"2nd Work E-mail address (optional)"), required=False, ) workEmail3 = schema.TextLine( title=_(u"3rd Work E-mail address (optional)"), required=False, ) photo = schema.Bytes( title=_(u"Photo"), required=False, ) address = schema.TextLine( title=_(u"Address"), required=False, ) country = schema.Choice(title=_(u"Country"), required=False, vocabulary='contacts.countries') state = schema.Choice(title=_(u"State"), required=False, vocabulary='contacts.states') city = schema.TextLine( title=_(u"City"), required=False, ) zip = schema.TextLine( title=_(u"ZIP"), required=False, ) phone = schema.TextLine( title=_(u"Phone Number"), required=False, ) mobilePhone = schema.TextLine( title=_(u"Mobile Phone Number"), required=False, ) email = schema.TextLine( title=_(u"E-mail address"), required=False, ) web = schema.TextLine( title=_(u"Web / Blog"), required=False, ) text = schema.TextLine( title=_(u"Text"), required=False, )
def __call__(self): self.request.set('disable_border', 1) # redirect on cancel if self.request.get('form.actions.label_cancel'): return self.request.response.redirect( '%s/list_%ss' % (self.context.absolute_url(), self.name)) # redirect on import if self.request.get('form.button.import', None) is not None: parent = aq_inner(self.context) while not IAddressBook.providedBy(parent): parent = aq_parent(parent) if not _checkPermission(ModifyPortalContent, parent): raise Unauthorized return self.request.response.redirect('%s/import' % parent.absolute_url()) self.error = None self.quick = self.request.get('quicksearch', None) is not None mail = self.request.get('form.button.mailto', None) is not None export = self.request.get('form.button.export', None) is not None exportall = self.request.get('form.button.exportall', None) is not None exportsearch = self.request.get('form.button.exportsearch', None) is not None exportformat = self.request.get('form.exportformat', 'csv') advanced = self.request.get('form.button.advanced', None) is not None rows = self.table.rows() self.batch = Batch(rows, self.page_size, self.request.form.get('b_start', 0)) selection = self.get_selection() if (export or mail) and not selection: self.error = _( u'You need to select at least one person or organization') elif mail: self.mailto = self.get_mailto(selection) if not self.mailto.strip(): self.error = _( u'You need to select at least one person or organization that has an email' ) elif export or exportall or exportsearch: if exportsearch: selection = [row['object'] for row in rows] handler = queryAdapter(self.context, interface=IExport, name=exportformat) if handler is None: handler = queryAdapter(self.context, interface=IExport, name='%s.csv' % self.name) return handler.export(self.request, (export or exportsearch) and selection or None) elif advanced: return self.request.RESPONSE.redirect(self.advanced_url()) if self.error: statusmessage = IStatusMessage(self.request) statusmessage.addStatusMessage(self.error, 'error') return self.request.response.redirect(self.back_url()) return self.template()
def importFile(self, file): self._errors = [] LOG(PROJECTNAME, INFO, 'Starting the organizations import process') # First we set our results as an empty list, we will be loading # each user here results = [] portal_catalog = getToolByName(self.context, 'portal_catalog') # we first make sure the content is in utf8 reader = UnicodeReader(file) # Now we first load the headers headers = reader.next() rowLength = len(headers) if rowLength != len(self.fields): self._errors.append( _('import_error_format', default= u'Wrong file format. Export an existing address book as CSV to get a reference file.' )) return 0 for field in self.fields: if not field in headers: self._errors.append( _('import_error_format', default= u'Wrong file format. Export an existing address book as CSV to get a reference file.' )) return 0 counter = 0 # Now i have to continue loading the rest of the persons for row in reader: # We now check that we have consistency in our CSV if not len(row) == rowLength: self._errors.append( _('import_error_format', default= u'Wrong file format. Export an existing address book as CSV to get a reference file.' )) return 0 result = {} for j in range(rowLength): result[headers[j]] = row[j] # And now, i have a new user, i add it to the results results.append(result) counter += 1 path = '/'.join(self.context.getPhysicalPath()) LOG(PROJECTNAME, INFO, '%s organizations to be added to %s.' % (counter, path)) counter = 0 # I now have all persons in my results, so i should start adding them to site for organization in results: if self.context.get(organization['id']): self._errors.append( _('import_error_organizationexists', default= u'There\'s already an organization with this id here. ' 'You will have to load the organization with id ${organization_id} ' 'manually.', mapping={'organization_id': organization['id']})) LOG(PROJECTNAME, WARNING, 'There\'s already an organization with this id here.') LOG( PROJECTNAME, WARNING, 'You will have to load the organization with id ' '%s manually.' % organization['id']) else: try: self.context.invokeFactory('Organization', organization['id']) new_organization = self.context.get(organization['id']) for attr in organization.keys(): if attr != 'id': setattr(new_organization, attr, organization[attr]) counter += 1 portal_catalog.reindexObject(new_organization) LOG(PROJECTNAME, INFO, 'Successfully added %s.' % organization['id']) except: self._errors.append( _('import_error_organization', default=u'There was an error while adding. ' 'You will have to load the organization with id ${organization_id} ' 'manually.', mapping={'organization_id': organization['id']})) LOG(PROJECTNAME, WARNING, 'There was an error while adding.') LOG( PROJECTNAME, WARNING, 'You will have to load the organization with id ' '%s manually.' % organization['id']) LOG(PROJECTNAME, INFO, 'Successfully added %s organizations to %s.' % (counter, path)) return counter
def __call__(self): """ This method gets called everytime the template needs to be rendered """ # XXX: This should be reviewed and changed to use portal_form_controller form = self.request.form if self.context.meta_type == 'Group': # Means i'm exporting persons from inside a group. I should form # the path from my parent path = '/'.join(self.context.aq_inner.aq_parent.getPhysicalPath()) else: path = '/'.join(self.context.getPhysicalPath()) # Here we know if the user requested to export the users # the organizations or to send mails to them. mailto = form.get('form.button.mailto', False) export_persons = form.get('form.button.export_persons', False) export_organizations = form.get('form.button.export_org', False) mailto_group = form.get('form.button.mailto_group', False) advanced_persons = form.get('form.button.advanced_persons', False) advanced_organizations = form.get('form.button.advanced_organizations', False) # This is necessary in case this method gets called and no button was # pressed. In that case it will just render the template if mailto or export_persons or export_organizations: # In any case we ask for the user selection # Now the selections come in a list formed of the id's and the # emails, using a space as a separator, so we now separate them if not form.has_key('user_selection') and not form.has_key('no_mail'): aux = _(u'You need to select at least one person or ' 'organization') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/search_addressbook?error_message=%s' % (status,) return self.request.response.redirect(url) elif not form.has_key('user_selection') and mailto: aux = _(u'You need to select at least one person or ' 'organization that has an email') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/search_addressbook?error_message=%s' % (status,) return self.request.response.redirect(url) if form.has_key('user_selection'): ids = [i.split(' ')[0] for i in form['user_selection']] if form.has_key('no_mail'): if not isinstance(form['no_mail'], list): ids_nomail = [form['no_mail'].strip()] else: ids_nomail = [i.strip() for i in form['no_mail']] ids = ids + ids_nomail mails = [i.split(' ')[1] for i in form['user_selection']] else: if not isinstance(form['no_mail'], list): ids = [form['no_mail'].strip()] else: ids = [i.strip() for i in form['no_mail']] mails = [] self.request.string_emails = ', '.join(mails) if export_persons: # If the export action was requested we will be using the # users selections to first filter and then we provide # a download dialog. The export will be done in csv format return exportPersons(self.context, self.request, path, ids, 'csv') if export_organizations: # If the export action was requested we will be using the # users selections to first filter and then we provide # a download dialog. The export will be done in csv format return exportOrganizations(self.context, self.request, path, ids, 'csv') if mailto_group: if not form.has_key('user_selection'): aux = _(u'You need to select at least one group') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/search_addressbook?error_message=%s' % (status,) return self.request.response.redirect(url) resulting_mails = [] for i in form['user_selection']: addresses = i.split(',') for i in addresses: if i not in resulting_mails and i != '': resulting_mails.append(i) self.request.string_emails = ', '.join(resulting_mails) if self.request.string_emails == '': aux = _(u'There are no persons to send an email to') status = zope.i18n.translate(aux, context=self.request) url = self.context.absolute_url() + \ '/search_addressbook?error_message=%s' % (status,) return self.request.response.redirect(url) if advanced_persons: url = self.context.absolute_url() + '/personssearch_view' return self.request.response.redirect(url) if advanced_organizations: url = self.context.absolute_url() + '/organizationssearch_view' return self.request.response.redirect(url) return self.pt()
def importCSVPersons(context, path, file): """ This function is used to import persons to a given path using a CSV file """ aux = _('Starting the persons import process') msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) portal_catalog = getToolByName(context, 'portal_catalog') # Now that we have all our configuration, we can start # First we set our results as an empty list, we will be loading # each user here results = [] # we first make sure the content is in utf8 reader = UnicodeReader(file) # Now we first load the headers headers = reader.next() rowLength = len(headers) counter = 0 # Now i have to continue loading the rest of the persons for row in reader: # We now check that we have consistency in our CSV assert len(row) == rowLength result = {} for j in range(rowLength): result[headers[j]] = row[j] # And now, i have a new user, i add it to the results results.append(result) counter += 1 aux = _('${persons_number} persons to be added to ${location}.',\ mapping={'persons_number':counter, 'location':path}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) counter = 0 # I now have all persons in my results, so i should start adding them to # the site for person in results: organization =[i.getObject() for i in portal_catalog( portal_type = 'Organization', path = path, Title = person['organization'] )] if organization and len(organization)>1: aux = _('There are ${org_size} organizations with the same title, ' 'i don\'t know with which one relate this person.',\ mapping={'org_size':len(organization)}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the person with id ${person_id} ' 'manually.',\ mapping={'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) elif ((organization and len(organization)==1) or person['organization'] == ''): if context.get(person['id']): aux = _('There\'s already a person with this id here.') msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the person with id ' '${person_id} manually.',\ mapping={'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) else: try: context.invokeFactory('Person', person['id']) new_person = context.get(person['id']) for attr in person.keys(): if attr != 'id' and attr != 'organization': setattr(new_person, attr, person[attr]) if (attr == 'organization' and person['organization'] != ''): new_person.setOrganization(organization[0]) counter += 1 portal_catalog.reindexObject(new_person) aux = _('Successfuly added ${person_id}.',\ mapping={'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) except: aux = _('There was an error while adding.') msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the person with id ' '${person_id} manually.',\ mapping={'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) else: aux = _('There\'s no organization with title ${organization_name}, ' 'make sure it exists before adding persons. ' '${person_id} not added',\ mapping={'organization_name':person['organization'], 'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('Successfuly added ${persons_number} persons to ${location}.',\ mapping={'persons_number':counter, 'location':path}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) return counter
def importCSVPersons(context, path, file): """ This function is used to import persons to a given path using a CSV file """ aux = _('Starting the persons import process') msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) portal_catalog = getToolByName(context, 'portal_catalog') # Now that we have all our configuration, we can start # First we set our results as an empty list, we will be loading # each user here results = [] # we first make sure the content is in utf8 reader = UnicodeReader(file) # Now we first load the headers headers = reader.next() rowLength = len(headers) counter = 0 # Now i have to continue loading the rest of the persons for row in reader: # We now check that we have consistency in our CSV assert len(row) == rowLength result = {} for j in range(rowLength): result[headers[j]] = row[j] # And now, i have a new user, i add it to the results results.append(result) counter += 1 aux = _('${persons_number} persons to be added to ${location}.',\ mapping={'persons_number':counter, 'location':path}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) counter = 0 # i now have all persons in my results, so i should start adding them to # the site for person in results: organization = [ i.getObject() for i in portal_catalog(portal_type='Organization', path=path, Title=person['organization']) ] if (organization and len(organization) > 1 and person['organization']): aux = _('There are ${org_size} organizations with the same title, ' 'i don\'t know with which one relate this person.',\ mapping={'org_size':len(organization)}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the person with id ${person_id} ' 'manually.',\ mapping={'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) else: if context.get(person['id']): aux = _('There\'s already a person with this id here.') msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the person with id ' '${person_id} manually.',\ mapping={'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) else: try: context.invokeFactory('Person', person['id']) new_person = context.get(person['id']) for attr in person.keys(): if attr != 'id' and attr != 'organization': setattr(new_person, attr, person[attr]) if (attr == 'organization' and person['organization'] and organization and len(organization) == 1): new_person.setOrganization(organization[0]) counter += 1 if person['organization'] and not organization: aux = _('Organization with title ${org_title} ' 'doesn\'t exist. Leaving that field ' 'in blank.',\ mapping={'org_title':person['organization']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) portal_catalog.reindexObject(new_person) aux = _('Successfuly added ${person_id}.',\ mapping={'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) except: aux = _('There was an error while adding.') msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('You will have to load the person with id ' '${person_id} manually.',\ mapping={'person_id':person['id']}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, WARNING, msg) aux = _('Successfuly added ${persons_number} persons to ${location}.',\ mapping={'persons_number':counter, 'location':path}) msg = zope.i18n.translate(aux, context=context.request) LOG(PROJECTNAME, INFO, msg) # Here I should return also the unexistent organizations return counter
from Products.ATContentTypes.content import base from Products.ATContentTypes.content import schemata from collective.contacts import contactsMessageFactory as _ from collective.contacts.interfaces import IOrganization from collective.contacts.config import PROJECTNAME from collective.contacts.content import DeprecatedATFieldProperty OrganizationSchema = schemata.ATContentTypeSchema.copy() + atapi.Schema(( # -*- Your Archetypes field definitions here ... -*- atapi.StringField( 'address', storage=atapi.AnnotationStorage(), widget=atapi.StringWidget( label=_(u"Address"), description=_(u"Organization's address"), ), required=False, searchable=1, ), atapi.StringField( 'country', storage=atapi.AnnotationStorage(), widget=atapi.SelectionWidget( label=_(u"Country"), description=_(u"Organization's country"), ), vocabulary_factory='contacts.countries', required=False, searchable=1,
def importFile(self, file): self._errors = [] LOG(PROJECTNAME, INFO, 'Starting the organizations import process') # First we set our results as an empty list, we will be loading # each user here results = [] portal_catalog = getToolByName(self.context, 'portal_catalog') # we first make sure the content is in utf8 reader = UnicodeReader(file) # Now we first load the headers headers = reader.next() rowLength = len(headers) if rowLength != len(self.fields): self._errors.append(_('import_error_format', default=u'Wrong file format. Export an existing address book as CSV to get a reference file.')) return 0 for field in self.fields: if not field in headers: self._errors.append(_('import_error_format', default=u'Wrong file format. Export an existing address book as CSV to get a reference file.')) return 0 counter = 0 # Now i have to continue loading the rest of the persons for row in reader: # We now check that we have consistency in our CSV if not len(row) == rowLength: self._errors.append(_('import_error_format', default=u'Wrong file format. Export an existing address book as CSV to get a reference file.')) return 0 result = {} for j in range(rowLength): result[headers[j]] = row[j] # And now, i have a new user, i add it to the results results.append(result) counter += 1 path = '/'.join(self.context.getPhysicalPath()) LOG(PROJECTNAME, INFO, '%s organizations to be added to %s.' % (counter, path)) counter = 0 # I now have all persons in my results, so i should start adding them to site for organization in results: if self.context.get(organization['id']): self._errors.append(_('import_error_organizationexists', default=u'There\'s already an organization with this id here. ' 'You will have to load the organization with id ${organization_id} ' 'manually.', mapping={'organization_id': organization['id']})) LOG(PROJECTNAME, WARNING, 'There\'s already an organization with this id here.') LOG(PROJECTNAME, WARNING, 'You will have to load the organization with id ' '%s manually.' % organization['id']) else: try: self.context.invokeFactory('Organization', organization['id']) new_organization = self.context.get(organization['id']) for attr in organization.keys(): if attr != 'id': setattr(new_organization, attr, organization[attr]) counter += 1 portal_catalog.reindexObject(new_organization) LOG(PROJECTNAME, INFO, 'Successfully added %s.' % organization['id']) except: self._errors.append(_('import_error_organization', default=u'There was an error while adding. ' 'You will have to load the organization with id ${organization_id} ' 'manually.', mapping={'organization_id': organization['id']})) LOG(PROJECTNAME, WARNING, 'There was an error while adding.') LOG(PROJECTNAME, WARNING, 'You will have to load the organization with id ' '%s manually.' % organization['id']) LOG(PROJECTNAME, INFO, 'Successfully added %s organizations to %s.' % (counter, path)) return counter