source: main/waeup.aaue/trunk/src/waeup/aaue/applicants/browser.py @ 15530

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

Implement Verification of Result/Transcript? and Certificate application form.

  • Property svn:keywords set to Id
File size: 28.8 KB
Line 
1## $Id: browser.py 15530 2019-07-31 10:49:59Z 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##
18"""UI components for basic applicants and related components.
19"""
20import grok
21import os
22from zope.component import getUtility, getAdapter
23from zope.i18n import translate
24from hurry.workflow.interfaces import IWorkflowState
25from waeup.kofa.interfaces import (
26    IExtFileStore, IFileStoreNameChooser, IKofaUtils)
27from zope.formlib.textwidgets import BytesDisplayWidget
28from waeup.kofa.utils.helpers import string_from_bytes, file_size
29from waeup.kofa.applicants.browser import (
30    ApplicantCheckStatusPage, ApplicantBaseDisplayFormPage)
31from waeup.kofa.applicants.workflow import STARTED, PAID
32from waeup.kofa.applicants.viewlets import PDFActionButton
33from waeup.kofa.applicants.interfaces import IApplicantRegisterUpdate
34from waeup.kofa.browser.layout import UtilityView
35from waeup.kofa.students.interfaces import IStudentsUtils
36from waeup.kofa.interfaces import IPDF
37from waeup.kofa.browser.viewlets import ManageActionButton
38from waeup.aaue.interfaces import MessageFactory as _
39from kofacustom.nigeria.applicants.browser import (
40    NigeriaApplicantDisplayFormPage,
41    NigeriaApplicantManageFormPage,
42    NigeriaApplicantEditFormPage,
43    NigeriaPDFApplicationSlip,
44    NigeriaApplicantRegistrationPage,
45    NigeriaExportPDFPaymentSlipPage,
46    )
47from kofacustom.nigeria.applicants.interfaces import OMIT_DISPLAY_FIELDS
48from waeup.aaue.applicants.interfaces import (
49    ICustomUGApplicant,
50    ICustomUGApplicantEdit,
51    ITranscriptApplicant,
52    ICertificateRequest,
53    ICustomApplicant,
54    IVerificationRequest
55    )
56
57UG_OMIT_FIELDS = (
58      'hq_type', 'hq_fname', 'hq_matric_no',
59      'hq_degree', 'hq_school', 'hq_session', 'hq_disc',
60      'hq_type2', 'hq_fname2', 'hq_matric_no2',
61      'hq_degree2', 'hq_school2', 'hq_session2', 'hq_disc2',
62      'hq_type3', 'hq_fname3', 'hq_matric_no3',
63      'hq_degree3', 'hq_school3', 'hq_session3', 'hq_disc3',
64      'nysc_year',
65      'nysc_location',
66      'nysc_lga',
67      'employer',
68      'emp_position',
69      'emp_start',
70      'emp_end',
71      'emp_reason',
72      'employer2',
73      'emp2_position',
74      'emp2_start',
75      'emp2_end',
76      'emp2_reason',
77      'former_matric',
78      )
79UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
80    'jamb_subjects_list', 'master_sheet_number') + UG_OMIT_FIELDS
81UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + UG_OMIT_FIELDS + (
82      'alr_fname', 'alr_no', 'alr_date',
83      'alr_results', 'notice')
84UG_OMIT_MANAGE_FIELDS = (
85    'special_application','jamb_subjects_list',) + UG_OMIT_FIELDS
86UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
87    'student_id',
88    'notice',
89    'jamb_age',
90    'jamb_subjects',
91    'jamb_score',
92    'jamb_reg_number',
93    'aggregate',
94    'master_sheet_number',
95    'screening_venue',
96    'screening_score',
97    'screening_date'
98    )
99
100UDE_OMIT_FIELDS = (
101      'nysc_year',
102      'nysc_location',
103      'nysc_lga',
104      'employer',
105      'emp_position',
106      'emp_start',
107      'emp_end',
108      'emp_reason',
109      'employer2',
110      'emp2_position',
111      'emp2_start',
112      'emp2_end',
113      'emp2_reason',
114      'former_matric',
115      )
116UDE_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
117    'jamb_subjects_list', 'master_sheet_number') + UDE_OMIT_FIELDS
118UDE_OMIT_PDF_FIELDS = UDE_OMIT_DISPLAY_FIELDS + UDE_OMIT_FIELDS + (
119      #'alr_fname', 'alr_no', 'alr_date', 'alr_results',
120      'hq_type2', 'hq_fname2', 'hq_matric_no2',
121      'hq_degree2', 'hq_school2', 'hq_session2', 'hq_disc2',
122      'hq_type3', 'hq_fname3', 'hq_matric_no3',
123      'hq_degree3', 'hq_school3', 'hq_session3', 'hq_disc3',
124      'notice')
125UDE_OMIT_MANAGE_FIELDS = (
126    'special_application','jamb_subjects_list',) + UDE_OMIT_FIELDS
127UDE_OMIT_EDIT_FIELDS = UDE_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
128    'student_id',
129    'notice',
130    'jamb_age',
131    'jamb_subjects',
132    'jamb_score',
133    'jamb_reg_number',
134    'aggregate',
135    'master_sheet_number',
136    'screening_venue',
137    'screening_score',
138    'screening_date'
139    )
140
141#UG_OMIT_PDF_FIELDS = tuple([
142#    element for element in UG_OMIT_PDF_FIELDS if not element == 'phone'])
143
144#UG_OMIT_PDF_FIELDS += (
145#      'reg_number','alr_fname', 'alr_no', 'alr_date',
146#      'alr_results', 'notice'
147#      )
148
149PG_OMIT_FIELDS = (
150    'fst_sit_fname',
151    'fst_sit_no',
152    'fst_sit_date',
153    'fst_sit_type',
154    'fst_sit_results',
155    'scd_sit_fname',
156    'scd_sit_no',
157    'scd_sit_date',
158    'scd_sit_type',
159    'scd_sit_results',
160    #'programme_type',
161    'jamb_age',
162    'jamb_subjects',
163    'jamb_score',
164    'jamb_reg_number',
165    'aggregate'
166    )
167PG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
168    'jamb_subjects_list',) + PG_OMIT_FIELDS
169PG_OMIT_PDF_FIELDS = PG_OMIT_DISPLAY_FIELDS + PG_OMIT_FIELDS + (
170      'reg_number','alr_fname', 'alr_no', 'alr_date',
171      'alr_results', 'notice',
172      'nysc_year',
173      'nysc_location',
174      'nysc_lga',
175      'former_matric',
176      )
177PG_OMIT_MANAGE_FIELDS = (
178    'special_application','jamb_subjects_list',) + PG_OMIT_FIELDS
179PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
180    'student_id',
181    'notice',
182    )
183
184PTEE_OMIT_FIELDS = (
185    'jamb_age',
186    'jamb_subjects',
187    'jamb_score',
188    'jamb_reg_number',
189    'aggregate'
190    )
191PTEE_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
192    'jamb_subjects_list',) + PTEE_OMIT_FIELDS
193PTEE_OMIT_PDF_FIELDS = PTEE_OMIT_DISPLAY_FIELDS + PTEE_OMIT_FIELDS + (
194      'reg_number','alr_fname', 'alr_no', 'alr_date',
195      'alr_results', 'notice',
196      'nysc_year',
197      'nysc_location',
198      'nysc_lga',
199      'employer',
200      'emp_position',
201      'emp_start',
202      'emp_end',
203      'emp_reason',
204      'employer2',
205      'emp2_position',
206      'emp2_start',
207      'emp2_end',
208      'emp2_reason',
209      'former_matric',
210    )
211PTEE_OMIT_MANAGE_FIELDS = (
212    'special_application','jamb_subjects_list',) + PTEE_OMIT_FIELDS
213PTEE_OMIT_EDIT_FIELDS = PTEE_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
214    'student_id',
215    'notice',
216    )
217
218UPDATE_OMIT_FIELDS = (
219    'firstname',
220    'middlename',
221    'lastname',
222    'sex',
223    'lga',
224    'course1',
225    )
226
227MAX_FILE_UPLOAD_SIZE = 1024 * 500
228
229def handle_file_upload(upload, context, view, attr=None):
230    """Handle upload of applicant files.
231
232    Returns `True` in case of success or `False`.
233
234    Please note that file pointer passed in (`upload`) most probably
235    points to end of file when leaving this function.
236    """
237    size = file_size(upload)
238    if size > MAX_FILE_UPLOAD_SIZE:
239        view.flash(_('Uploaded file is too big!'))
240        return False
241    dummy, ext = os.path.splitext(upload.filename)
242    ext.lower()
243    if ext != '.pdf':
244        view.flash(_('pdf file extension expected.'))
245        return False
246    upload.seek(0) # file pointer moved when determining size
247    store = getUtility(IExtFileStore)
248    file_id = IFileStoreNameChooser(context).chooseName(attr=attr)
249    store.createFile(file_id, upload)
250    return True
251
252class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
253    """A display view for applicant data.
254    """
255
256    @property
257    def file_links(self):
258        html = ''
259        pdf = getUtility(IExtFileStore).getFileByContext(
260            self.context, attr='stateresult.pdf')
261        if pdf:
262            html += '<a href="stateresult.pdf">Statement of Result</a>'
263        pdf = getUtility(IExtFileStore).getFileByContext(
264            self.context, attr='verificationdoc.pdf')
265        if pdf:
266            html += '<a href="verificationdoc.pdf">Result/Certificate Document</a>'
267        return html
268
269    @property
270    def form_fields(self):
271        if self.target is not None and self.target == 'trans':
272            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
273                'locked', 'suspended')
274            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
275            form_fields['perm_address'].custom_widget = BytesDisplayWidget
276            return form_fields
277        if self.target is not None and self.target == 'ver':
278            form_fields = grok.AutoFields(IVerificationRequest).omit(
279                'locked', 'suspended')
280            form_fields['body_address'].custom_widget = BytesDisplayWidget
281            return form_fields
282        if self.target is not None and self.target == 'cert':
283            form_fields = grok.AutoFields(ICertificateRequest).omit(
284                'locked', 'suspended')
285            #form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
286            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
287            return form_fields
288        # AAUE is using the same interface for all regular applications.
289        form_fields = grok.AutoFields(ICustomUGApplicant)
290        if self.target is not None and self.target.startswith('pg'):
291            for field in PG_OMIT_DISPLAY_FIELDS:
292                form_fields = form_fields.omit(field)
293        elif self.target is not None and self.target in ('ptee','dsh',):
294            for field in PTEE_OMIT_DISPLAY_FIELDS:
295                form_fields = form_fields.omit(field)
296        elif self.target is not None and self.target in ('bridge', 'ude',):
297            for field in UDE_OMIT_DISPLAY_FIELDS:
298                form_fields = form_fields.omit(field)
299        else:
300            for field in UG_OMIT_DISPLAY_FIELDS:
301                form_fields = form_fields.omit(field)
302        form_fields['perm_address'].custom_widget = BytesDisplayWidget
303        form_fields['notice'].custom_widget = BytesDisplayWidget
304        if not getattr(self.context, 'student_id'):
305            form_fields = form_fields.omit('student_id')
306        if not getattr(self.context, 'screening_score'):
307            form_fields = form_fields.omit('screening_score')
308        if not getattr(self.context, 'screening_venue') or \
309            self.context.state not in ('submitted', 'admitted', 'created'):
310            form_fields = form_fields.omit('screening_venue')
311        if not getattr(self.context, 'screening_date') or \
312            self.context.state not in ('submitted', 'admitted', 'created'):
313            form_fields = form_fields.omit('screening_date')
314        return form_fields
315
316    def getCourseAdmitted(self):
317        """Return link, title and code in html format to the certificate
318           admitted.
319        """
320        if self.layout.isApplicant():
321            return ''
322        course_admitted = self.context.course_admitted
323        if getattr(course_admitted, '__parent__',None):
324            url = self.url(course_admitted)
325            title = course_admitted.title
326            code = course_admitted.code
327            return '<a href="%s">%s - %s</a>' %(url,code,title)
328        return ''
329
330    #def update(self):
331    #    super(CustomApplicantDisplayFormPage, self).update()
332    #    #self.extraform_url = self.url(self.context, 'stateresult.pdf')
333    #    return
334
335class CustomPDFActionButton(PDFActionButton):
336
337    @property
338    def target_url(self):
339        if self.context.state in ('initialized', 'started', 'paid') \
340            or self.context.special or self.view.target in ('trans', 'cert'):
341            return
342        return self.view.url(self.view.context, self.target)
343
344
345class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
346
347    column_two_fields = ('applicant_id', 'reg_number',
348        'firstname', 'middlename', 'lastname', 'sex', 'date_of_birth')
349    #two_columns_design_fields = [
350    #    'fst_sit_fname', 'fst_sit_no', 'fst_sit_date',
351    #    'fst_sit_type', 'fst_sit_results',
352    #    'scd_sit_fname', 'scd_sit_no', 'scd_sit_date',
353    #    'scd_sit_type', 'scd_sit_results']
354
355    def _getCourseAdmittedLink(self, view):
356        return None
357
358    def _getDeptAndFaculty(self):
359        return [None, None]
360
361    @property
362    def note(self):
363        note = getattr(self.context.__parent__, 'application_slip_notice', None)
364        if note:
365            return '<br /><br />' + note
366        if self.context.sex == 'm':
367            pronoun = 'he'
368        else:
369            pronoun = 'she'
370        return '''
371The applicant has acknowledged that, if discovered at any time that %s does not possess
372any of the qualifications which %s claims %s has obtained, %s will be expelled from the
373University not be re-admitted for the same or any other programme, even if %s has
374upgraded previous qualifications or possess additional qualifications.
375
376''' % (
377    pronoun, pronoun, pronoun, pronoun, pronoun)
378
379    @property
380    def form_fields(self):
381        # AAUE is using the same interface for all regular applications.
382        form_fields = grok.AutoFields(ICustomUGApplicant)
383        if self.target is not None and self.target.startswith('pg'):
384            for field in PG_OMIT_PDF_FIELDS:
385                form_fields = form_fields.omit(field)
386        elif self.target is not None and self.target in ('ptee', 'dsh',):
387            for field in PTEE_OMIT_PDF_FIELDS:
388                form_fields = form_fields.omit(field)
389        elif self.target is not None and self.target in ('bridge', 'ude',):
390            for field in UDE_OMIT_PDF_FIELDS:
391                form_fields = form_fields.omit(field)
392        else:
393            for field in UG_OMIT_PDF_FIELDS:
394                form_fields = form_fields.omit(field)
395        if not getattr(self.context, 'student_id'):
396            form_fields = form_fields.omit('student_id')
397        if not getattr(self.context, 'screening_score'):
398            form_fields = form_fields.omit('screening_score')
399        if not getattr(self.context, 'screening_venue'):
400            form_fields = form_fields.omit('screening_venue')
401        if not getattr(self.context, 'screening_date'):
402            form_fields = form_fields.omit('screening_date')
403        return form_fields
404
405class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
406    """A full edit view for applicant data.
407    """
408
409    @property
410    def form_fields(self):
411        if self.target is not None and self.target == 'trans':
412            form_fields = grok.AutoFields(ITranscriptApplicant)
413            form_fields['applicant_id'].for_display = True
414            return form_fields
415        if self.target is not None and self.target == 'cert':
416            form_fields = grok.AutoFields(ICertificateRequest)
417            form_fields['applicant_id'].for_display = True
418            return form_fields
419        if self.target is not None and self.target == 'ver':
420            form_fields = grok.AutoFields(IVerificationRequest)
421            form_fields['applicant_id'].for_display = True
422            return form_fields
423        # AAUE is using the same interface for all regular applications.
424        form_fields = grok.AutoFields(ICustomUGApplicant)
425        if self.target is not None and self.target.startswith('pg'):
426            for field in PG_OMIT_MANAGE_FIELDS:
427                form_fields = form_fields.omit(field)
428        elif self.target is not None and self.target in ('ptee', 'dsh',):
429            for field in PTEE_OMIT_MANAGE_FIELDS:
430                form_fields = form_fields.omit(field)
431        elif self.target is not None and self.target in ('bridge', 'ude',):
432            for field in UDE_OMIT_MANAGE_FIELDS:
433                form_fields = form_fields.omit(field)
434        else:
435            for field in UG_OMIT_MANAGE_FIELDS:
436                form_fields = form_fields.omit(field)
437        form_fields['student_id'].for_display = True
438        form_fields['applicant_id'].for_display = True
439        return form_fields
440
441    def update(self):
442        super(CustomApplicantManageFormPage, self).update()
443        upload_stateresult = self.request.form.get('form.stateresult', None)
444        upload_verificationdoc = self.request.form.get('form.verificationdoc', None)
445        if upload_stateresult:
446            # We got a fresh stateresult upload
447            success = handle_file_upload(
448                upload_stateresult, self.context, self, attr='stateresult.pdf')
449            if success:
450                self.context.writeLogMessage(self, 'saved: stateresult')
451            else:
452                self.upload_success = False
453        if upload_verificationdoc:
454            # We got a fresh verificationdoc upload
455            success = handle_file_upload(
456                upload_verificationdoc, self.context, self, attr='verificationdoc.pdf')
457            if success:
458                self.context.writeLogMessage(self, 'saved: verificationdoc')
459            else:
460                self.upload_success = False
461        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
462        return
463
464class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
465    """An applicant-centered edit view for applicant data.
466    """
467
468    def unremovable(self, ticket):
469        return True
470
471    def dataNotComplete(self):
472        store = getUtility(IExtFileStore)
473        # Temporarily enable passport upload also for cert and trans
474        # applications.
475        if self.context.__parent__.with_picture:
476            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
477                return _('No passport picture uploaded.')
478            if not self.target[:4] in ('cert', 'tran') and \
479                not self.request.form.get('confirm_passport', False):
480                return _('Passport picture confirmation box not ticked.')
481        if self.target in ('trans', 'cert') and \
482            not store.getFileByContext(self.context, attr=u'stateresult.pdf'):
483            return _('No statement of result pdf file uploaded.')
484
485        return False
486
487    # AAUE applicants never see the 'Remove Selected Tickets' button.
488    @property
489    def display_actions(self):
490        # If the form is unlocked, applicants are allowed to save the form
491        # and remove unused tickets.
492        actions = [[_('Save')], []]
493        # Only in state started they can also add tickets.
494        if self.context.state == STARTED:
495            actions = [[_('Save')],
496                [_('Add online payment ticket')]]
497        # In state paid, they can submit the data and further add tickets
498        # if the application is special.
499        elif self.context.special and self.context.state == PAID:
500            actions = [[_('Save'), _('Finally Submit')],
501                [_('Add online payment ticket')]]
502        elif self.context.state == PAID:
503            actions = [[_('Save'), _('Finally Submit')], []]
504        return actions
505
506    @property
507    def form_fields(self):
508        if self.target is not None and self.target == 'trans':
509            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
510                'locked', 'suspended')
511            form_fields['applicant_id'].for_display = True
512            form_fields['reg_number'].for_display = True
513            form_fields['place_of_birth'].field.required = True
514            form_fields['date_of_birth'].field.required = True
515            form_fields['nationality'].field.required = True
516            form_fields['email'].field.required = True
517            form_fields['phone'].field.required = True
518            form_fields['perm_address'].field.required = True
519            form_fields['dispatch_address'].field.required = True
520            form_fields['entry_mode'].field.required = True
521            form_fields['entry_session'].field.required = True
522            form_fields['end_session'].field.required = True
523            form_fields['course_studied'].field.required = True
524            return form_fields
525        if self.target is not None and self.target == 'cert':
526            form_fields = grok.AutoFields(ICertificateRequest).omit(
527                'locked', 'suspended')
528            form_fields['applicant_id'].for_display = True
529            form_fields['reg_number'].for_display = True
530            form_fields['place_of_birth'].field.required = True
531            form_fields['date_of_birth'].field.required = True
532            form_fields['nationality'].field.required = True
533            form_fields['email'].field.required = True
534            form_fields['phone'].field.required = True
535            form_fields['entry_session'].field.required = True
536            form_fields['end_session'].field.required = True
537            form_fields['course_studied'].field.required = True
538            form_fields['certificate_type'].field.required = True
539            # Additional omissions
540            if self.context.__parent__.code == 'cert5':
541                for field in ('firstname', 'middlename', 'lastname'):
542                    form_fields[field].for_display = True
543            return form_fields
544        if self.target is not None and self.target == 'ver':
545            form_fields = grok.AutoFields(IVerificationRequest).omit(
546                'locked', 'suspended')
547            form_fields['applicant_id'].for_display = True
548            return form_fields
549        # AAUE is using the same interface for all regular applications.
550        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
551        if self.target is not None and self.target.startswith('pg'):
552            for field in PG_OMIT_EDIT_FIELDS:
553                form_fields = form_fields.omit(field)
554        elif self.target is not None and self.target in ('ptee','dsh',):
555            for field in PTEE_OMIT_EDIT_FIELDS:
556                form_fields = form_fields.omit(field)
557        elif self.target is not None and self.target in ('bridge', 'ude',):
558            for field in UDE_OMIT_EDIT_FIELDS:
559                form_fields = form_fields.omit(field)
560        else:
561            for field in UG_OMIT_EDIT_FIELDS:
562                form_fields = form_fields.omit(field)
563        # Additional omissions
564        if self.target is not None and self.target in ('ude', 'utme'):
565            for field in UPDATE_OMIT_FIELDS:
566                form_fields[field].for_display = True
567        form_fields['applicant_id'].for_display = True
568        form_fields['reg_number'].for_display = True
569        return form_fields
570
571    def update(self):
572        if self.context.locked or (
573            self.context.__parent__.expired and
574            self.context.__parent__.strict_deadline):
575            self.emit_lock_message()
576            return
577        if getattr(
578            self.context.course1, 'code', 'nocourse') == self.request.form.get(
579            'form.course2', None):
580            self.flash(_('2nd choice course must differ from 1st choice course.'),
581                       type='danger')
582            self.redirect(self.url(self.context))
583            return
584        if getattr(
585            self.context.course1, 'code', 'nocourse') == self.request.form.get(
586            'form.course3', None):
587            self.flash(_('3rd choice course must differ from 1st choice course.'),
588                       type='danger')
589            self.redirect(self.url(self.context))
590            return
591        super(CustomApplicantEditFormPage, self).update()
592        upload_stateresult = self.request.form.get('form.stateresult', None)
593        upload_verificationdoc = self.request.form.get('form.verificationdoc', None)
594        if upload_stateresult:
595            # We got a fresh stateresult upload
596            success = handle_file_upload(
597                upload_stateresult, self.context, self, attr='stateresult.pdf')
598            if not success:
599                self.upload_success = False
600        if upload_verificationdoc:
601            # We got a fresh verificationdoc upload
602            success = handle_file_upload(
603                upload_verificationdoc, self.context, self, attr='verificationdoc.pdf')
604            if not success:
605                self.upload_success = False
606        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
607        return
608
609class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
610    """Captcha'd registration page for applicants.
611    """
612
613    @property
614    def form_fields(self):
615        form_fields = None
616        if self.context.mode == 'update':
617            form_fields = grok.AutoFields(IApplicantRegisterUpdate).select(
618                'lastname','reg_number','email')
619            target = getattr(self.context, 'prefix', None)
620            if target in ('trans', 'cert'):
621                form_fields.get('reg_number').field.title = u'Matriculation Number'
622        else: #if self.context.mode == 'create':
623            form_fields = grok.AutoFields(ICustomUGApplicantEdit).select(
624                'firstname', 'middlename', 'lastname', 'email', 'phone')
625        return form_fields
626
627    def _redirect(self, email, password, applicant_id):
628        # Forward email and credentials to landing page.
629        self.redirect(self.url(self.context, 'registration_complete',
630            data = dict(email=email, password=password,
631            applicant_id=applicant_id)))
632        return
633
634    @property
635    def _postfix(self):
636        """Alumni records have to be imported into several containers.
637        Therefore a string must be added to their registration number
638        to make it unique.
639        """
640        if self.context.prefix in ('trans', 'cert'):
641            return self.context.code
642        return ''
643
644class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
645
646    @property
647    def payment_slip_download_warning(self):
648        return ''
649
650class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
651    """Captcha'd status checking page for applicants.
652    """
653    grok.template('applicantcheckstatus')
654
655class ScreeningInvitationActionButton(ManageActionButton):
656    grok.order(8) # This button should always be the last one.
657    grok.context(ICustomApplicant)
658    grok.view(CustomApplicantDisplayFormPage)
659    grok.require('waeup.viewApplication')
660    icon = 'actionicon_pdf.png'
661    text = _('Download screening invitation letter')
662    target = 'screening_invitation.pdf'
663
664    @property
665    def target_url(self):
666        if not self.context.screening_date or not self.context.state in (
667            'submitted', 'admitted', 'created'):
668            return ''
669        return self.view.url(self.view.context, self.target)
670
671class ExportScreeningInvitationLetter(UtilityView, grok.View):
672    """Deliver a slip with only screening data.
673    This form page is available only in AAUE.
674    """
675    grok.context(ICustomApplicant)
676    grok.name('screening_invitation.pdf')
677    grok.require('waeup.viewApplication')
678    prefix = 'form'
679
680    label = u'Screening Invitation Letter'
681
682    form_fields = []
683
684    @property
685    def note(self):
686        if self.context.screening_date:
687            year = self.context.__parent__.year
688            session = '%s/%s' % (year, year + 1)
689            sdate = self.context.screening_date
690            stime = ''
691            if '@' in self.context.screening_date:
692                sdate = self.context.screening_date.split('@')[0].strip()
693                stime = self.context.screening_date.split('@')[1].strip()
694            return """
695<br /><br /><br /><br /><font size='12'>
696Dear %s,
697<br /><br />
698You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
699<br /><br />
700<strong>Date: %s
701<br /><br />
702Time: %s
703<br /><br />
704Venue: %s
705</strong>
706<br /><br />
707Please bring this letter of invitation and the downloaded application form along with you on your screening date.
708<br /><br />
709You are expected to be available 30 minutes before the commencement of your Screening.
710</font>
711
712""" % (
713       self.context.display_fullname,
714       session,
715       sdate,
716       stime,
717       self.context.screening_venue)
718        return
719
720    @property
721    def title(self):
722        return None
723
724    def update(self):
725        if not self.context.screening_date or not self.context.state in (
726            'submitted', 'admitted', 'created'):
727            self.flash(_('Forbidden'), type="warning")
728            self.redirect(self.url(self.context))
729
730    def render(self):
731        applicantview = ApplicantBaseDisplayFormPage(self.context, self.request)
732        students_utils = getUtility(IStudentsUtils)
733        return students_utils.renderPDF(self,'screening_data.pdf',
734            self.context, applicantview, note=self.note)
735
736class StateResult(grok.View):
737    """Renders the pdf form extension for applicants.
738    """
739    grok.name('stateresult.pdf')
740    grok.context(ICustomApplicant)
741    grok.require('waeup.viewApplication')
742
743    def render(self):
744        pdf = getUtility(IExtFileStore).getFileByContext(
745            self.context, attr='stateresult.pdf')
746        self.response.setHeader('Content-Type', 'application/pdf')
747        return pdf
748
749class VerificationDoc(grok.View):
750    """Renders the pdf form extension for applicants.
751    """
752    grok.name('verificationdoc.pdf')
753    grok.context(ICustomApplicant)
754    grok.require('waeup.viewApplication')
755
756    def render(self):
757        pdf = getUtility(IExtFileStore).getFileByContext(
758            self.context, attr='verificationdoc.pdf')
759        self.response.setHeader('Content-Type', 'application/pdf')
760        return pdf
Note: See TracBrowser for help on using the repository browser.