source: main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/customers/contracts.py @ 12682

Last change on this file since 12682 was 12681, checked in by uli, 10 years ago

pep8, pyflakes.

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