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

Last change on this file since 12656 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
RevLine 
[12089]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"""
[12097]19Customer contract components.
[12089]20"""
21import os
22import grok
23from zope.component import queryUtility, getUtility
24from zope.component.interfaces import IFactory
25from zope.interface import implementedBy
[12144]26from zope.schema import getFields
[12089]27from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
28from waeup.ikoba.interfaces import MessageFactory as _
[12258]29from waeup.ikoba.interfaces import (
[12573]30    IIkobaUtils, IObjectHistory,
31    VERIFIED, APPROVED, PROVISIONALLY,
32    IIDSource)
[12089]33from waeup.ikoba.customers.interfaces import (
[12097]34    IContractsContainer, ICustomerNavigation,
[12500]35    IContract, IContractSelectProduct, ICustomersUtils,
36    ISampleContract, ISampleContractProcess, ISampleContractEdit,
37    ISampleContractOfficialUse)
[12097]38from waeup.ikoba.customers.utils import generate_contract_id
[12089]39from waeup.ikoba.utils.helpers import attrs_to_fields
40
[12097]41class ContractsContainer(grok.Container):
42    """This is a container for customer contracts.
[12089]43    """
[12097]44    grok.implements(IContractsContainer, ICustomerNavigation)
45    grok.provides(IContractsContainer)
[12089]46
[12097]47    def addContract(self, contract):
48        if not IContract.providedBy(contract):
[12089]49            raise TypeError(
[12097]50                'ContractsContainers contain only IContract instances')
51        self[contract.contract_id] = contract
[12089]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
[12097]61ContractsContainer = attrs_to_fields(ContractsContainer)
[12089]62
[12097]63class ContractBase(grok.Container):
64    """This is a customer contract baseclass.
[12089]65    """
[12486]66    grok.implements(IContractSelectProduct)  # Necesary for the selectproduct page
[12333]67
[12089]68    grok.baseclass()
69
70    def __init__(self):
[12097]71        super(ContractBase, self).__init__()
[12089]72        # The site doesn't exist in unit tests
[12258]73        source = getUtility(IIDSource)
74        self.contract_id = unicode(source.get_hex_uuid())
[12094]75        self.last_product_id = None
[12363]76        self.tc_dict = {}
[12580]77        self.title = None
[12633]78        self.valid_to = None
79        self.valid_from = None
[12089]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(
[12097]95                ICustomersUtils).TRANSLATED_CONTRACT_STATES
[12089]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:
[12210]107            return self.history.messages[-1].split(' - ')[0]
108        except IndexError:
[12089]109            return
110
111    @property
112    def customer(self):
113        try:
114            return self.__parent__.__parent__
115        except AttributeError:
116            return None
117
[12289]118    @property
119    def user_id(self):
120        if self.customer is not None:
121            return self.customer.customer_id
122        return
123
[12089]124    def writeLogMessage(self, view, message):
125        return self.__parent__.__parent__.writeLogMessage(view, message)
126
127    @property
[12337]128    def is_editable(self):
[12089]129        try:
[12573]130            # Customer must have requested
[12089]131            cond1 = self.customer.state in getUtility(
[12099]132                ICustomersUtils).CONMANAGE_CUSTOMER_STATES
[12097]133            # Contract must be in state created
[12089]134            cond2 = self.state in getUtility(
[12099]135                ICustomersUtils).CONMANAGE_CONTRACT_STATES
[12089]136            if not (cond1 and cond2):
137                return False
138        except AttributeError:
139            pass
140        return True
141
142    @property
[12144]143    def is_approvable(self):
[12573]144        if self.customer and not self.customer.state in (
145            APPROVED, PROVISIONALLY):
[12352]146            return False, _("Customer has not yet been approved.")
[12144]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:
[12168]152                    return False, _("Attached documents must be verified first.")
153        return True, None
[12144]154
155    @property
[12089]156    def translated_class_name(self):
157        try:
[12099]158            CONTYPES_DICT = getUtility(ICustomersUtils).CONTYPES_DICT
159            return CONTYPES_DICT[self.class_name]
[12089]160        except KeyError:
161            return
162
163
[12097]164class SampleContract(ContractBase):
165    """This is a sample contract.
[12089]166    """
167
[12333]168    grok.implements(
169        ISampleContractProcess, # must come before ISampleContract
170        ISampleContract,
171        ISampleContractEdit,
172        ICustomerNavigation)
[12103]173
[12097]174    contract_category = 'sample'
[12092]175
[12103]176    form_fields_interface = ISampleContract
177
178    edit_form_fields_interface = ISampleContractEdit
179
[12500]180    ou_form_fields_interface = ISampleContractOfficialUse
181
[12144]182    check_docs_interface = ISampleContract
183
[12097]184SampleContract = attrs_to_fields(SampleContract)
[12089]185
186
[12097]187# Contracts must be importable. So we might need a factory.
188class SampleContractFactory(grok.GlobalUtility):
189    """A factory for contracts.
[12089]190    """
191    grok.implements(IFactory)
[12097]192    grok.name(u'waeup.SampleContract')
193    title = u"Create a new contract.",
194    description = u"This factory instantiates new sample contract instances."
[12089]195
196    def __call__(self, *args, **kw):
[12097]197        return SampleContract(*args, **kw)
[12089]198
199    def getInterfaces(self):
[12097]200        return implementedBy(SampleContract)
[12089]201
[12097]202@grok.subscribe(IContract, grok.IObjectAddedEvent)
203def handle_contract_added(contract, event):
204    """If an contract is added the transition create is fired.
[12090]205    The latter produces a logging message.
206    """
[12097]207    if IWorkflowState(contract).getState() is None:
208        IWorkflowInfo(contract).fireTransition('create')
[12090]209    return
Note: See TracBrowser for help on using the repository browser.