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

Last change on this file since 16763 was 16763, checked in by Henrik Bettermann, 3 years ago

Implement new pg application form.

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