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

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

Reorder class definitions.

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