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

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

Save 'terms and conditions' when adding a contract.

Prevent changing product_object after adding contract.

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