source: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/workflow.py @ 12213

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

We need different workflows for customer documents and central 'public' documents.

  • Property svn:keywords set to Id
File size: 11.1 KB
Line 
1## $Id: workflow.py 12213 2014-12-13 10:51:17Z 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"""Workflow for customers.
19"""
20import grok
21from datetime import datetime
22from zope.component import getUtility
23from hurry.workflow.workflow import Transition, WorkflowState, NullCondition
24from hurry.workflow.interfaces import (
25    IWorkflowState, IWorkflowTransitionEvent, InvalidTransitionError)
26from waeup.ikoba.interfaces import (
27    IObjectHistory, IIkobaWorkflowInfo, IIkobaUtils,
28    STARTED, CREATED, REQUESTED, APPROVED,
29    SUBMITTED, VERIFIED, REJECTED, EXPIRED)
30from waeup.ikoba.interfaces import MessageFactory as _
31from waeup.ikoba.workflow import (
32    IkobaWorkflow, IkobaWorkflowInfo)
33from waeup.ikoba.customers.interfaces import (
34    ICustomer, ICustomersUtils,
35    IContract, ICustomerDocument)
36from waeup.ikoba.utils.helpers import get_current_principal
37
38# Customer workflow
39
40IMPORTABLE_REGISTRATION_STATES = (STARTED, REQUESTED, APPROVED)
41
42REGISTRATION_TRANSITIONS = (
43    Transition(
44        transition_id = 'create',
45        title = _('Create customer'),
46        source = None,
47        condition = NullCondition,
48        msg = _('Customer record created'),
49        destination = CREATED),
50
51    Transition(
52        transition_id = 'start',
53        title = _('Start registration'),
54        source = CREATED,
55        condition = NullCondition,
56        msg = _('Customer registration started'),
57        destination = STARTED),
58
59    Transition(
60        transition_id = 'request',
61        title = _('Request registration'),
62        msg = _('Customer registration requested'),
63        source = STARTED,
64        destination = REQUESTED),
65
66    Transition(
67        transition_id = 'approve',
68        title = _('Approve customer'),
69        msg = _('Customer registration approved'),
70        source = REQUESTED,
71        destination = APPROVED),
72
73    Transition(
74        transition_id = 'reject',
75        title = _('Reject customer'),
76        msg = _('Customer registration rejected'),
77        source = REQUESTED,
78        destination = STARTED),
79
80    Transition(
81        transition_id = 'reset1',
82        title = _('Reset customer'),
83        msg = _('Reset to initial customer state'),
84        source = APPROVED,
85        destination = STARTED),
86
87    Transition(
88        transition_id = 'reset2',
89        title = _('Reset to requested'),
90        msg = _("Reset to 'requested'"),
91        source = APPROVED,
92        destination = REQUESTED),
93
94    Transition(
95        transition_id = 'reset3',
96        title = _('Reset customer'),
97        msg = _("Reset to initial state"),
98        source = REQUESTED,
99        destination = STARTED),
100
101    )
102
103
104IMPORTABLE_REGISTRATION_TRANSITIONS = [i.transition_id for i in REGISTRATION_TRANSITIONS]
105
106registration_workflow = IkobaWorkflow(REGISTRATION_TRANSITIONS)
107
108
109class RegistrationWorkflowState(WorkflowState, grok.Adapter):
110    """An adapter to adapt Customer objects to workflow states.
111    """
112    grok.context(ICustomer)
113    grok.provides(IWorkflowState)
114
115    state_key = 'wf.registration.state'
116    state_id = 'wf.registration.id'
117
118
119class RegistrationWorkflowInfo(IkobaWorkflowInfo, grok.Adapter):
120    """Adapter to adapt Customer objects to workflow info objects.
121    """
122    grok.context(ICustomer)
123    grok.provides(IIkobaWorkflowInfo)
124
125    def __init__(self, context):
126        self.context = context
127        self.wf = registration_workflow
128
129
130@grok.subscribe(ICustomer, IWorkflowTransitionEvent)
131def handle_customer_transition_event(obj, event):
132    """Append message to customer history and log file when transition happened.
133    """
134
135    msg = event.transition.user_data['msg']
136    history = IObjectHistory(obj)
137    history.addMessage(msg)
138    try:
139        customers_container = grok.getSite()['customers']
140        customers_container.logger.info('%s - %s' % (obj.customer_id,msg))
141    except (TypeError, AttributeError):
142        pass
143    return
144
145
146# Contract workflow
147
148
149CONTRACT_TRANSITIONS = (
150    Transition(
151        transition_id = 'create',
152        title = _('Create contract record'),
153        source = None,
154        condition = NullCondition,
155        msg = _('Contract record created'),
156        destination = CREATED),
157
158    Transition(
159        transition_id = 'submit',
160        title = _('Submit for approval'),
161        msg = _('Submitted for approval'),
162        source = CREATED,
163        destination = SUBMITTED),
164
165    Transition(
166        transition_id = 'approve',
167        title = _('Approve'),
168        msg = _('Approved'),
169        source = SUBMITTED,
170        destination = APPROVED),
171
172    Transition(
173        transition_id = 'reject',
174        title = _('Reject'),
175        msg = _('REJECTED'),
176        source = SUBMITTED,
177        destination = REJECTED),
178
179    Transition(
180        transition_id = 'reset1',
181        title = _('Reset to initial state'),
182        msg = _('Reset to initial state'),
183        source = REJECTED,
184        destination = CREATED),
185
186    Transition(
187        transition_id = 'reset2',
188        title = _('Reset to initial state'),
189        msg = _('Reset to initial state'),
190        source = APPROVED,
191        destination = CREATED),
192
193    Transition(
194        transition_id = 'reset3',
195        title = _('Reset to initial state'),
196        msg = _('Reset to initial state'),
197        source = SUBMITTED,
198        destination = CREATED),
199
200    Transition(
201        transition_id = 'expire',
202        title = _('Set to expired'),
203        msg = _('Set to expired'),
204        source = APPROVED,
205        destination = EXPIRED),
206
207    Transition(
208        transition_id = 'reset4',
209        title = _('Reset to initial state'),
210        msg = _('Reset to initial state'),
211        source = EXPIRED,
212        destination = CREATED),
213    )
214
215contract_workflow = IkobaWorkflow(CONTRACT_TRANSITIONS)
216
217
218class ContractWorkflowState(WorkflowState, grok.Adapter):
219    """An adapter to adapt Contract objects to workflow states.
220    """
221    grok.context(IContract)
222    grok.provides(IWorkflowState)
223
224    state_key = 'wf.contract.state'
225    state_id = 'wf.contract.id'
226
227
228class ContractWorkflowInfo(IkobaWorkflowInfo, grok.Adapter):
229    """Adapter to adapt Contract objects to workflow info objects.
230    """
231    grok.context(IContract)
232    grok.provides(IIkobaWorkflowInfo)
233
234    def __init__(self, context):
235        self.context = context
236        self.wf = contract_workflow
237
238@grok.subscribe(IContract, IWorkflowTransitionEvent)
239def handle_contract_transition_event(obj, event):
240    """Append message to contract history and log file.
241
242    Undo the approval of contract and raise an exception if contract
243    does not meet the requirements for approval.
244    """
245    if event.transition.destination == APPROVED:
246        approvable, error = obj.is_approvable
247        if not approvable:
248            # Undo transition and raise an exception.
249            IWorkflowState(obj).setState(event.transition.source)
250            raise InvalidTransitionError(error)
251    msg = event.transition.user_data['msg']
252    history = IObjectHistory(obj)
253    history.addMessage(msg)
254    try:
255        customers_container = grok.getSite()['customers']
256        customers_container.logger.info('%s - %s' % (obj.customer_id,msg))
257    except (TypeError, AttributeError):
258        pass
259    return
260
261# Customer document workflow
262
263VERIFICATION_TRANSITIONS = (
264    Transition(
265        transition_id = 'create',
266        title = _('Create document'),
267        source = None,
268        condition = NullCondition,
269        msg = _('Document created'),
270        destination = CREATED),
271
272    Transition(
273        transition_id = 'submit',
274        title = _('Submit for verification'),
275        msg = _('Submitted for verification'),
276        source = CREATED,
277        destination = SUBMITTED),
278
279    Transition(
280        transition_id = 'verify',
281        title = _('Verify'),
282        msg = _('Verified'),
283        source = SUBMITTED,
284        destination = VERIFIED),
285
286    Transition(
287        transition_id = 'reject',
288        title = _('Reject'),
289        msg = _('REJECTED'),
290        source = SUBMITTED,
291        destination = REJECTED),
292
293    Transition(
294        transition_id = 'reset1',
295        title = _('Reset to initial state'),
296        msg = _('Reset to initial state'),
297        source = REJECTED,
298        destination = CREATED),
299
300    Transition(
301        transition_id = 'reset2',
302        title = _('Reset to initial state'),
303        msg = _('Reset to initial state'),
304        source = VERIFIED,
305        destination = CREATED),
306
307    Transition(
308        transition_id = 'reset3',
309        title = _('Reset to initial state'),
310        msg = _('Reset to initial state'),
311        source = SUBMITTED,
312        destination = CREATED),
313
314    Transition(
315        transition_id = 'expire',
316        title = _('Set to expired'),
317        msg = _('Set to expired'),
318        source = VERIFIED,
319        destination = EXPIRED),
320
321    Transition(
322        transition_id = 'reset4',
323        title = _('Reset to initial state'),
324        msg = _('Reset to initial state'),
325        source = EXPIRED,
326        destination = CREATED),
327    )
328
329verification_workflow = IkobaWorkflow(VERIFICATION_TRANSITIONS)
330
331
332class VerificationWorkflowState(WorkflowState, grok.Adapter):
333    """An adapter to adapt CustomerDocument objects to workflow states.
334    """
335    grok.context(ICustomerDocument)
336    grok.provides(IWorkflowState)
337
338    state_key = 'wf.verification.state'
339    state_id = 'wf.verification.id'
340
341
342class VerificationWorkflowInfo(IkobaWorkflowInfo, grok.Adapter):
343    """Adapter to adapt CustomerDocument objects to workflow info objects.
344    """
345    grok.context(ICustomerDocument)
346    grok.provides(IIkobaWorkflowInfo)
347
348    def __init__(self, context):
349        self.context = context
350        self.wf = verification_workflow
351
352@grok.subscribe(ICustomerDocument, IWorkflowTransitionEvent)
353def handle_customer_document_transition_event(obj, event):
354    """Append message to document history and log file.
355
356    Undo the verification of document and raise an exception if document
357    does not meet the requirements for verification.
358    """
359    if event.transition.destination == VERIFIED:
360        verifiable, error = obj.is_verifiable
361        if not verifiable:
362            # Undo transition and raise an exception.
363            IWorkflowState(obj).setState(event.transition.source)
364            raise InvalidTransitionError(error)
365    if event.transition.transition_id == 'verify':
366        obj.setMD5()
367    msg = event.transition.user_data['msg']
368    history = IObjectHistory(obj)
369    history.addMessage(msg)
370    try:
371        customers_container = grok.getSite()['customers']
372        customers_container.logger.info('%s - %s' % (obj.customer_id,msg))
373    except (TypeError, AttributeError):
374        pass
375    return
Note: See TracBrowser for help on using the repository browser.