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()
Beispiel #2
0
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."),
    )
Beispiel #4
0
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')
Beispiel #5
0
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]
Beispiel #7
0
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')
Beispiel #8
0
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
    )
Beispiel #9
0
    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()
Beispiel #10
0
 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()
Beispiel #13
0
    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()
Beispiel #14
0
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()
Beispiel #15
0
    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()
Beispiel #16
0
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())})
Beispiel #17
0
 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': ''})
Beispiel #19
0
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
Beispiel #20
0
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)
Beispiel #24
0
    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()
Beispiel #25
0
    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()
Beispiel #26
0
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})
Beispiel #30
0
 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())})
Beispiel #33
0
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
Beispiel #34
0
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.
Beispiel #35
0
 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
Beispiel #37
0

@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
Beispiel #39
0
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()
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 = {
    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()
Beispiel #45
0
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
Beispiel #46
0
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,
Beispiel #49
0
 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
Beispiel #50
0
 def successMsg(self, imported):
     return _(u'Successfully imported ${number} persons', mapping={'number': imported})
Beispiel #51
0
 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