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

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

Let dsh2019 use same form as ptee2018 for application.

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