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

Last change on this file since 17814 was 17777, checked in by Henrik Bettermann, 8 months ago

send and res applications were using the same interface (field definitions) but res applications have different set of request types.

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