source: main/waeup.ikoba/branches/uli-fake-gw-provider/src/waeup/ikoba/customers/contracts.py @ 12643

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

Copy over valid_from and valid_to from products when creating contract objects.

Fix ContractProcessorBase?. Do really allow to import tc_dict, valid_from, title and valid_to.

  • Property svn:keywords set to Id
File size: 6.5 KB
Line 
1## $Id: contracts.py 12633 2015-02-27 17:39:46Z 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"""
19Customer contract components.
20"""
21import os
22import grok
23from zope.component import queryUtility, getUtility
24from zope.component.interfaces import IFactory
25from zope.interface import implementedBy
26from zope.schema import getFields
27from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
28from waeup.ikoba.interfaces import MessageFactory as _
29from waeup.ikoba.interfaces import (
30    IIkobaUtils, IObjectHistory,
31    VERIFIED, APPROVED, PROVISIONALLY,
32    IIDSource)
33from waeup.ikoba.customers.interfaces import (
34    IContractsContainer, ICustomerNavigation,
35    IContract, IContractSelectProduct, ICustomersUtils,
36    ISampleContract, ISampleContractProcess, ISampleContractEdit,
37    ISampleContractOfficialUse)
38from waeup.ikoba.customers.utils import generate_contract_id
39from waeup.ikoba.utils.helpers import attrs_to_fields
40
41class ContractsContainer(grok.Container):
42    """This is a container for customer contracts.
43    """
44    grok.implements(IContractsContainer, ICustomerNavigation)
45    grok.provides(IContractsContainer)
46
47    def addContract(self, contract):
48        if not IContract.providedBy(contract):
49            raise TypeError(
50                'ContractsContainers contain only IContract instances')
51        self[contract.contract_id] = contract
52        return
53
54    @property
55    def customer(self):
56        return self.__parent__
57
58    def writeLogMessage(self, view, message):
59        return self.__parent__.writeLogMessage(view, message)
60
61ContractsContainer = attrs_to_fields(ContractsContainer)
62
63class ContractBase(grok.Container):
64    """This is a customer contract baseclass.
65    """
66    grok.implements(IContractSelectProduct)  # Necesary for the selectproduct page
67
68    grok.baseclass()
69
70    def __init__(self):
71        super(ContractBase, self).__init__()
72        # The site doesn't exist in unit tests
73        source = getUtility(IIDSource)
74        self.contract_id = unicode(source.get_hex_uuid())
75        self.last_product_id = None
76        self.tc_dict = {}
77        self.title = None
78        self.valid_to = None
79        self.valid_from = None
80        return
81
82    @property
83    def history(self):
84        history = IObjectHistory(self)
85        return history
86
87    @property
88    def state(self):
89        return IWorkflowState(self).getState()
90
91    @property
92    def translated_state(self):
93        try:
94            TRANSLATED_STATES = getUtility(
95                ICustomersUtils).TRANSLATED_CONTRACT_STATES
96            return TRANSLATED_STATES[self.state]
97        except KeyError:
98            return
99
100    @property
101    def class_name(self):
102        return self.__class__.__name__
103
104    @property
105    def formatted_transition_date(self):
106        try:
107            return self.history.messages[-1].split(' - ')[0]
108        except IndexError:
109            return
110
111    @property
112    def customer(self):
113        try:
114            return self.__parent__.__parent__
115        except AttributeError:
116            return None
117
118    @property
119    def user_id(self):
120        if self.customer is not None:
121            return self.customer.customer_id
122        return
123
124    def writeLogMessage(self, view, message):
125        return self.__parent__.__parent__.writeLogMessage(view, message)
126
127    @property
128    def is_editable(self):
129        try:
130            # Customer must have requested
131            cond1 = self.customer.state in getUtility(
132                ICustomersUtils).CONMANAGE_CUSTOMER_STATES
133            # Contract must be in state created
134            cond2 = self.state in getUtility(
135                ICustomersUtils).CONMANAGE_CONTRACT_STATES
136            if not (cond1 and cond2):
137                return False
138        except AttributeError:
139            pass
140        return True
141
142    @property
143    def is_approvable(self):
144        if self.customer and not self.customer.state in (
145            APPROVED, PROVISIONALLY):
146            return False, _("Customer has not yet been approved.")
147        for key, field in getFields(self.check_docs_interface).items():
148            if key.endswith('_object'):
149                obj = getattr(self, key, None)
150                state = getattr(obj, 'state', None)
151                if state and state != VERIFIED:
152                    return False, _("Attached documents must be verified first.")
153        return True, None
154
155    @property
156    def translated_class_name(self):
157        try:
158            CONTYPES_DICT = getUtility(ICustomersUtils).CONTYPES_DICT
159            return CONTYPES_DICT[self.class_name]
160        except KeyError:
161            return
162
163
164class SampleContract(ContractBase):
165    """This is a sample contract.
166    """
167
168    grok.implements(
169        ISampleContractProcess, # must come before ISampleContract
170        ISampleContract,
171        ISampleContractEdit,
172        ICustomerNavigation)
173
174    contract_category = 'sample'
175
176    form_fields_interface = ISampleContract
177
178    edit_form_fields_interface = ISampleContractEdit
179
180    ou_form_fields_interface = ISampleContractOfficialUse
181
182    check_docs_interface = ISampleContract
183
184SampleContract = attrs_to_fields(SampleContract)
185
186
187# Contracts must be importable. So we might need a factory.
188class SampleContractFactory(grok.GlobalUtility):
189    """A factory for contracts.
190    """
191    grok.implements(IFactory)
192    grok.name(u'waeup.SampleContract')
193    title = u"Create a new contract.",
194    description = u"This factory instantiates new sample contract instances."
195
196    def __call__(self, *args, **kw):
197        return SampleContract(*args, **kw)
198
199    def getInterfaces(self):
200        return implementedBy(SampleContract)
201
202@grok.subscribe(IContract, grok.IObjectAddedEvent)
203def handle_contract_added(contract, event):
204    """If an contract is added the transition create is fired.
205    The latter produces a logging message.
206    """
207    if IWorkflowState(contract).getState() is None:
208        IWorkflowInfo(contract).fireTransition('create')
209    return
Note: See TracBrowser for help on using the repository browser.