source: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/contracts.py @ 12585

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

Title must be stored with the contract. Otherwise no title will be displayed if product is removed.

  • Property svn:keywords set to Id
File size: 6.4 KB
Line 
1## $Id: contracts.py 12580 2015-02-10 13:22:23Z 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        return
79
80    @property
81    def history(self):
82        history = IObjectHistory(self)
83        return history
84
85    @property
86    def state(self):
87        return IWorkflowState(self).getState()
88
89    @property
90    def translated_state(self):
91        try:
92            TRANSLATED_STATES = getUtility(
93                ICustomersUtils).TRANSLATED_CONTRACT_STATES
94            return TRANSLATED_STATES[self.state]
95        except KeyError:
96            return
97
98    @property
99    def class_name(self):
100        return self.__class__.__name__
101
102    @property
103    def formatted_transition_date(self):
104        try:
105            return self.history.messages[-1].split(' - ')[0]
106        except IndexError:
107            return
108
109    @property
110    def customer(self):
111        try:
112            return self.__parent__.__parent__
113        except AttributeError:
114            return None
115
116    @property
117    def user_id(self):
118        if self.customer is not None:
119            return self.customer.customer_id
120        return
121
122    def writeLogMessage(self, view, message):
123        return self.__parent__.__parent__.writeLogMessage(view, message)
124
125    @property
126    def is_editable(self):
127        try:
128            # Customer must have requested
129            cond1 = self.customer.state in getUtility(
130                ICustomersUtils).CONMANAGE_CUSTOMER_STATES
131            # Contract must be in state created
132            cond2 = self.state in getUtility(
133                ICustomersUtils).CONMANAGE_CONTRACT_STATES
134            if not (cond1 and cond2):
135                return False
136        except AttributeError:
137            pass
138        return True
139
140    @property
141    def is_approvable(self):
142        if self.customer and not self.customer.state in (
143            APPROVED, PROVISIONALLY):
144            return False, _("Customer has not yet been approved.")
145        for key, field in getFields(self.check_docs_interface).items():
146            if key.endswith('_object'):
147                obj = getattr(self, key, None)
148                state = getattr(obj, 'state', None)
149                if state and state != VERIFIED:
150                    return False, _("Attached documents must be verified first.")
151        return True, None
152
153    @property
154    def translated_class_name(self):
155        try:
156            CONTYPES_DICT = getUtility(ICustomersUtils).CONTYPES_DICT
157            return CONTYPES_DICT[self.class_name]
158        except KeyError:
159            return
160
161
162class SampleContract(ContractBase):
163    """This is a sample contract.
164    """
165
166    grok.implements(
167        ISampleContractProcess, # must come before ISampleContract
168        ISampleContract,
169        ISampleContractEdit,
170        ICustomerNavigation)
171
172    contract_category = 'sample'
173
174    form_fields_interface = ISampleContract
175
176    edit_form_fields_interface = ISampleContractEdit
177
178    ou_form_fields_interface = ISampleContractOfficialUse
179
180    check_docs_interface = ISampleContract
181
182SampleContract = attrs_to_fields(SampleContract)
183
184
185# Contracts must be importable. So we might need a factory.
186class SampleContractFactory(grok.GlobalUtility):
187    """A factory for contracts.
188    """
189    grok.implements(IFactory)
190    grok.name(u'waeup.SampleContract')
191    title = u"Create a new contract.",
192    description = u"This factory instantiates new sample contract instances."
193
194    def __call__(self, *args, **kw):
195        return SampleContract(*args, **kw)
196
197    def getInterfaces(self):
198        return implementedBy(SampleContract)
199
200@grok.subscribe(IContract, grok.IObjectAddedEvent)
201def handle_contract_added(contract, event):
202    """If an contract is added the transition create is fired.
203    The latter produces a logging message.
204    """
205    if IWorkflowState(contract).getState() is None:
206        IWorkflowInfo(contract).fireTransition('create')
207    return
Note: See TracBrowser for help on using the repository browser.