source: main/waeup.kofa/trunk/src/waeup/kofa/students/workflow.py @ 17388

Last change on this file since 17388 was 15450, checked in by Henrik Bettermann, 5 years ago

Define alumni states (used in base packages).

  • Property svn:keywords set to Id
File size: 10.7 KB
RevLine 
[15402]1## $Id: workflow.py 15450 2019-06-04 07:01:04Z henrik $
2##
3## Copyright (C) 2011 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##
[6637]18"""Workflow for students.
19"""
20import grok
[9161]21from datetime import datetime
[7615]22from zope.component import getUtility
[6637]23from hurry.workflow.workflow import Transition, WorkflowState, NullCondition
24from hurry.workflow.interfaces import IWorkflowState, IWorkflowTransitionEvent
[7811]25from waeup.kofa.interfaces import (
[7819]26    IObjectHistory, IKofaWorkflowInfo, IKofaUtils,
[6990]27    CREATED, ADMITTED, CLEARANCE, REQUESTED, CLEARED, PAID, RETURNING,
[15163]28    REGISTERED, VALIDATED, GRADUATED, TRANSREQ, TRANSVAL, TRANSREL,
29    IExtFileStore)
[7811]30from waeup.kofa.interfaces import MessageFactory as _
[7819]31from waeup.kofa.workflow import KofaWorkflow, KofaWorkflowInfo
[7811]32from waeup.kofa.students.interfaces import IStudent, IStudentsUtils
[9161]33from waeup.kofa.utils.helpers import get_current_principal
[6637]34
[7615]35
[7513]36IMPORTABLE_STATES = (ADMITTED, CLEARANCE, REQUESTED, CLEARED, PAID, RETURNING,
[10452]37    REGISTERED, VALIDATED, GRADUATED)
[7513]38
[9028]39FORBIDDEN_POSTGRAD_STATES = (RETURNING, REGISTERED, VALIDATED)
40
[15450]41ALUMNI_STATES = (GRADUATED, TRANSREQ, TRANSVAL, TRANSREL)
42
[6637]43REGISTRATION_TRANSITIONS = (
44    Transition(
45        transition_id = 'create',
[7677]46        title = _('Create student'),
[6637]47        source = None,
48        condition = NullCondition,
[9022]49        msg = _('Record created'),
[6637]50        destination = CREATED),
51
52    Transition(
53        transition_id = 'admit',
[7670]54        title = _('Admit student'),
[9022]55        msg = _('Admitted'),
[6637]56        source = CREATED,
57        destination = ADMITTED),
58
59    Transition(
60        transition_id = 'reset1',
[7677]61        title = _('Reset student'),
[7996]62        msg = _('Reset to initial state'),
[6637]63        source = ADMITTED,
64        destination = CREATED),
[6720]65
66    Transition(
67        transition_id = 'start_clearance',
[7677]68        title = _('Start clearance'),
69        msg = _('Clearance started'),
[6720]70        source = ADMITTED,
71        destination = CLEARANCE),
72
73    Transition(
74        transition_id = 'reset2',
[7677]75        title = _('Reset to admitted'),
[7996]76        msg = _("Reset to 'admitted'"),
[6720]77        source = CLEARANCE,
78        destination = ADMITTED),
79
80    Transition(
81        transition_id = 'request_clearance',
[7677]82        title = _('Request clearance'),
83        msg = _('Clearance requested'),
[6720]84        source = CLEARANCE,
85        destination = REQUESTED),
86
87    Transition(
88        transition_id = 'reset3',
[9022]89        title = _('Reset to clearance started'),
90        msg = _("Reset to 'clearance started'"),
[6720]91        source = REQUESTED,
92        destination = CLEARANCE),
93
94    Transition(
95        transition_id = 'clear',
[7677]96        title = _('Clear student'),
97        msg = _('Cleared'),
[6720]98        source = REQUESTED,
99        destination = CLEARED),
100
101    Transition(
102        transition_id = 'reset4',
[9022]103        title = _('Reset to clearance started'),
104        msg = _("Reset to 'clearance started'"),
[6720]105        source = CLEARED,
106        destination = CLEARANCE),
[6742]107
108    Transition(
109        transition_id = 'pay_first_school_fee',
[7677]110        title = _('Pay school fee'),
[9022]111        msg = _('First school fee payment made'),
[6742]112        source = CLEARED,
113        destination = PAID),
114
115    Transition(
[8434]116        transition_id = 'approve_first_school_fee',
117        title = _('Approve payment'),
[9022]118        msg = _('First school fee payment approved'),
[8434]119        source = CLEARED,
120        destination = PAID),
121
122    Transition(
[6742]123        transition_id = 'reset5',
[7677]124        title = _('Reset to cleared'),
[7996]125        msg = _("Reset to 'cleared'"),
[6742]126        source = PAID,
127        destination = CLEARED),
128
129    Transition(
130        transition_id = 'pay_school_fee',
[7677]131        title = _('Pay school fee'),
[9022]132        msg = _('School fee payment made'),
[6742]133        source = RETURNING,
134        destination = PAID),
135
136    Transition(
[8471]137        transition_id = 'pay_pg_fee',
[9022]138        title = _('Pay PG school fee'),
139        msg = _('PG school fee payment made'),
[8471]140        source = PAID,
141        destination = PAID),
142
143    Transition(
[8434]144        transition_id = 'approve_school_fee',
[9022]145        title = _('Approve school fee payment'),
[8434]146        msg = _('School fee payment approved'),
147        source = RETURNING,
148        destination = PAID),
149
150    Transition(
[8471]151        transition_id = 'approve_pg_fee',
[9022]152        title = _('Approve PG school fee payment'),
153        msg = _('PG school fee payment approved'),
[8471]154        source = PAID,
155        destination = PAID),
156
157    Transition(
[6742]158        transition_id = 'reset6',
[7677]159        title = _('Reset to returning'),
[7996]160        msg = _("Reset to 'returning'"),
[6742]161        source = PAID,
162        destination = RETURNING),
[6801]163
164    Transition(
165        transition_id = 'register_courses',
[7677]166        title = _('Register courses'),
167        msg = _('Courses registered'),
[6801]168        source = PAID,
169        destination = REGISTERED),
170
171    Transition(
172        transition_id = 'reset7',
[13610]173        title = _('Unregister courses'),
174        msg = _("Courses unregistered"),
[6801]175        source = REGISTERED,
176        destination = PAID),
177
178    Transition(
179        transition_id = 'validate_courses',
[7677]180        title = _('Validate courses'),
181        msg = _('Courses validated'),
[6801]182        source = REGISTERED,
183        destination = VALIDATED),
184
185    Transition(
[9284]186        transition_id = 'bypass_validation',
187        title = _('Return and bypass validation'),
[9295]188        msg = _("Course validation bypassed"),
[9284]189        source = REGISTERED,
190        destination = RETURNING),
191
192    Transition(
[6801]193        transition_id = 'reset8',
[9022]194        title = _('Reset to school fee paid'),
195        msg = _("Reset to 'school fee paid'"),
[6801]196        source = VALIDATED,
197        destination = PAID),
198
199    Transition(
200        transition_id = 'return',
[7677]201        title = _('Return'),
[9284]202        msg = _("Returned"),
[6801]203        source = VALIDATED,
204        destination = RETURNING),
205
206    Transition(
207        transition_id = 'reset9',
[9022]208        title = _('Reset to courses validated'),
209        msg = _("Reset to 'courses validated'"),
[6801]210        source = RETURNING,
211        destination = VALIDATED),
[10446]212
213    # There is no transition to graduated.
214
215    Transition(
216        transition_id = 'request_transcript',
217        title = _('Request transript'),
218        msg = _("Transcript requested"),
219        source = GRADUATED,
[15163]220        destination = TRANSREQ),
[10446]221
222    Transition(
[15163]223        transition_id = 'reset10',
224        title = _('Reject transcript request'),
225        msg = _("Transcript request rejected"),
226        source = TRANSREQ,
[10446]227        destination = GRADUATED),
[15163]228
229    Transition(
230        transition_id = 'validate_transcript',
231        title = _('Validate transcript'),
232        msg = _("Transcript validated"),
233        source = TRANSREQ,
234        destination = TRANSVAL),
235
236    Transition(
237        transition_id = 'release_transcript',
238        title = _('Release transcript'),
239        msg = _("Transcript released"),
240        source = TRANSVAL,
241        destination = TRANSREL),
242
243    Transition(
244        transition_id = 'reset11',
245        title = _('Reset to graduated'),
246        msg = _("Transcript process reset"),
247        source = TRANSREL,
248        destination = GRADUATED),
[6637]249    )
250
[10446]251
[8309]252IMPORTABLE_TRANSITIONS = [i.transition_id for i in REGISTRATION_TRANSITIONS]
253
[9028]254FORBIDDEN_POSTGRAD_TRANS = ['reset6', 'register_courses']
[6720]255
[7819]256registration_workflow = KofaWorkflow(REGISTRATION_TRANSITIONS)
[6637]257
258class RegistrationWorkflowState(WorkflowState, grok.Adapter):
259    """An adapter to adapt Student objects to workflow states.
260    """
261    grok.context(IStudent)
262    grok.provides(IWorkflowState)
263
264    state_key = 'wf.registration.state'
265    state_id = 'wf.registration.id'
266
[7819]267class RegistrationWorkflowInfo(KofaWorkflowInfo, grok.Adapter):
[6637]268    """Adapter to adapt Student objects to workflow info objects.
269    """
270    grok.context(IStudent)
[7819]271    grok.provides(IKofaWorkflowInfo)
[6637]272
273    def __init__(self, context):
274        self.context = context
275        self.wf = registration_workflow
276
277@grok.subscribe(IStudent, IWorkflowTransitionEvent)
278def handle_student_transition_event(obj, event):
[6644]279    """Append message to student history and log file when transition happened.
[7133]280
[7681]281    Lock and unlock clearance form.
[9005]282    Trigger actions after school fee payment.
[6637]283    """
[7679]284
285    msg = event.transition.user_data['msg']
[6637]286    history = IObjectHistory(obj)
287    history.addMessage(msg)
[6742]288    # School fee payment of returning students triggers the change of
289    # current session, current level, and current verdict
[8434]290    if event.transition.transition_id in (
291        'pay_school_fee', 'approve_school_fee'):
[7615]292        getUtility(IStudentsUtils).setReturningData(obj)
[8471]293    elif event.transition.transition_id in (
294        'pay_pg_fee', 'approve_pg_fee'):
295        new_session = obj['studycourse'].current_session + 1
296        obj['studycourse'].current_session = new_session
[9161]297    elif event.transition.transition_id == 'validate_courses':
298        current_level = obj['studycourse'].current_level
299        level_object = obj['studycourse'].get(str(current_level), None)
300        if level_object is not None:
301            user = get_current_principal()
302            if user is None:
303                usertitle = 'system'
304            else:
305                usertitle = getattr(user, 'public_name', None)
306                if not usertitle:
307                    usertitle = user.title
308            level_object.validated_by = usertitle
309            level_object.validation_date = datetime.utcnow()
[9484]310    elif event.transition.transition_id == 'clear':
[9486]311        obj.officer_comment = None
[9161]312    elif event.transition.transition_id == 'reset8':
313        current_level = obj['studycourse'].current_level
314        level_object = obj['studycourse'].get(str(current_level), None)
315        if level_object is not None:
316            level_object.validated_by = None
317            level_object.validation_date = None
[15163]318    elif event.transition.transition_id == 'reset11':
319        transcript_file = getUtility(IExtFileStore).getFileByContext(
320            obj, attr='final_transcript')
321        if transcript_file:
322            getUtility(IExtFileStore).deleteFileByContext(
323                obj, attr='final_transcript')
324        obj['studycourse'].transcript_comment = None
325        obj['studycourse'].transcript_signees = None
[7652]326    # In some tests we don't have a students container
[6644]327    try:
328        students_container = grok.getSite()['students']
[7652]329        students_container.logger.info('%s - %s' % (obj.student_id,msg))
[6644]330    except (TypeError, AttributeError):
331        pass
[6637]332    return
Note: See TracBrowser for help on using the repository browser.