source: main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py @ 6774

Last change on this file since 6774 was 6774, checked in by Henrik Bettermann, 14 years ago

Add StudentStudyLevel? container class. These containers will contain the course tickets. The study level containers correspond with the the 'course lists' which have to be registered at the beginning of each session.

  • work in progress -
  • Property svn:keywords set to Id
File size: 25.3 KB
Line 
1## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
2## This program is free software; you can redistribute it and/or modify
3## it under the terms of the GNU General Public License as published by
4## the Free Software Foundation; either version 2 of the License, or
5## (at your option) any later version.
6##
7## This program is distributed in the hope that it will be useful,
8## but WITHOUT ANY WARRANTY; without even the implied warranty of
9## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10## GNU General Public License for more details.
11##
12## You should have received a copy of the GNU General Public License
13## along with this program; if not, write to the Free Software
14## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15##
16"""UI components for students and related components.
17"""
18import grok
19
20from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
21from zope.component import createObject
22from waeup.sirp.accesscodes import invalidate_accesscode, get_access_code
23from waeup.sirp.accesscodes.workflow import USED
24from waeup.sirp.browser import (
25    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage, WAeUPDisplayFormPage)
26from waeup.sirp.browser.breadcrumbs import Breadcrumb
27from waeup.sirp.browser.resources import datepicker, datatable
28from waeup.sirp.browser.viewlets import (
29    ManageActionButton, PrimaryNavTab, AddActionButton)
30from waeup.sirp.interfaces import IWAeUPObject, IUserAccount
31from waeup.sirp.widgets.datewidget import (
32    FriendlyDateWidget, FriendlyDateDisplayWidget)
33from waeup.sirp.students.interfaces import (
34    IStudentsContainer, IStudent, IStudentClearance, IStudentPasswordSetting,
35    IStudentPersonal, IStudentBase, IStudentStudyCourse, IStudentPayments,
36    IStudentAccommodation, IStudentClearanceEdit, IStudentStudyLevel,
37    )
38from waeup.sirp.students.catalog import search
39from waeup.sirp.students.workflow import CLEARANCE
40from waeup.sirp.students.studylevel import StudentStudyLevel
41
42# Save function used for save methods in manager pages
43def msave(view, **data):
44    form = view.request.form
45    ob_class = view.__implemented__.__name__.replace('waeup.sirp.','')
46    changed_fields = view.applyData(view.context, **data)
47    # Turn list of lists into single list
48    if changed_fields:
49        changed_fields = reduce(lambda x,y: x+y, changed_fields.values())
50    fields_string = ' + '.join(changed_fields)
51    view.context._p_changed = True
52    view.flash('Form has been saved.')
53    if fields_string:
54        try:
55            view.context.loggerInfo(ob_class, 'saved: % s' % fields_string)
56        except AttributeError:
57            view.context.__parent__.loggerInfo(ob_class, 'saved: % s' % fields_string)
58    return
59
60class StudentsTab(PrimaryNavTab):
61    """Students tab in primary navigation.
62    """
63
64    grok.context(IWAeUPObject)
65    grok.order(3)
66    grok.require('waeup.viewStudent')
67    grok.template('primarynavtab')
68
69    pnav = 4
70    tab_title = u'Students'
71
72    @property
73    def link_target(self):
74        return self.view.application_url('students')
75
76class StudentsBreadcrumb(Breadcrumb):
77    """A breadcrumb for the students container.
78    """
79    grok.context(IStudentsContainer)
80    title = u'Students'
81
82class SudyCourseBreadcrumb(Breadcrumb):
83    """A breadcrumb for the student study course.
84    """
85    grok.context(IStudentStudyCourse)
86    title = u'Study Course'
87
88class PaymentsBreadcrumb(Breadcrumb):
89    """A breadcrumb for the student payments folder.
90    """
91    grok.context(IStudentPayments)
92    title = u'Payments'
93
94class AccommodationBreadcrumb(Breadcrumb):
95    """A breadcrumb for the student accommodation folder.
96    """
97    grok.context(IStudentAccommodation)
98    title = u'Accommodation'
99
100class StudentsContainerPage(WAeUPPage):
101    """The standard view for student containers.
102    """
103    grok.context(IStudentsContainer)
104    grok.name('index')
105    grok.require('waeup.viewStudent')
106    grok.template('containerpage')
107    label = 'Student Section'
108    title = 'Students'
109    pnav = 4
110
111    def update(self, *args, **kw):
112        datatable.need()
113        form = self.request.form
114        self.hitlist = []
115        if 'searchterm' in form and form['searchterm']:
116            self.searchterm = form['searchterm']
117            self.searchtype = form['searchtype']
118        elif 'old_searchterm' in form:
119            self.searchterm = form['old_searchterm']
120            self.searchtype = form['old_searchtype']
121        else:
122            if 'search' in form:
123                self.flash('Empty search string.')
124            return
125        self.hitlist = search(query=self.searchterm,
126            searchtype=self.searchtype, view=self)
127        if not self.hitlist:
128            self.flash('No student found.')
129        return
130
131class SetPasswordPage(WAeUPPage):
132    grok.context(IWAeUPObject)
133    grok.name('setpassword')
134    grok.require('waeup.Public')
135    grok.template('setpassword')
136    title = ''
137    label = 'Set password for first-time login'
138    ac_prefix = 'PWD'
139    pnav = 0
140
141    def update(self, SUBMIT=None):
142        self.reg_number = self.request.form.get('reg_number', None)
143        self.ac_series = self.request.form.get('ac_series', None)
144        self.ac_number = self.request.form.get('ac_number', None)
145
146        if SUBMIT is None:
147            return
148        hitlist = search(query=self.reg_number,
149            searchtype='reg_number', view=self)
150        if not hitlist:
151            self.flash('No student found.')
152            return
153        if len(hitlist) != 1:   # Cannot happen but anyway
154            self.flash('More than one student found.')
155            return
156        student = hitlist[0].context
157        self.student_id = student.student_id
158        student_pw = student.password
159        pin = '%s-%s-%s' % (self.ac_prefix, self.ac_series, self.ac_number)
160        code = get_access_code(pin)
161        if not code:
162            self.flash('Access code is invalid.')
163            return
164        if student_pw and pin == student.adm_code:
165            self.flash('Password has already been set. Your Student Id is %s'
166                % self.student_id)
167            return
168        elif student_pw:
169            self.flash('Password has already been set.')
170            return
171        # Mark pin as used (this also fires a pin related transition)
172        # and set student password
173        if code.state == USED:
174            self.flash('Access code has already been used.')
175            return
176        else:
177            comment = u"AC invalidated for %s" % self.student_id
178            # Here we know that the ac is in state initialized so we do not
179            # expect an exception
180            #import pdb; pdb.set_trace()
181            invalidate_accesscode(pin,comment)
182            IUserAccount(student).setPassword(self.ac_number)
183            student.adm_code = pin
184        self.flash('Password has been set. Your Student Id is %s'
185            % self.student_id)
186        return
187
188class StudentsContainerManageActionButton(ManageActionButton):
189    grok.order(1)
190    grok.context(IStudentsContainer)
191    grok.view(StudentsContainerPage)
192    grok.require('waeup.manageStudents')
193    text = 'Manage student section'
194
195
196class StudentsContainerManagePage(WAeUPPage):
197    """The manage page for student containers.
198    """
199    grok.context(IStudentsContainer)
200    grok.name('manage')
201    grok.require('waeup.manageStudents')
202    grok.template('containermanagepage')
203    pnav = 4
204    title = 'Manage student section'
205
206    @property
207    def label(self):
208        return self.title
209
210    def update(self, *args, **kw):
211        datatable.need()
212        form = self.request.form
213        self.hitlist = []
214        if 'searchterm' in form and form['searchterm']:
215            self.searchterm = form['searchterm']
216            self.searchtype = form['searchtype']
217        elif 'old_searchterm' in form:
218            self.searchterm = form['old_searchterm']
219            self.searchtype = form['old_searchtype']
220        else:
221            if 'search' in form:
222                self.flash('Empty search string.')
223            return
224        if not 'entries' in form:
225            self.hitlist = search(query=self.searchterm,
226                searchtype=self.searchtype, view=self)
227            if not self.hitlist:
228                self.flash('No student found.')
229            return
230        entries = form['entries']
231        if isinstance(entries, basestring):
232            entries = [entries]
233        deleted = []
234        for entry in entries:
235            if 'remove' in form:
236                del self.context[entry]
237                deleted.append(entry)
238        self.hitlist = search(query=self.searchterm,
239            searchtype=self.searchtype, view=self)
240        if len(deleted):
241            self.flash('Successfully removed: %s' % ', '.join(deleted))
242        return
243
244class StudentsContainerAddActionButton(AddActionButton):
245    grok.order(1)
246    grok.context(IStudentsContainer)
247    grok.view(StudentsContainerManagePage)
248    grok.require('waeup.manageStudents')
249    text = 'Add student'
250    target = 'addstudent'
251
252class StudentAddFormPage(WAeUPAddFormPage):
253    """Add-form to add a student.
254    """
255    grok.context(IStudentsContainer)
256    grok.require('waeup.manageStudents')
257    grok.name('addstudent')
258    grok.template('studentaddpage')
259    form_fields = grok.AutoFields(IStudent)
260    title = 'Students'
261    label = 'Add student'
262    pnav = 4
263
264    @grok.action('Create student record')
265    def addStudent(self, **data):
266        student = createObject(u'waeup.Student')
267        self.applyData(student, **data)
268        self.context.addStudent(student)
269        self.flash('Student record created.')
270        self.redirect(self.url(self.context[student.student_id], 'index'))
271        return
272
273class StudentBaseDisplayFormPage(WAeUPDisplayFormPage):
274    """ Page to display student base data
275    """
276    grok.context(IStudent)
277    grok.name('index')
278    grok.require('waeup.viewStudent')
279    grok.template('basepage')
280    form_fields = grok.AutoFields(IStudentBase).omit('password')
281    pnav = 4
282    title = 'Base Data'
283
284    @property
285    def label(self):
286        return '%s: Base Data' % self.context.name
287
288    @property
289    def hasPassword(self):
290        if self.context.password:
291            return 'set'
292        return 'unset'
293
294class StudentBaseManageActionButton(ManageActionButton):
295    grok.order(1)
296    grok.context(IStudent)
297    grok.view(StudentBaseDisplayFormPage)
298    grok.require('waeup.manageStudents')
299    text = 'Manage'
300    target = 'edit_base'
301
302class StudentBaseManageFormPage(WAeUPEditFormPage):
303    """ View to edit student base data
304    """
305    grok.context(IStudent)
306    grok.name('edit_base')
307    grok.require('waeup.manageStudents')
308    form_fields = grok.AutoFields(IStudentBase).omit('student_id')
309    grok.template('basemanagepage')
310    label = 'Manage base data'
311    title = 'Base Data'
312    pnav = 4
313
314    def update(self):
315        datepicker.need() # Enable jQuery datepicker in date fields.
316        super(StudentBaseManageFormPage, self).update()
317        self.wf_info = IWorkflowInfo(self.context)
318        return
319
320    def getTransitions(self):
321        """Return a list of dicts of allowed transition ids and titles.
322
323        Each list entry provides keys ``name`` and ``title`` for
324        internal name and (human readable) title of a single
325        transition.
326        """
327        allowed_transitions = self.wf_info.getManualTransitions()
328        return [dict(name='', title='No transition')] +[
329            dict(name=x, title=y) for x, y in allowed_transitions]
330
331    @grok.action('Save')
332    def save(self, **data):
333        form = self.request.form
334        ob_class = self.__implemented__.__name__.replace('waeup.sirp.','')
335        if form.has_key('password') and form['password']:
336            if form['password'] != form['control_password']:
337                self.flash('Passwords do not match.')
338                return
339            IUserAccount(self.context).setPassword(form['password'])
340            self.context.loggerInfo(ob_class, 'password changed')
341        # Turn list of lists into single list
342        changed_fields = self.applyData(self.context, **data)
343        if changed_fields:
344            changed_fields = reduce(lambda x,y: x+y, changed_fields.values())
345            changed_fields = [x for x in changed_fields
346                              if not x.startswith('password')]
347        fields_string = ' + '.join(changed_fields)
348        self.context._p_changed = True
349        if form.has_key('transition') and form['transition']:
350            transition_id = form['transition']
351            self.wf_info.fireTransition(transition_id)
352        self.flash('Form has been saved.')
353        if fields_string:
354            self.context.loggerInfo(ob_class, 'saved: % s' % fields_string)
355        return
356
357class StudentClearanceDisplayFormPage(WAeUPDisplayFormPage):
358    """ Page to display student clearance data
359    """
360    grok.context(IStudent)
361    grok.name('view_clearance')
362    grok.require('waeup.viewStudent')
363    form_fields = grok.AutoFields(IStudentClearance).omit('clearance_locked')
364    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
365    title = 'Clearance Data'
366    pnav = 4
367
368    @property
369    def label(self):
370        return '%s: Clearance Data' % self.context.name
371
372class StudentClearanceManageActionButton(ManageActionButton):
373    grok.order(1)
374    grok.context(IStudent)
375    grok.view(StudentClearanceDisplayFormPage)
376    grok.require('waeup.manageStudents')
377    text = 'Manage'
378    target = 'edit_clearance'
379
380class StudentClearanceManageFormPage(WAeUPEditFormPage):
381    """ Page to edit student clearance data
382    """
383    grok.context(IStudent)
384    grok.name('edit_clearance')
385    grok.require('waeup.manageStudents')
386    form_fields = grok.AutoFields(IStudentClearance)
387    label = 'Manage clearance data'
388    title = 'Clearance Data'
389    pnav = 4
390
391    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
392
393    def update(self):
394        datepicker.need() # Enable jQuery datepicker in date fields.
395        return super(StudentClearanceManageFormPage, self).update()
396
397    @grok.action('Save')
398    def save(self, **data):
399        msave(self, **data)
400        return
401
402class StudentPersonalDisplayFormPage(WAeUPDisplayFormPage):
403    """ Page to display student personal data
404    """
405    grok.context(IStudent)
406    grok.name('view_personal')
407    grok.require('waeup.viewStudent')
408    form_fields = grok.AutoFields(IStudentPersonal)
409    title = 'Personal Data'
410    pnav = 4
411
412    @property
413    def label(self):
414        return '%s: Personal Data' % self.context.name
415
416class StudentPersonalManageActionButton(ManageActionButton):
417    grok.order(1)
418    grok.context(IStudent)
419    grok.view(StudentPersonalDisplayFormPage)
420    grok.require('waeup.manageStudents')
421    text = 'Manage'
422    target = 'edit_personal'
423
424class StudentPersonalManageFormPage(WAeUPEditFormPage):
425    """ Page to edit student clearance data
426    """
427    grok.context(IStudent)
428    grok.name('edit_personal')
429    grok.require('waeup.viewStudent')
430    form_fields = grok.AutoFields(IStudentPersonal)
431    label = 'Manage personal data'
432    title = 'Personal Data'
433    pnav = 4
434
435    @grok.action('Save')
436    def save(self, **data):
437        msave(self, **data)
438        return
439
440class StudyCourseDisplayFormPage(WAeUPDisplayFormPage):
441    """ Page to display the student study course data
442    """
443    grok.context(IStudentStudyCourse)
444    grok.name('index')
445    grok.require('waeup.viewStudent')
446    form_fields = grok.AutoFields(IStudentStudyCourse)
447    #grok.template('studycoursepage')
448    title = 'Study Course'
449    pnav = 4
450
451    @property
452    def label(self):
453        return '%s: Study Course' % self.context.__parent__.name
454
455class StudyCourseManageActionButton(ManageActionButton):
456    grok.order(1)
457    grok.context(IStudentStudyCourse)
458    grok.view(StudyCourseDisplayFormPage)
459    grok.require('waeup.manageStudents')
460    text = 'Manage'
461    target = 'edit'
462
463class StudyCourseManageFormPage(WAeUPEditFormPage):
464    """ Page to edit the student study course data
465    """
466    grok.context(IStudentStudyCourse)
467    grok.name('edit')
468    grok.require('waeup.manageStudents')
469    form_fields = grok.AutoFields(IStudentStudyCourse)
470    title = 'Study Course'
471    label = 'Manage study course'
472    pnav = 4
473
474    @grok.action('Save')
475    def save(self, **data):
476        msave(self, **data)
477        return
478
479    @grok.action('Add level')
480    def addStudyLevel(self, **data):
481        studylevel = StudentStudyLevel()
482        studylevel.level = str(self.context.current_level)
483        self.context.addStudentStudyLevel(studylevel)
484        return
485
486class StudyCourseAddActionButton(AddActionButton):
487    grok.order(1)
488    grok.context(IStudentStudyCourse)
489    grok.view(StudyCourseManageFormPage)
490    grok.require('waeup.manageStudents')
491    text = 'Add study level'
492    target = ''
493
494class StudyLevelDisplayFormPage(WAeUPDisplayFormPage):
495    """ Page to display student study levels
496    """
497    grok.context(IStudentStudyLevel)
498    grok.name('index')
499    grok.require('waeup.viewStudent')
500    form_fields = grok.AutoFields(IStudentStudyCourse)
501    #grok.template('studylevelpage')
502    title = 'Study Level'
503    pnav = 4
504
505    @property
506    def label(self):
507        return '%s: Study Level' % self.context.__parent__.name
508
509class PaymentsDisplayFormPage(WAeUPDisplayFormPage):
510    """ Page to display the student payments
511    """
512    grok.context(IStudentPayments)
513    grok.name('index')
514    grok.require('waeup.viewStudent')
515    form_fields = grok.AutoFields(IStudentPayments)
516    #grok.template('paymentspage')
517    title = 'Payments'
518    pnav = 4
519
520    @property
521    def label(self):
522        return '%s: Payments' % self.context.__parent__.name
523
524class AccommodationDisplayFormPage(WAeUPDisplayFormPage):
525    """ Page to display the student accommodation data
526    """
527    grok.context(IStudentAccommodation)
528    grok.name('index')
529    grok.require('waeup.viewStudent')
530    form_fields = grok.AutoFields(IStudentAccommodation)
531    #grok.template('accommodationpage')
532    title = 'Accommodation'
533    pnav = 4
534
535    @property
536    def label(self):
537        return '%s: Accommodation Data' % self.context.__parent__.name
538
539class StudentHistoryPage(WAeUPPage):
540    """ Page to display student clearance data
541    """
542    grok.context(IStudent)
543    grok.name('history')
544    grok.require('waeup.viewStudent')
545    grok.template('studenthistory')
546    title = 'History'
547    pnav = 4
548
549    @property
550    def label(self):
551        return '%s: History' % self.context.name
552
553# Pages for students only
554
555class StudentBaseEditActionButton(ManageActionButton):
556    grok.order(1)
557    grok.context(IStudent)
558    grok.view(StudentBaseDisplayFormPage)
559    grok.require('waeup.handleStudent')
560    text = 'Change password'
561    target = 'bedit'
562
563class StudentPasswordSetting(grok.Adapter):
564    """Adapt IStudent to data needed for password settings.
565
566    We provide password getters/setters for the attached context (an
567    IStudent object) that cooperate seamless with the usual
568    formlib/form techniques.
569    """
570    grok.context(IStudent)
571    grok.provides(IStudentPasswordSetting)
572
573    def __init__(self, context):
574        self.name = context.name
575        self.password_repeat = context.password
576        self.context = context
577        return
578
579    def getPassword(self):
580        return self.context.password
581
582    def setPassword(self, password):
583        IUserAccount(self.context).setPassword(password)
584        return
585
586    password = property(getPassword, setPassword)
587
588class StudentBaseEditFormPage(WAeUPEditFormPage):
589    """ View to edit student base data by student
590    """
591    grok.context(IStudent)
592    grok.name('bedit')
593    grok.require('waeup.handleStudent')
594    #form_fields = grok.AutoFields(IStudentBaseEdit).omit(
595    #    'student_id', 'reg_number', 'matric_number')
596    form_fields = grok.AutoFields(IStudentPasswordSetting)
597    grok.template('baseeditpage')
598    label = 'Change password'
599    title = 'Base Data'
600    pnav = 4
601
602    def update(self):
603        super(StudentBaseEditFormPage, self).update()
604        self.wf_info = IWorkflowInfo(self.context)
605        return
606
607    def onFailure(self, action, data, errors):
608        new_status = []
609        other_errors = False
610        for error in errors:
611            msg = getattr(error, 'message', '')
612            if isinstance(msg, basestring) and msg != '':
613                new_status.append(msg)
614            else:
615                other_errors = True
616        if other_errors:
617            if new_status:
618                new_status.append('see below for further errors')
619            else:
620                new_status.append('See below for details.')
621        if new_status:
622            self.status = u'There were errors: %s' % ', '.join(new_status)
623        return
624
625    @grok.action('Save', failure=onFailure)
626    def save(self, **data):
627        self.applyData(self.context, **data)
628        self.flash('Form has been saved.')
629        return
630
631class StudentClearanceStartActionButton(ManageActionButton):
632    grok.order(1)
633    grok.context(IStudent)
634    grok.view(StudentClearanceDisplayFormPage)
635    grok.require('waeup.handleStudent')
636    icon = 'actionicon_start.png'
637    text = 'Start clearance'
638    target = 'start_clearance'
639
640    @property
641    def target_url(self):
642        if self.context.state != 'admitted':
643            return ''
644        return self.view.url(self.view.context, self.target)
645
646class StartClearancePage(WAeUPPage):
647    grok.context(IStudent)
648    grok.name('start_clearance')
649    grok.require('waeup.handleStudent')
650    grok.template('enterpin')
651    title = 'Start clearance'
652    label = 'Start clearance'
653    ac_prefix = 'CLR'
654    notice = ''
655    pnav = 4
656    buttonname = 'Start clearance now'
657
658    def update(self, SUBMIT=None):
659        self.ac_series = self.request.form.get('ac_series', None)
660        self.ac_number = self.request.form.get('ac_number', None)
661
662        if SUBMIT is None:
663            return
664        pin = '%s-%s-%s' % (self.ac_prefix, self.ac_series, self.ac_number)
665        code = get_access_code(pin)
666        if not code:
667            self.flash('Access code is invalid.')
668            return
669        # Mark pin as used (this also fires a pin related transition)
670        # and fire transition start_clearance
671        if code.state == USED:
672            self.flash('Access code has already been used.')
673            return
674        else:
675            comment = u"AC invalidated for %s" % self.context.student_id
676            # Here we know that the ac is in state initialized so we do not
677            # expect an exception
678            invalidate_accesscode(pin,comment)
679            self.context.clr_code = pin
680        IWorkflowInfo(self.context).fireTransition('start_clearance')
681        self.flash('Clearance process has been started.')
682        self.redirect(self.url(self.context,'cedit'))
683        return
684
685class StudentClearanceEditActionButton(ManageActionButton):
686    grok.order(1)
687    grok.context(IStudent)
688    grok.view(StudentClearanceDisplayFormPage)
689    grok.require('waeup.handleStudent')
690    text = 'Edit'
691    target = 'cedit'
692
693    @property
694    def target_url(self):
695        if self.context.clearance_locked:
696            return ''
697        return self.view.url(self.view.context, self.target)
698
699class StudentClearanceEditFormPage(StudentClearanceManageFormPage):
700    """ View to edit student clearance data by student
701    """
702    grok.context(IStudent)
703    grok.name('cedit')
704    grok.require('waeup.handleStudent')
705    form_fields = grok.AutoFields(
706        IStudentClearanceEdit).omit('clearance_locked')
707    label = 'Edit clearance data'
708    title = 'Clearance Data'
709    pnav = 4
710    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
711
712    def emitLockMessage(self):
713        self.flash('The requested form is locked (read-only).')
714        self.redirect(self.url(self.context))
715        return
716
717    def update(self):
718        if self.context.clearance_locked:
719            self.emitLockMessage()
720            return
721        datepicker.need()
722        return super(StudentClearanceEditFormPage, self).update()
723
724    @grok.action('Save')
725    def save(self, **data):
726        self.applyData(self.context, **data)
727        self.flash('Clearance form has been saved.')
728        return
729
730    @grok.action('Save and request clearance')
731    def requestclearance(self, **data):
732        self.applyData(self.context, **data)
733        self.context._p_changed = True
734        #if self.dataNotComplete():
735        #    self.flash(self.dataNotComplete())
736        #    return
737        self.flash('Clearance form has been saved.')
738        self.redirect(self.url(self.context,'request_clearance'))
739        return
740
741class RequestClearancePage(WAeUPPage):
742    grok.context(IStudent)
743    grok.name('request_clearance')
744    grok.require('waeup.handleStudent')
745    grok.template('enterpin')
746    title = 'Request clearance'
747    label = 'Request clearance'
748    notice = 'Enter the CLR access code used for starting clearance.'
749    ac_prefix = 'CLR'
750    pnav = 4
751    buttonname = 'Request clearance now'
752
753    def update(self, SUBMIT=None):
754        self.ac_series = self.request.form.get('ac_series', None)
755        self.ac_number = self.request.form.get('ac_number', None)
756        if SUBMIT is None:
757            return
758        pin = '%s-%s-%s' % (self.ac_prefix, self.ac_series, self.ac_number)
759        if self.context.clr_code != pin:
760            self.flash("This isn't your CLR access code.")
761            return
762        state = IWorkflowState(self.context).getState()
763        # This shouldn't happen, but the application officer
764        # might have forgotten to lock the form after changing the state
765        if state != CLEARANCE:
766            self.flash('This form cannot be submitted. Wrong state!')
767            return
768        IWorkflowInfo(self.context).fireTransition('request_clearance')
769        self.flash('Clearance has been requested.')
770        self.redirect(self.url(self.context))
771        return
Note: See TracBrowser for help on using the repository browser.