source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/workflow.py @ 6339

Last change on this file since 6339 was 6339, checked in by uli, 13 years ago

Maintain history of objects in a separate component, similar to workflows, instead of storing everything with the object core object.

  • Property svn:keywords set to Id
File size: 5.7 KB
Line 
1"""Workflow for applicants.
2"""
3import grok
4from datetime import datetime
5from hurry.workflow.workflow import (
6    Transition, Workflow, WorkflowVersions, WorkflowInfo, WorkflowState,
7    NullCondition)
8from hurry.workflow.interfaces import (
9    IWorkflow, IWorkflowState, IWorkflowInfo, IWorkflowVersions,
10    InvalidTransitionError, IWorkflowTransitionEvent)
11from waeup.sirp.applicants.interfaces import IApplicantBaseData
12from waeup.sirp.interfaces import IObjectHistory
13
14
15INITIALIZED = 'initialized'
16STARTED = 'started'
17SUBMITTED = 'submitted'
18ADMITTED = 'admitted'
19NOT_ADMITTED = 'not admitted'
20CREATED = 'created'
21
22def create_workflow():
23    init_transition = Transition(
24        transition_id = 'init',
25        title = 'Initialize application',
26        source = None,
27        condition = NullCondition,
28        msg = 'application process initialized',
29        destination = INITIALIZED)
30
31    start_transition = Transition(
32        transition_id = 'start',
33        title = 'Start application',
34        msg = 'application process started',
35        source = INITIALIZED,
36        destination = STARTED)
37
38    submit_transition = Transition(
39        transition_id = 'submit',
40        title = 'Submit application',
41        msg = 'application record submitted',
42        source = STARTED,
43        destination = SUBMITTED)
44
45    admit_transition = Transition(
46        transition_id = 'admit',
47        title = 'Admit applicant',
48        msg = 'applicant admitted',
49        source = SUBMITTED,
50        destination = ADMITTED)
51
52    refuse1_transition = Transition(
53        transition_id = 'refuse1',
54        title = 'Refuse application',
55        msg = 'application refused',
56        source = SUBMITTED,
57        destination = NOT_ADMITTED)
58
59    refuse2_transition = Transition(
60        transition_id = 'refuse2',
61        title = 'Refuse application',
62        msg = 'application refused',
63        source = ADMITTED,
64        destination = NOT_ADMITTED)
65
66    create_transition = Transition(
67        transition_id = 'create',
68        title = 'Create student record',
69        msg = 'student record created',
70        source = ADMITTED,
71        destination = CREATED)
72
73    reset1_transition = Transition(
74        transition_id = 'reset1',
75        title = 'Reset application',
76        msg = 'application record reset',
77        source = SUBMITTED,
78        destination = STARTED)
79
80    reset2_transition = Transition(
81        transition_id = 'reset2',
82        title = 'Reset application',
83        msg = 'application record reset',
84        source = ADMITTED,
85        destination = STARTED)
86
87    reset3_transition = Transition(
88        transition_id = 'reset3',
89        title = 'Reset application',
90        msg = 'application record reset',
91        source = NOT_ADMITTED,
92        destination = STARTED)
93
94    reset4_transition = Transition(
95        transition_id = 'reset4',
96        title = 'Reset application',
97        msg = 'application record reset',
98        source = CREATED,
99        destination = STARTED)
100
101    return [init_transition, start_transition, submit_transition,
102            admit_transition, create_transition, refuse1_transition,
103            refuse2_transition, reset1_transition, reset2_transition,
104            reset3_transition, reset4_transition]
105
106
107class ApplicationWorkflow(Workflow):
108    """A hurry.workflow Workflow with more appropriate error messages.
109    """
110    grok.provides(IWorkflow)
111    def __init__(self):
112        super(Workflow, self).__init__()
113        self.refresh(create_workflow())
114
115    def getTransition(self, source, transition_id):
116        transition = self._id_transitions[transition_id]
117        if transition.source != source:
118            raise InvalidTransitionError(
119                "Transition '%s' requires '%s' as source state (is: '%s')" % (
120                    transition_id, transition.source, source))
121        return transition
122
123
124class ApplicationWorkflowNullVersions(WorkflowVersions):
125    """A workflow versions manager that does not handle versions.
126
127    Sounds odd, but the default implementation of
128    :class:`hurry.workflow.workflow.WorkflowVersions` is a base
129    implementation that raises :exc:`NotImplemented` exceptions for
130    most of the methods defined below.
131
132    If we want to register a versionless workflow, an utility
133    implementing IWorkflowVersions is looked up nevertheless by
134    WorkflowInfo and WorkflowState components so we **have** to
135    provide workflow versions, even if we do not support versioned
136    workflows.
137
138    This implementation returns empty result sets for any requests,
139    but does not raise :exc:`NotImplemented`.
140    """
141    def getVersions(self, state, id):
142        return []
143
144    def getVersionsWithAutomaticTransitions(self):
145        return []
146
147    def hasVersion(self, id, state):
148        return False
149
150    def hasVersionId(self, id):
151        return False
152
153# Register global utilities for workflows and workflow versions...
154grok.global_utility(ApplicationWorkflow, IWorkflow)
155grok.global_utility(ApplicationWorkflowNullVersions, IWorkflowVersions)
156
157class ApplicationState(grok.Adapter, WorkflowState):
158    """An adapter to adapt Applicant objects to workflow states.
159    """
160    grok.context(IApplicantBaseData)
161    grok.provides(IWorkflowState)
162
163class ApplicationInfo(grok.Adapter, WorkflowInfo):
164    """Adapter to adapt Applicant objects to workflow info objects.
165    """
166    grok.context(IApplicantBaseData)
167    grok.provides(IWorkflowInfo)
168
169
170@grok.subscribe(IApplicantBaseData, IWorkflowTransitionEvent)
171def handle_applicant_transition_event(obj, event):
172    """Append message to applicant when transition happened.
173    """
174    timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
175    msg = '%s - %s (new state: %s)' % (
176        timestamp, event.transition.user_data['msg'], event.destination)
177    history = IObjectHistory(obj)
178    history.addMessage(msg)
179    return
Note: See TracBrowser for help on using the repository browser.