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

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

Extend customer registration workflow.

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