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

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

Fix links.

Change fac_dep category title.

  • Property svn:keywords set to Id
File size: 30.6 KB
Line 
1## $Id: browser.py 15841 2019-11-22 12:43:00Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""UI components for basic applicants and related components.
19"""
20import grok
21import os
22from zope.component import getUtility, getAdapter
23from zope.i18n import translate
24from hurry.workflow.interfaces import IWorkflowState
25from waeup.kofa.interfaces import (
26    IExtFileStore, IFileStoreNameChooser, IKofaUtils)
27from zope.formlib.textwidgets import BytesDisplayWidget
28from waeup.kofa.utils.helpers import string_from_bytes, file_size
29from waeup.kofa.applicants.browser import (
30    ApplicantCheckStatusPage, ApplicantBaseDisplayFormPage)
31from waeup.kofa.applicants.workflow import STARTED, PAID
32from waeup.kofa.applicants.viewlets import PDFActionButton
33from waeup.kofa.applicants.interfaces import IApplicantRegisterUpdate
34from waeup.kofa.browser.layout import UtilityView
35from waeup.kofa.students.interfaces import IStudentsUtils
36from waeup.kofa.interfaces import IPDF
37from waeup.kofa.browser.viewlets import ManageActionButton
38from waeup.aaue.interfaces import MessageFactory as _
39from kofacustom.nigeria.applicants.browser import (
40    NigeriaApplicantDisplayFormPage,
41    NigeriaApplicantManageFormPage,
42    NigeriaApplicantEditFormPage,
43    NigeriaPDFApplicationSlip,
44    NigeriaApplicantRegistrationPage,
45    NigeriaExportPDFPaymentSlipPage,
46    )
47from kofacustom.nigeria.applicants.interfaces import OMIT_DISPLAY_FIELDS
48from waeup.aaue.applicants.interfaces import (
49    ICustomUGApplicant,
50    ICustomUGApplicantEdit,
51    ITranscriptApplicant,
52    ICertificateRequest,
53    ICustomApplicant,
54    IVerificationRequest,
55    ISendByEmailRequest
56    )
57
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',
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',
79      )
80UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
81    'jamb_subjects_list', 'master_sheet_number') + UG_OMIT_FIELDS
82UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + UG_OMIT_FIELDS + (
83      'alr_fname', 'alr_no', 'alr_date',
84      'alr_results', 'notice')
85UG_OMIT_MANAGE_FIELDS = (
86    'special_application','jamb_subjects_list',) + UG_OMIT_FIELDS
87UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
88    'student_id',
89    'notice',
90    'jamb_age',
91    'jamb_subjects',
92    'jamb_score',
93    'jamb_reg_number',
94    'aggregate',
95    'master_sheet_number',
96    'screening_venue',
97    'screening_score',
98    'screening_date'
99    )
100
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 + (
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')
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
142#UG_OMIT_PDF_FIELDS = tuple([
143#    element for element in UG_OMIT_PDF_FIELDS if not element == 'phone'])
144
145#UG_OMIT_PDF_FIELDS += (
146#      'reg_number','alr_fname', 'alr_no', 'alr_date',
147#      'alr_results', 'notice'
148#      )
149
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',
161    #'programme_type',
162    'jamb_age',
163    'jamb_subjects',
164    'jamb_score',
165    'jamb_reg_number',
166    'aggregate'
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',
172      'alr_results', 'notice',
173      'nysc_year',
174      'nysc_location',
175      'nysc_lga',
176      'former_matric',
177      )
178PG_OMIT_MANAGE_FIELDS = (
179    'special_application','jamb_subjects_list',) + PG_OMIT_FIELDS
180PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
181    'student_id',
182    'notice',
183    )
184
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
219UPDATE_OMIT_FIELDS = (
220    'firstname',
221    'middlename',
222    'lastname',
223    'sex',
224    'lga',
225    'course1',
226    )
227
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
253class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
254    """A display view for applicant data.
255    """
256
257    @property
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="%s">Statement of Result</a>' % self.url(
264                self.context, 'stateresult.pdf')
265        pdf = getUtility(IExtFileStore).getFileByContext(
266            self.context, attr='verificationdoc.pdf')
267        if pdf:
268            html += '<a href="%s">Result/Certificate Document</a>' % self.url(
269                self.context, 'verificationdoc.pdf')
270        return html
271
272    @property
273    def form_fields(self):
274        if self.target is not None and self.target == 'trans':
275            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
276                'locked', 'suspended')
277            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
278            form_fields['perm_address'].custom_widget = BytesDisplayWidget
279            return form_fields
280        if self.target is not None and self.target == 'ver':
281            form_fields = grok.AutoFields(IVerificationRequest).omit(
282                'locked', 'suspended')
283            form_fields['body_address'].custom_widget = BytesDisplayWidget
284            return form_fields
285        if self.target is not None and self.target == 'send':
286            form_fields = grok.AutoFields(ISendByEmailRequest).omit(
287                'locked', 'suspended')
288            form_fields['body_address'].custom_widget = BytesDisplayWidget
289            return form_fields
290        if self.target is not None and self.target == 'cert':
291            form_fields = grok.AutoFields(ICertificateRequest).omit(
292                'locked', 'suspended')
293            #form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
294            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
295            return form_fields
296        # AAUE is using the same interface for all regular applications.
297        form_fields = grok.AutoFields(ICustomUGApplicant)
298        if self.target is not None and self.target.startswith('pg'):
299            for field in PG_OMIT_DISPLAY_FIELDS:
300                form_fields = form_fields.omit(field)
301        elif self.target is not None and self.target in ('ptee','dsh',):
302            for field in PTEE_OMIT_DISPLAY_FIELDS:
303                form_fields = form_fields.omit(field)
304        elif self.target is not None and self.target in ('bridge', 'ude',):
305            for field in UDE_OMIT_DISPLAY_FIELDS:
306                form_fields = form_fields.omit(field)
307        else:
308            for field in UG_OMIT_DISPLAY_FIELDS:
309                form_fields = form_fields.omit(field)
310        form_fields['perm_address'].custom_widget = BytesDisplayWidget
311        form_fields['notice'].custom_widget = BytesDisplayWidget
312        if not getattr(self.context, 'student_id'):
313            form_fields = form_fields.omit('student_id')
314        if not getattr(self.context, 'screening_score'):
315            form_fields = form_fields.omit('screening_score')
316        if not getattr(self.context, 'screening_venue') or \
317            self.context.state not in ('submitted', 'admitted', 'created'):
318            form_fields = form_fields.omit('screening_venue')
319        if not getattr(self.context, 'screening_date') or \
320            self.context.state not in ('submitted', 'admitted', 'created'):
321            form_fields = form_fields.omit('screening_date')
322        return form_fields
323
324    def getCourseAdmitted(self):
325        """Return link, title and code in html format to the certificate
326           admitted.
327        """
328        if self.layout.isApplicant():
329            return ''
330        course_admitted = self.context.course_admitted
331        if getattr(course_admitted, '__parent__',None):
332            url = self.url(course_admitted)
333            title = course_admitted.title
334            code = course_admitted.code
335            return '<a href="%s">%s - %s</a>' %(url,code,title)
336        return ''
337
338    #def update(self):
339    #    super(CustomApplicantDisplayFormPage, self).update()
340    #    #self.extraform_url = self.url(self.context, 'stateresult.pdf')
341    #    return
342
343class CustomPDFActionButton(PDFActionButton):
344
345    @property
346    def target_url(self):
347        if self.context.state in ('initialized', 'started', 'paid'):
348            # or self.context.special or self.view.target in ('trans', 'cert'):
349            return
350        return self.view.url(self.view.context, self.target)
351
352
353class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
354
355    column_two_fields = ('applicant_id', 'reg_number',
356        'firstname', 'middlename', 'lastname', 'sex', 'date_of_birth')
357    #two_columns_design_fields = [
358    #    'fst_sit_fname', 'fst_sit_no', 'fst_sit_date',
359    #    'fst_sit_type', 'fst_sit_results',
360    #    'scd_sit_fname', 'scd_sit_no', 'scd_sit_date',
361    #    'scd_sit_type', 'scd_sit_results']
362
363    def _getCourseAdmittedLink(self, view):
364        return None
365
366    def _getDeptAndFaculty(self):
367        return [None, None]
368
369    @property
370    def note(self):
371        note = getattr(self.context.__parent__, 'application_slip_notice', None)
372        if note:
373            return '<br /><br />' + note
374        if self.target is not None and self.target in (
375            'trans', 'cert', 'ver', 'send'):
376            return
377        if self.context.sex == 'm':
378            pronoun = 'he'
379        else:
380            pronoun = 'she'
381        return '''
382The applicant has acknowledged that, if discovered at any time that %s does not possess
383any of the qualifications which %s claims %s has obtained, %s will be expelled from the
384University not be re-admitted for the same or any other programme, even if %s has
385upgraded previous qualifications or possess additional qualifications.
386
387''' % (
388    pronoun, pronoun, pronoun, pronoun, pronoun)
389
390    @property
391    def form_fields(self):
392        # AAUE is using the same interface for all regular applications.
393        form_fields = grok.AutoFields(ICustomUGApplicant)
394        if self.target is not None and self.target.startswith('pg'):
395            for field in PG_OMIT_PDF_FIELDS:
396                form_fields = form_fields.omit(field)
397        elif self.target is not None and self.target in ('ptee', 'dsh',):
398            for field in PTEE_OMIT_PDF_FIELDS:
399                form_fields = form_fields.omit(field)
400        elif self.target is not None and self.target in ('bridge', 'ude',):
401            for field in UDE_OMIT_PDF_FIELDS:
402                form_fields = form_fields.omit(field)
403        elif self.target is not None and self.target == 'trans':
404            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
405                'locked', 'suspended')
406        elif self.target is not None and self.target == 'ver':
407            form_fields = grok.AutoFields(IVerificationRequest).omit(
408                'locked', 'suspended')
409        elif self.target is not None and self.target == 'send':
410            form_fields = grok.AutoFields(ISendByEmailRequest).omit(
411                'locked', 'suspended')
412        elif self.target is not None and self.target == 'cert':
413            form_fields = grok.AutoFields(ICertificateRequest).omit(
414                'locked', 'suspended')
415        else:
416            for field in UG_OMIT_PDF_FIELDS:
417                form_fields = form_fields.omit(field)
418        if not getattr(self.context, 'student_id'):
419            form_fields = form_fields.omit('student_id')
420        if not getattr(self.context, 'screening_score'):
421            form_fields = form_fields.omit('screening_score')
422        if not getattr(self.context, 'screening_venue'):
423            form_fields = form_fields.omit('screening_venue')
424        if not getattr(self.context, 'screening_date'):
425            form_fields = form_fields.omit('screening_date')
426        return form_fields
427
428class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
429    """A full edit view for applicant data.
430    """
431
432    @property
433    def form_fields(self):
434        if self.target is not None and self.target == 'trans':
435            form_fields = grok.AutoFields(ITranscriptApplicant)
436            form_fields['applicant_id'].for_display = True
437            return form_fields
438        if self.target is not None and self.target == 'cert':
439            form_fields = grok.AutoFields(ICertificateRequest)
440            form_fields['applicant_id'].for_display = True
441            return form_fields
442        if self.target is not None and self.target == 'ver':
443            form_fields = grok.AutoFields(IVerificationRequest)
444            form_fields['applicant_id'].for_display = True
445            return form_fields
446        if self.target is not None and self.target == 'send':
447            form_fields = grok.AutoFields(ISendByEmailRequest)
448            form_fields['applicant_id'].for_display = True
449            return form_fields
450        # AAUE is using the same interface for all regular applications.
451        form_fields = grok.AutoFields(ICustomUGApplicant)
452        if self.target is not None and self.target.startswith('pg'):
453            for field in PG_OMIT_MANAGE_FIELDS:
454                form_fields = form_fields.omit(field)
455        elif self.target is not None and self.target in ('ptee', 'dsh',):
456            for field in PTEE_OMIT_MANAGE_FIELDS:
457                form_fields = form_fields.omit(field)
458        elif self.target is not None and self.target in ('bridge', 'ude',):
459            for field in UDE_OMIT_MANAGE_FIELDS:
460                form_fields = form_fields.omit(field)
461        else:
462            for field in UG_OMIT_MANAGE_FIELDS:
463                form_fields = form_fields.omit(field)
464        form_fields['student_id'].for_display = True
465        form_fields['applicant_id'].for_display = True
466        return form_fields
467
468    def update(self):
469        super(CustomApplicantManageFormPage, self).update()
470        upload_stateresult = self.request.form.get('form.stateresult', None)
471        upload_verificationdoc = self.request.form.get('form.verificationdoc', None)
472        if upload_stateresult:
473            # We got a fresh stateresult upload
474            success = handle_file_upload(
475                upload_stateresult, self.context, self, attr='stateresult.pdf')
476            if success:
477                self.context.writeLogMessage(self, 'saved: stateresult')
478            else:
479                self.upload_success = False
480        if upload_verificationdoc:
481            # We got a fresh verificationdoc upload
482            success = handle_file_upload(
483                upload_verificationdoc, self.context, self, attr='verificationdoc.pdf')
484            if success:
485                self.context.writeLogMessage(self, 'saved: verificationdoc')
486            else:
487                self.upload_success = False
488        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
489        return
490
491class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
492    """An applicant-centered edit view for applicant data.
493    """
494
495    def unremovable(self, ticket):
496        return True
497
498    def dataNotComplete(self, data):
499        store = getUtility(IExtFileStore)
500        # Temporarily enable passport upload also for cert and trans
501        # applications.
502        if self.context.__parent__.with_picture:
503            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
504                return _('No passport picture uploaded.')
505            if not self.target[:4] in ('cert', 'tran') and \
506                not self.request.form.get('confirm_passport', False):
507                return _('Passport picture confirmation box not ticked.')
508        if self.target in ('trans', 'cert') and \
509            not store.getFileByContext(self.context, attr=u'stateresult.pdf'):
510            return _('No statement of result pdf file uploaded.')
511        if self.target in ('ver',) and \
512            not store.getFileByContext(self.context, attr=u'verificationdoc.pdf'):
513            return _('No pdf file uploaded.')
514
515        return False
516
517    # AAUE applicants never see the 'Remove Selected Tickets' button.
518    @property
519    def display_actions(self):
520        # If the form is unlocked, applicants are allowed to save the form
521        # and remove unused tickets.
522        actions = [[_('Save')], []]
523        # Only in state started they can also add tickets.
524        if self.context.state == STARTED:
525            actions = [[_('Save')],
526                [_('Add online payment ticket')]]
527        # In state paid, they can submit the data and further add tickets
528        # if the application is special.
529        elif self.context.special and self.context.state == PAID:
530            actions = [[_('Save'), _('Finally Submit')],
531                [_('Add online payment ticket')]]
532        elif self.context.state == PAID:
533            actions = [[_('Save'), _('Finally Submit')], []]
534        return actions
535
536    @property
537    def form_fields(self):
538        if self.target is not None and self.target == 'trans':
539            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
540                'locked', 'suspended')
541            form_fields['applicant_id'].for_display = True
542            form_fields['reg_number'].for_display = True
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['perm_address'].field.required = True
549            form_fields['dispatch_address'].field.required = True
550            form_fields['entry_mode'].field.required = True
551            form_fields['entry_session'].field.required = True
552            form_fields['end_session'].field.required = True
553            form_fields['course_studied'].field.required = True
554            return form_fields
555        if self.target is not None and self.target == 'cert':
556            form_fields = grok.AutoFields(ICertificateRequest).omit(
557                'locked', 'suspended')
558            form_fields['applicant_id'].for_display = True
559            form_fields['reg_number'].for_display = True
560            form_fields['place_of_birth'].field.required = True
561            form_fields['date_of_birth'].field.required = True
562            form_fields['nationality'].field.required = True
563            form_fields['email'].field.required = True
564            form_fields['phone'].field.required = True
565            form_fields['entry_session'].field.required = True
566            form_fields['end_session'].field.required = True
567            form_fields['course_studied'].field.required = True
568            form_fields['certificate_type'].field.required = True
569            # Additional omissions
570            if self.context.__parent__.code == 'cert5':
571                for field in ('firstname', 'middlename', 'lastname'):
572                    form_fields[field].for_display = True
573            return form_fields
574        if self.target is not None and self.target == 'ver':
575            form_fields = grok.AutoFields(IVerificationRequest).omit(
576                'locked', 'suspended')
577            form_fields['applicant_id'].for_display = True
578            return form_fields
579        if self.target is not None and self.target == 'send':
580            form_fields = grok.AutoFields(ISendByEmailRequest).omit(
581                'locked', 'suspended')
582            form_fields['applicant_id'].for_display = True
583            return form_fields
584        # AAUE is using the same interface for all regular applications.
585        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
586        if self.target is not None and self.target.startswith('pg'):
587            for field in PG_OMIT_EDIT_FIELDS:
588                form_fields = form_fields.omit(field)
589        elif self.target is not None and self.target in ('ptee','dsh',):
590            for field in PTEE_OMIT_EDIT_FIELDS:
591                form_fields = form_fields.omit(field)
592        elif self.target is not None and self.target in ('bridge', 'ude',):
593            for field in UDE_OMIT_EDIT_FIELDS:
594                form_fields = form_fields.omit(field)
595        else:
596            for field in UG_OMIT_EDIT_FIELDS:
597                form_fields = form_fields.omit(field)
598        # Additional omissions
599        if self.target is not None and self.target in ('ude', 'utme'):
600            for field in UPDATE_OMIT_FIELDS:
601                form_fields[field].for_display = True
602        form_fields['applicant_id'].for_display = True
603        form_fields['reg_number'].for_display = True
604        return form_fields
605
606    def update(self):
607        if self.context.locked or (
608            self.context.__parent__.expired and
609            self.context.__parent__.strict_deadline):
610            self.emit_lock_message()
611            return
612        if getattr(
613            self.context.course1, 'code', 'nocourse') == self.request.form.get(
614            'form.course2', None):
615            self.flash(_('2nd choice course must differ from 1st choice course.'),
616                       type='danger')
617            self.redirect(self.url(self.context))
618            return
619        if getattr(
620            self.context.course1, 'code', 'nocourse') == self.request.form.get(
621            'form.course3', None):
622            self.flash(_('3rd choice course must differ from 1st choice course.'),
623                       type='danger')
624            self.redirect(self.url(self.context))
625            return
626        super(CustomApplicantEditFormPage, self).update()
627        upload_stateresult = self.request.form.get('form.stateresult', None)
628        upload_verificationdoc = self.request.form.get('form.verificationdoc', None)
629        if upload_stateresult:
630            # We got a fresh stateresult upload
631            success = handle_file_upload(
632                upload_stateresult, self.context, self, attr='stateresult.pdf')
633            if not success:
634                self.upload_success = False
635        if upload_verificationdoc:
636            # We got a fresh verificationdoc upload
637            success = handle_file_upload(
638                upload_verificationdoc, self.context, self, attr='verificationdoc.pdf')
639            if not success:
640                self.upload_success = False
641        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
642        return
643
644class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
645    """Captcha'd registration page for applicants.
646    """
647
648    @property
649    def form_fields(self):
650        form_fields = None
651        if self.context.mode == 'update':
652            form_fields = grok.AutoFields(IApplicantRegisterUpdate).select(
653                'lastname','reg_number','email')
654            target = getattr(self.context, 'prefix', None)
655            if target in ('trans', 'cert'):
656                form_fields.get('reg_number').field.title = u'Matriculation Number'
657        else: #if self.context.mode == 'create':
658            form_fields = grok.AutoFields(ICustomUGApplicantEdit).select(
659                'firstname', 'middlename', 'lastname', 'email', 'phone')
660        return form_fields
661
662    def _redirect(self, email, password, applicant_id):
663        # Forward email and credentials to landing page.
664        self.redirect(self.url(self.context, 'registration_complete',
665            data = dict(email=email, password=password,
666            applicant_id=applicant_id)))
667        return
668
669    @property
670    def _postfix(self):
671        """Alumni records have to be imported into several containers.
672        Therefore a string must be added to their registration number
673        to make it unique.
674        """
675        if self.context.prefix in ('trans', 'cert'):
676            return self.context.code
677        return ''
678
679class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
680
681    @property
682    def payment_slip_download_warning(self):
683        return ''
684
685class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
686    """Captcha'd status checking page for applicants.
687    """
688    grok.template('applicantcheckstatus')
689
690class ScreeningInvitationActionButton(ManageActionButton):
691    grok.order(8) # This button should always be the last one.
692    grok.context(ICustomApplicant)
693    grok.view(CustomApplicantDisplayFormPage)
694    grok.require('waeup.viewApplication')
695    icon = 'actionicon_pdf.png'
696    text = _('Download screening invitation letter')
697    target = 'screening_invitation.pdf'
698
699    @property
700    def target_url(self):
701        if not self.context.screening_date or not self.context.state in (
702            'submitted', 'admitted', 'created'):
703            return ''
704        return self.view.url(self.view.context, self.target)
705
706class ExportScreeningInvitationLetter(UtilityView, grok.View):
707    """Deliver a slip with only screening data.
708    This form page is available only in AAUE.
709    """
710    grok.context(ICustomApplicant)
711    grok.name('screening_invitation.pdf')
712    grok.require('waeup.viewApplication')
713    prefix = 'form'
714
715    label = u'Screening Invitation Letter'
716
717    form_fields = []
718
719    @property
720    def note(self):
721        if self.context.screening_date:
722            year = self.context.__parent__.year
723            session = '%s/%s' % (year, year + 1)
724            sdate = self.context.screening_date
725            stime = ''
726            if '@' in self.context.screening_date:
727                sdate = self.context.screening_date.split('@')[0].strip()
728                stime = self.context.screening_date.split('@')[1].strip()
729            return """
730<br /><br /><br /><br /><font size='12'>
731Dear %s,
732<br /><br />
733You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
734<br /><br />
735<strong>Date: %s
736<br /><br />
737Time: %s
738<br /><br />
739Venue: %s
740</strong>
741<br /><br />
742Please bring this letter of invitation and the downloaded application form along with you on your screening date.
743<br /><br />
744You are expected to be available 30 minutes before the commencement of your Screening.
745</font>
746
747""" % (
748       self.context.display_fullname,
749       session,
750       sdate,
751       stime,
752       self.context.screening_venue)
753        return
754
755    @property
756    def title(self):
757        return None
758
759    def update(self):
760        if not self.context.screening_date or not self.context.state in (
761            'submitted', 'admitted', 'created'):
762            self.flash(_('Forbidden'), type="warning")
763            self.redirect(self.url(self.context))
764
765    def render(self):
766        applicantview = ApplicantBaseDisplayFormPage(self.context, self.request)
767        students_utils = getUtility(IStudentsUtils)
768        return students_utils.renderPDF(self,'screening_data.pdf',
769            self.context, applicantview, note=self.note)
770
771class StateResult(grok.View):
772    """Renders the pdf form extension for applicants.
773    """
774    grok.name('stateresult.pdf')
775    grok.context(ICustomApplicant)
776    grok.require('waeup.viewApplication')
777
778    def render(self):
779        pdf = getUtility(IExtFileStore).getFileByContext(
780            self.context, attr='stateresult.pdf')
781        self.response.setHeader('Content-Type', 'application/pdf')
782        return pdf
783
784class VerificationDoc(grok.View):
785    """Renders the pdf form extension for applicants.
786    """
787    grok.name('verificationdoc.pdf')
788    grok.context(ICustomApplicant)
789    grok.require('waeup.viewApplication')
790
791    def render(self):
792        pdf = getUtility(IExtFileStore).getFileByContext(
793            self.context, attr='verificationdoc.pdf')
794        self.response.setHeader('Content-Type', 'application/pdf')
795        return pdf
Note: See TracBrowser for help on using the repository browser.