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
Line 
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
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    )
55
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',
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',
77      )
78UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
79    'jamb_subjects_list', 'master_sheet_number') + UG_OMIT_FIELDS
80UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + UG_OMIT_FIELDS + (
81      'alr_fname', 'alr_no', 'alr_date',
82      'alr_results', 'notice')
83UG_OMIT_MANAGE_FIELDS = (
84    'special_application','jamb_subjects_list',) + UG_OMIT_FIELDS
85UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
86    'student_id',
87    'notice',
88    'jamb_age',
89    'jamb_subjects',
90    'jamb_score',
91    'jamb_reg_number',
92    'aggregate',
93    'master_sheet_number',
94    'screening_venue',
95    'screening_score',
96    'screening_date'
97    )
98
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 + (
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')
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
140#UG_OMIT_PDF_FIELDS = tuple([
141#    element for element in UG_OMIT_PDF_FIELDS if not element == 'phone'])
142
143#UG_OMIT_PDF_FIELDS += (
144#      'reg_number','alr_fname', 'alr_no', 'alr_date',
145#      'alr_results', 'notice'
146#      )
147
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',
159    #'programme_type',
160    'jamb_age',
161    'jamb_subjects',
162    'jamb_score',
163    'jamb_reg_number',
164    'aggregate'
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',
170      'alr_results', 'notice',
171      'nysc_year',
172      'nysc_location',
173      'nysc_lga',
174      'former_matric',
175      )
176PG_OMIT_MANAGE_FIELDS = (
177    'special_application','jamb_subjects_list',) + PG_OMIT_FIELDS
178PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
179    'student_id',
180    'notice',
181    )
182
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
217UPDATE_OMIT_FIELDS = (
218    'firstname',
219    'middlename',
220    'lastname',
221    'sex',
222    'lga',
223    'course1',
224    )
225
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
251class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
252    """A display view for applicant data.
253    """
254
255    @property
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
265    def form_fields(self):
266        if self.target is not None and self.target == 'trans':
267            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
268                'locked', 'suspended')
269            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
270            form_fields['perm_address'].custom_widget = BytesDisplayWidget
271            return form_fields
272        if self.target is not None and self.target == 'cert':
273            form_fields = grok.AutoFields(ICertificateRequest).omit(
274                'locked', 'suspended')
275            #form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
276            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
277            return form_fields
278        # AAUE is using the same interface for all regular applications.
279        form_fields = grok.AutoFields(ICustomUGApplicant)
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)
283        elif self.target is not None and self.target in ('ptee','dsh',):
284            for field in PTEE_OMIT_DISPLAY_FIELDS:
285                form_fields = form_fields.omit(field)
286        elif self.target is not None and self.target in ('bridge', 'ude',):
287            for field in UDE_OMIT_DISPLAY_FIELDS:
288                form_fields = form_fields.omit(field)
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')
298        if not getattr(self.context, 'screening_venue') or \
299            self.context.state not in ('submitted', 'admitted', 'created'):
300            form_fields = form_fields.omit('screening_venue')
301        if not getattr(self.context, 'screening_date') or \
302            self.context.state not in ('submitted', 'admitted', 'created'):
303            form_fields = form_fields.omit('screening_date')
304        return form_fields
305
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
320    def update(self):
321        super(CustomApplicantDisplayFormPage, self).update()
322        self.extraform_url = self.url(self.context, 'stateresult.pdf')
323        return
324
325class CustomPDFActionButton(PDFActionButton):
326
327    @property
328    def target_url(self):
329        if self.context.state in ('initialized', 'started', 'paid') \
330            or self.context.special or self.view.target in ('trans', 'cert'):
331            return
332        return self.view.url(self.view.context, self.target)
333
334
335class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
336
337    column_two_fields = ('applicant_id', 'reg_number',
338        'firstname', 'middlename', 'lastname', 'sex', 'date_of_birth')
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']
344
345    def _getCourseAdmittedLink(self, view):
346        return None
347
348    def _getDeptAndFaculty(self):
349        return [None, None]
350
351    @property
352    def note(self):
353        note = getattr(self.context.__parent__, 'application_slip_notice', None)
354        if note:
355            return '<br /><br />' + note
356        if self.context.sex == 'm':
357            pronoun = 'he'
358        else:
359            pronoun = 'she'
360        return '''
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
363University not be re-admitted for the same or any other programme, even if %s has
364upgraded previous qualifications or possess additional qualifications.
365
366''' % (
367    pronoun, pronoun, pronoun, pronoun, pronoun)
368
369    @property
370    def form_fields(self):
371        # AAUE is using the same interface for all regular applications.
372        form_fields = grok.AutoFields(ICustomUGApplicant)
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)
376        elif self.target is not None and self.target in ('ptee', 'dsh',):
377            for field in PTEE_OMIT_PDF_FIELDS:
378                form_fields = form_fields.omit(field)
379        elif self.target is not None and self.target in ('bridge', 'ude',):
380            for field in UDE_OMIT_PDF_FIELDS:
381                form_fields = form_fields.omit(field)
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):
401        if self.target is not None and self.target == 'trans':
402            form_fields = grok.AutoFields(ITranscriptApplicant)
403            form_fields['applicant_id'].for_display = True
404            return form_fields
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
409        # AAUE is using the same interface for all regular applications.
410        form_fields = grok.AutoFields(ICustomUGApplicant)
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)
414        elif self.target is not None and self.target in ('ptee', 'dsh',):
415            for field in PTEE_OMIT_MANAGE_FIELDS:
416                form_fields = form_fields.omit(field)
417        elif self.target is not None and self.target in ('bridge', 'ude',):
418            for field in UDE_OMIT_MANAGE_FIELDS:
419                form_fields = form_fields.omit(field)
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
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
441class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
442    """An applicant-centered edit view for applicant data.
443    """
444
445    def unremovable(self, ticket):
446        return True
447
448    def dataNotComplete(self):
449        store = getUtility(IExtFileStore)
450        # Temporarily enable passport upload also for cert and trans
451        # applications.
452        if self.context.__parent__.with_picture:
453            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
454                return _('No passport picture uploaded.')
455            if not self.target[:4] in ('cert', 'tran') and \
456                not self.request.form.get('confirm_passport', False):
457                return _('Passport picture confirmation box not ticked.')
458        if self.target in ('trans', 'cert') and \
459            not store.getFileByContext(self.context, attr=u'stateresult.pdf'):
460            return _('No statement of result pdf file uploaded.')
461
462        return False
463
464    # AAUE applicants never see the 'Remove Selected Tickets' button.
465    @property
466    def display_actions(self):
467        # If the form is unlocked, applicants are allowed to save the form
468        # and remove unused tickets.
469        actions = [[_('Save')], []]
470        # Only in state started they can also add tickets.
471        if self.context.state == STARTED:
472            actions = [[_('Save')],
473                [_('Add online payment ticket')]]
474        # In state paid, they can submit the data and further add tickets
475        # if the application is special.
476        elif self.context.special and self.context.state == PAID:
477            actions = [[_('Save'), _('Finally Submit')],
478                [_('Add online payment ticket')]]
479        elif self.context.state == PAID:
480            actions = [[_('Save'), _('Finally Submit')], []]
481        return actions
482
483    @property
484    def form_fields(self):
485        if self.target is not None and self.target == 'trans':
486            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
487                'locked', 'suspended')
488            form_fields['applicant_id'].for_display = True
489            form_fields['reg_number'].for_display = True
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
501            return form_fields
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
506            form_fields['reg_number'].for_display = True
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
516            # Additional omissions
517            if self.context.__parent__.code == 'cert5':
518                for field in ('firstname', 'middlename', 'lastname'):
519                    form_fields[field].for_display = True
520            return form_fields
521        # AAUE is using the same interface for all regular applications.
522        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
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)
526        elif self.target is not None and self.target in ('ptee','dsh',):
527            for field in PTEE_OMIT_EDIT_FIELDS:
528                form_fields = form_fields.omit(field)
529        elif self.target is not None and self.target in ('bridge', 'ude',):
530            for field in UDE_OMIT_EDIT_FIELDS:
531                form_fields = form_fields.omit(field)
532        else:
533            for field in UG_OMIT_EDIT_FIELDS:
534                form_fields = form_fields.omit(field)
535        # Additional omissions
536        if self.target is not None and self.target in ('ude', 'utme'):
537            for field in UPDATE_OMIT_FIELDS:
538                form_fields[field].for_display = True
539        form_fields['applicant_id'].for_display = True
540        form_fields['reg_number'].for_display = True
541        return form_fields
542
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
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
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
574class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
575    """Captcha'd registration page for applicants.
576    """
577
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')
584            target = getattr(self.context, 'prefix', None)
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
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)))
597        return
598
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
609class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
610
611    @property
612    def payment_slip_download_warning(self):
613        return ''
614
615class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
616    """Captcha'd status checking page for applicants.
617    """
618    grok.template('applicantcheckstatus')
619
620class ScreeningInvitationActionButton(ManageActionButton):
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'
628
629    @property
630    def target_url(self):
631        if not self.context.screening_date or not self.context.state in (
632            'submitted', 'admitted', 'created'):
633            return ''
634        return self.view.url(self.view.context, self.target)
635
636class ExportScreeningInvitationLetter(UtilityView, grok.View):
637    """Deliver a slip with only screening data.
638    This form page is available only in AAUE.
639    """
640    grok.context(ICustomApplicant)
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:
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()
659            return """
660<br /><br /><br /><br /><font size='12'>
661Dear %s,
662<br /><br />
663You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
664<br /><br />
665<strong>Date: %s
666<br /><br />
667Time: %s
668<br /><br />
669Venue: %s
670</strong>
671<br /><br />
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.
675</font>
676
677""" % (
678       self.context.display_fullname,
679       session,
680       sdate,
681       stime,
682       self.context.screening_venue)
683        return
684
685    @property
686    def title(self):
687        return None
688
689    def update(self):
690        if not self.context.screening_date or not self.context.state in (
691            'submitted', 'admitted', 'created'):
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',
699            self.context, applicantview, note=self.note)
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.