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

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

Add interface and page for editing official use data. Adjust exporter.

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