source: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/vocabularies.py @ 12236

Last change on this file since 12236 was 12127, checked in by Henrik Bettermann, 10 years ago

When checking conversion during import, contracts do not belong to
customers. Thus all portal documents must be returned by getValues.

  • Property svn:keywords set to Id
File size: 5.8 KB
Line 
1## $Id: vocabularies.py 12127 2014-12-03 18:09:28Z henrik $
2##
3## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Vocabularies and sources for the customer section.
19"""
20import grok
21from zope.component import getUtility, queryUtility
22from zope.catalog.interfaces import ICatalog
23from zope.interface import implements, directlyProvides
24from zope.schema.interfaces import ISource, IContextSourceBinder
25from zope.schema.interfaces import ValidationError
26from zc.sourcefactory.basic import BasicSourceFactory
27from zc.sourcefactory.contextual import BasicContextualSourceFactory
28from waeup.ikoba.sourcefactory import SmartBasicContextualSourceFactory
29from waeup.ikoba.interfaces import SimpleIkobaVocabulary, SUBMITTED, VERIFIED
30from waeup.ikoba.interfaces import MessageFactory as _
31from waeup.ikoba.utils.helpers import get_sorted_preferred
32from waeup.ikoba.utils.countries import COUNTRIES
33
34#: a tuple of tuples (<COUNTRY-NAME>, <ISO-CODE>) with Nigeria first.
35COUNTRIES = get_sorted_preferred(COUNTRIES, ['NG'])
36nats_vocab = SimpleIkobaVocabulary(*COUNTRIES)
37
38
39class GenderSource(BasicSourceFactory):
40    """A gender source delivers basically a mapping
41       ``{'m': 'Male', 'f': 'Female'}``
42
43       Using a source, we make sure that the tokens (which are
44       stored/expected for instance from CSV files) are something one
45       can expect and not cryptic IntIDs.
46    """
47    def getValues(self):
48        return ['m', 'f']
49
50    def getToken(self, value):
51        return value[0].lower()
52
53    def getTitle(self, value):
54        if value == 'm':
55            return _('male')
56        if value == 'f':
57            return _('female')
58
59
60class RegNumNotInSource(ValidationError):
61    """Registration number exists already
62    """
63    # The docstring of ValidationErrors is used as error description
64    # by zope.formlib.
65    pass
66
67
68class RegNumberSource(object):
69    """A source that accepts any entry for a certain field if not used
70    already.
71
72    Using this kind of source means a way of setting an invariant.
73
74    We accept a value iff:
75    - the value cannot be found in catalog or
76    - the value can be found as part of some item but the bound item
77      is the context object itself.
78    """
79    implements(ISource)
80    cat_name = 'customers_catalog'
81    field_name = 'reg_number'
82    validation_error = RegNumNotInSource
83    comp_field = 'customer_id'
84
85    def __init__(self, context):
86        self.context = context
87        return
88
89    def __contains__(self, value):
90        """We accept all values not already given to other customers.
91        """
92        cat = queryUtility(ICatalog, self.cat_name)
93        if cat is None:
94            return True
95        kw = {self.field_name: (value, value)}
96        results = cat.searchResults(**kw)
97        for entry in results:
98            if not hasattr(self.context, self.comp_field):
99                # we have no context with comp_field (most probably
100                # while adding a new object, where the container is
101                # the context) which means that the value was given
102                # already to another object (as _something_ was found in
103                # the catalog with that value). Fail on first round.
104                raise self.validation_error(value)
105            if getattr(entry, self.comp_field) != getattr(
106                self.context, self.comp_field):
107                # An entry already given to another customer is not in our
108                # range of acceptable values.
109                raise self.validation_error(value)
110                #return False
111        return True
112
113
114def contextual_reg_num_source(context):
115    source = RegNumberSource(context)
116    return source
117
118directlyProvides(contextual_reg_num_source, IContextSourceBinder)
119
120
121class ConCatProductSource(BasicContextualSourceFactory):
122    """A contract category product source delivers all products
123    which belong to a certain contract_category.
124    """
125
126    def getValues(self, context):
127        concat = getattr(context, 'contract_category', None)
128        products = grok.getSite()['products'].values()
129        if not concat:
130            return products
131        resultlist = [
132            value for value in products if value.contract_category == concat]
133        return resultlist
134
135    def getToken(self, context, value):
136        return value.product_id
137
138    def getTitle(self, context, value):
139        return "%s - %s" % (value.product_id, value.title)
140
141
142class CustomerDocumentSource(BasicContextualSourceFactory):
143    """A customer document source delivers all submitted and verified documents
144    of the context customer.
145    """
146
147    def getValues(self, context):
148        # When checking conversion during import, contracts do not belong to
149        # customers. Thus all portal documents must be returned.
150        user_id = getattr(getattr(context, 'customer', None), 'user_id', None)
151        catalog = getUtility(ICatalog, name='documents_catalog')
152        results = catalog.searchResults(user_id=(user_id, user_id))
153        resultlist = [
154            value for value in results if value.state in (SUBMITTED, VERIFIED)]
155        return resultlist
156
157    def getToken(self, context, value):
158        return value.document_id
159
160    def getTitle(self, context, value):
161        return "%s - %s" % (value.document_id, value.title)
Note: See TracBrowser for help on using the repository browser.