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

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

Adjust to changes made in base package.

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