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

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

Let's take the 'last transition date' from the history. Saving the date is redundant.

  • Property svn:keywords set to Id
File size: 6.0 KB
RevLine 
[12089]1## $Id: contracts.py 12210 2014-12-13 08:58:43Z 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 _
[12144]29from waeup.ikoba.interfaces import IIkobaUtils, IObjectHistory, VERIFIED
[12089]30from waeup.ikoba.customers.interfaces import (
[12097]31    IContractsContainer, ICustomerNavigation,
32    IContract, IContractEdit, ICustomersUtils,
[12103]33    ISampleContract, ISampleContractEdit)
[12097]34from waeup.ikoba.customers.utils import generate_contract_id
[12089]35from waeup.ikoba.utils.helpers import attrs_to_fields
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
[12097]59class ContractBase(grok.Container):
60    """This is a customer contract baseclass.
[12089]61    """
[12097]62    grok.implements(IContract, IContractEdit, ICustomerNavigation)
63    grok.provides(IContract)
[12089]64    grok.baseclass()
65
[12144]66    check_docs_interface = None
67
[12097]68    contract_category = None
[12092]69
[12103]70    form_fields_interface = None
71
72    edit_form_fields_interface = None
73
[12089]74    def __init__(self):
[12097]75        super(ContractBase, self).__init__()
[12089]76        # The site doesn't exist in unit tests
77        try:
[12097]78            self.contract_id = generate_contract_id()
[12089]79        except AttributeError:
[12196]80            self.contract_id = u'c999'
[12094]81        self.last_product_id = None
[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
114    def customer(self):
115        try:
116            return self.__parent__.__parent__
117        except AttributeError:
118            return None
119
120    def writeLogMessage(self, view, message):
121        return self.__parent__.__parent__.writeLogMessage(view, message)
122
123    @property
[12167]124    def is_editable_by_customer(self):
[12089]125        try:
126            # Customer must be approved
127            cond1 = self.customer.state in getUtility(
[12099]128                ICustomersUtils).CONMANAGE_CUSTOMER_STATES
[12097]129            # Contract must be in state created
[12089]130            cond2 = self.state in getUtility(
[12099]131                ICustomersUtils).CONMANAGE_CONTRACT_STATES
[12089]132            if not (cond1 and cond2):
133                return False
134        except AttributeError:
135            pass
136        return True
137
138    @property
[12144]139    def is_approvable(self):
140        for key, field in getFields(self.check_docs_interface).items():
141            if key.endswith('_object'):
142                obj = getattr(self, key, None)
143                state = getattr(obj, 'state', None)
144                if state and state != VERIFIED:
[12168]145                    return False, _("Attached documents must be verified first.")
146        return True, None
[12144]147
148    @property
[12089]149    def translated_class_name(self):
150        try:
[12099]151            CONTYPES_DICT = getUtility(ICustomersUtils).CONTYPES_DICT
152            return CONTYPES_DICT[self.class_name]
[12089]153        except KeyError:
154            return
155
156
[12097]157class SampleContract(ContractBase):
158    """This is a sample contract.
[12089]159    """
160
[12103]161    grok.implements(ISampleContract, ISampleContractEdit, ICustomerNavigation)
162
[12097]163    contract_category = 'sample'
[12092]164
[12103]165    form_fields_interface = ISampleContract
166
167    edit_form_fields_interface = ISampleContractEdit
168
[12144]169    check_docs_interface = ISampleContract
170
[12097]171SampleContract = attrs_to_fields(SampleContract)
[12089]172
173
[12097]174# Contracts must be importable. So we might need a factory.
175class SampleContractFactory(grok.GlobalUtility):
176    """A factory for contracts.
[12089]177    """
178    grok.implements(IFactory)
[12097]179    grok.name(u'waeup.SampleContract')
180    title = u"Create a new contract.",
181    description = u"This factory instantiates new sample contract instances."
[12089]182
183    def __call__(self, *args, **kw):
[12097]184        return SampleContract(*args, **kw)
[12089]185
186    def getInterfaces(self):
[12097]187        return implementedBy(SampleContract)
[12089]188
[12097]189@grok.subscribe(IContract, grok.IObjectAddedEvent)
190def handle_contract_added(contract, event):
191    """If an contract is added the transition create is fired.
[12090]192    The latter produces a logging message.
193    """
[12097]194    if IWorkflowState(contract).getState() is None:
195        IWorkflowInfo(contract).fireTransition('create')
[12090]196    return
Note: See TracBrowser for help on using the repository browser.