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

Last change on this file since 17754 was 17719, checked in by Henrik Bettermann, 7 months ago

Add new application form and change existing ones.

  • Property svn:keywords set to Id
File size: 35.3 KB
Line 
1## $Id: browser.py 17719 2024-03-15 12:57:36Z 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')
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')
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)
446            form_fields['applicant_id'].for_display = True
447            return form_fields
448        if self.target is not None and self.target == 'fedex':
449            form_fields = grok.AutoFields(IFedexRequest)
450            form_fields['applicant_id'].for_display = True
451            return form_fields
452        if self.target is not None and self.target == 'rec':
453            form_fields = grok.AutoFields(IRecruitment)
454            form_fields['applicant_id'].for_display = True
455            return form_fields
456        # AAUE is using the same interface for all regular applications.
457        form_fields = grok.AutoFields(ICustomUGApplicant)
458        if self.target is not None and self.target.startswith('pg'):
459            form_fields = grok.AutoFields(ICustomPGApplicant)
460            for field in PG_OMIT_MANAGE_FIELDS:
461                form_fields = form_fields.omit(field)
462        elif self.target is not None and self.target in ('ptee', 'dsh',):
463            for field in PTEE_OMIT_MANAGE_FIELDS:
464                form_fields = form_fields.omit(field)
465        elif self.target is not None and self.target in ('bridge', 'ude',):
466            for field in UDE_OMIT_MANAGE_FIELDS:
467                form_fields = form_fields.omit(field)
468        else:
469            for field in UG_OMIT_MANAGE_FIELDS:
470                form_fields = form_fields.omit(field)
471        form_fields['student_id'].for_display = True
472        form_fields['applicant_id'].for_display = True
473        return form_fields
474
475class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
476    """An applicant-centered edit view for applicant data.
477    """
478
479    def display_fileupload(self, filename):
480        if filename[1] == 'stateresult':
481            if self.target in ('trans', 'cert'):
482                return True
483        if filename[1] == 'verificationdoc':
484            if self.target in ('ver', 'send'):
485                return True
486        return False
487
488    def unremovable(self, ticket):
489        return True
490
491    def dataNotComplete(self, data):
492        store = getUtility(IExtFileStore)
493        # Temporarily enable passport upload also for cert and trans
494        # applications.
495        if self.picture_editable:
496            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
497                return _('No passport picture uploaded.')
498            if not self.target in ('cert', 'trans') and \
499                not self.request.form.get('confirm_passport', False):
500                return _('Passport picture confirmation box not ticked.')
501        if self.target in ('trans', 'cert') and \
502            not store.getFileByContext(self.context, attr=u'stateresult'):
503            return _('No statement of result pdf file uploaded.')
504        if self.target in ('ver',) and \
505            not store.getFileByContext(self.context, attr=u'verificationdoc'):
506            return _('No pdf file uploaded.')
507        if self.target == 'fedex':
508            cat = getUtility(ICatalog, name='applicants_catalog')
509            results = list(cat.searchResults(
510                applicant_id=(data['trans_id'], data['trans_id'])))
511            if not results:
512                return _('The transcript application id does not exist.')
513        return False
514
515    # AAUE applicants never see the 'Remove Selected Tickets' button.
516    @property
517    def display_actions(self):
518        # If the form is unlocked, applicants are allowed to save the form
519        # and remove unused tickets.
520        actions = [[_('Save')], []]
521        # Only in state started they can also add tickets.
522        if self.context.state == STARTED:
523            actions = [[_('Save')],
524                [_('Add online payment ticket')]]
525        # In state paid, they can submit the data and further add tickets
526        # if the application is special.
527        elif self.context.special and self.context.state == PAID:
528            actions = [[_('Save'), _('Finally Submit')],
529                [_('Add online payment ticket')]]
530        elif self.context.state == PAID:
531            actions = [[_('Save'), _('Finally Submit')], []]
532        return actions
533
534    @property
535    def form_fields(self):
536        if self.target is not None and self.target == 'trans':
537            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
538                'locked', 'suspended')
539            form_fields['applicant_id'].for_display = True
540            form_fields['reg_number'].for_display = True
541            form_fields['place_of_birth'].field.required = True
542            form_fields['date_of_birth'].field.required = True
543            form_fields['nationality'].field.required = True
544            form_fields['email'].field.required = True
545            form_fields['phone'].field.required = True
546            form_fields['perm_address'].field.required = True
547            form_fields['dispatch_address'].field.required = True
548            form_fields['entry_mode'].field.required = True
549            form_fields['entry_session'].field.required = True
550            form_fields['end_session'].field.required = True
551            form_fields['course_studied'].field.required = True
552            return form_fields
553        if self.target is not None and self.target == 'cert':
554            form_fields = grok.AutoFields(ICertificateRequest).omit(
555                'locked', 'suspended')
556            form_fields['applicant_id'].for_display = True
557            form_fields['reg_number'].for_display = True
558            form_fields['place_of_birth'].field.required = True
559            form_fields['date_of_birth'].field.required = True
560            form_fields['nationality'].field.required = True
561            form_fields['email'].field.required = True
562            form_fields['phone'].field.required = True
563            form_fields['entry_session'].field.required = True
564            form_fields['end_session'].field.required = True
565            form_fields['course_studied'].field.required = True
566            form_fields['certificate_type'].field.required = True
567            # Additional omissions
568            if self.context.__parent__.code == 'cert5':
569                for field in ('firstname', 'middlename', 'lastname'):
570                    form_fields[field].for_display = True
571            return form_fields
572        if self.target is not None and self.target == 'ver':
573            form_fields = grok.AutoFields(IVerificationRequest).omit(
574                'locked', 'suspended')
575            form_fields['applicant_id'].for_display = True
576            return form_fields
577        if self.target is not None and self.target == 'send':
578            form_fields = grok.AutoFields(ISendByEmailRequest).omit(
579                'locked', 'suspended')
580            return form_fields
581        if self.target is not None and self.target == 'res':
582            form_fields = grok.AutoFields(IResultReissuanceRequest).omit(
583                'locked', 'suspended')
584            return form_fields
585        if self.target is not None and self.target == 'fedex':
586            form_fields = grok.AutoFields(IFedexRequest).omit(
587                'locked', 'suspended')
588            form_fields['applicant_id'].for_display = True
589            return form_fields
590        if self.target is not None and self.target == 'rec':
591            form_fields = grok.AutoFields(IRecruitment).omit(
592                'locked', 'suspended')
593            form_fields['applicant_id'].for_display = True
594            return form_fields
595        # AAUE is using the same interface for all regular applications.
596        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
597        if self.target is not None and self.target.startswith('pg'):
598            form_fields = grok.AutoFields(ICustomPGApplicantEdit)
599            for field in PG_OMIT_EDIT_FIELDS:
600                form_fields = form_fields.omit(field)
601            form_fields['screening_venue'].for_display = True
602            form_fields['screening_date'].for_display = True
603            form_fields['screening_score'].for_display = True
604            form_fields['student_id'].for_display = True
605            form_fields['notice'].for_display = True
606        elif self.target is not None and self.target in ('ptee','dsh',):
607            for field in PTEE_OMIT_EDIT_FIELDS:
608                form_fields = form_fields.omit(field)
609        elif self.target is not None and self.target in ('bridge', 'ude',):
610            for field in UDE_OMIT_EDIT_FIELDS:
611                form_fields = form_fields.omit(field)
612        else:
613            for field in UG_OMIT_EDIT_FIELDS:
614                form_fields = form_fields.omit(field)
615        # Additional omissions
616        if self.target is not None and self.target in ('ude', 'utme'):
617            for field in UPDATE_OMIT_FIELDS:
618                form_fields[field].for_display = True
619        form_fields['applicant_id'].for_display = True
620        form_fields['reg_number'].for_display = True
621        return form_fields
622
623    def update(self):
624        if self.context.locked or (
625            self.context.__parent__.expired and
626            self.context.__parent__.strict_deadline):
627            self.emit_lock_message()
628            return
629        course1_in_form = self.request.form.get('form.course1', None)
630        course2_in_form = self.request.form.get('form.course2', None)
631        course3_in_form = self.request.form.get('form.course3', None)
632        cat = queryUtility(ICatalog, name='certificates_catalog')
633        if self.target is not None and self.target == 'utme':
634            if course2_in_form:
635                if  not self.context.jamb_score:
636                    self.flash(("Total JAMB score not set."), type='danger')
637                    self.redirect(self.url(self.context))
638                    return
639                results = list(
640                    cat.searchResults(code=(course2_in_form, course2_in_form)))
641                cutoff = getattr(results[0], 'custom_float_1')
642                if cutoff and cutoff > self.context.jamb_score:
643                    self.flash("You do not meet the minimum cutoff mark for your 2nd choice course. Please consider selecting an alternative choice.",
644                        type='danger')
645                    self.redirect(self.url(self.context))
646                    return
647            if course3_in_form:
648                if  not self.context.jamb_score:
649                    self.flash(("Total JAMB score not set."), type='danger')
650                    self.redirect(self.url(self.context))
651                    return
652                results = list(
653                    cat.searchResults(code=(course3_in_form, course3_in_form)))
654                cutoff = getattr(results[0], 'custom_float_1')
655                if cutoff and cutoff > self.context.jamb_score:
656                    self.flash("You do not meet the minimum cutoff mark for your 3rd choice course. Please consider selecting an alternative choice.",
657                        type='danger')
658                    self.redirect(self.url(self.context))
659                    return
660        if getattr(self.context.course1, 'code', 'nocourse') == course2_in_form:
661            self.flash(_('2nd choice course must differ from 1st choice course.'),
662                       type='danger')
663            self.redirect(self.url(self.context))
664            return
665        if getattr(self.context.course1, 'code', 'nocourse') == course3_in_form:
666            self.flash(_('3rd choice course must differ from 1st choice course.'),
667                       type='danger')
668            self.redirect(self.url(self.context))
669            return
670        super(CustomApplicantEditFormPage, self).update()
671        return
672
673class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
674    """Captcha'd registration page for applicants.
675    """
676
677    @property
678    def form_fields(self):
679        form_fields = None
680        if self.context.mode == 'update':
681            form_fields = grok.AutoFields(IApplicantRegisterUpdate).select(
682                'lastname','reg_number','email')
683            target = getattr(self.context, 'prefix', None)
684            if target in ('trans', 'cert'):
685                form_fields.get('reg_number').field.title = u'Matriculation Number'
686        else: #if self.context.mode == 'create':
687            form_fields = grok.AutoFields(ICustomUGApplicantEdit).select(
688                'firstname', 'middlename', 'lastname', 'email', 'phone')
689        return form_fields
690
691    def _redirect(self, email, password, applicant_id):
692        # Forward email and credentials to landing page.
693        self.redirect(self.url(self.context, 'registration_complete',
694            data = dict(email=email, password=password,
695            applicant_id=applicant_id)))
696        return
697
698    @property
699    def _postfix(self):
700        """Alumni records have to be imported into several containers.
701        Therefore a string must be added to their registration number
702        to make it unique.
703        """
704        if self.context.prefix in ('trans', 'cert'):
705            return self.context.code
706        return ''
707
708class ApplicantBaseDisplayFormPage(CustomApplicantDisplayFormPage):
709    grok.context(ICustomApplicant)
710    grok.name('base')
711
712    @property
713    def form_fields(self):
714        if self.context.__parent__.prefix in ('fedex',):
715            form_fields = grok.AutoFields(IFedexRequest).select(
716                'applicant_id', 'trans_id', 'email',)
717        else:
718            form_fields = grok.AutoFields(ICustomApplicant).select(
719                'applicant_id', 'reg_number', 'email', 'course1')
720        if self.context.__parent__.prefix in ('special',):
721            form_fields['reg_number'].field.title = u'Identification Number'
722            return form_fields
723        return form_fields
724
725class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
726
727    form_fields = grok.AutoFields(ICustomApplicantOnlinePayment).omit(
728        'ac', 'provider_amt', 'gateway_amt', 'thirdparty_amt', 'p_item',
729        'p_split_data')
730    form_fields['creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
731    form_fields['payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
732
733    @property
734    def payment_slip_download_warning(self):
735        return ''
736
737    def render(self):
738        if self.payment_slip_download_warning:
739            self.flash(self.payment_slip_download_warning, type='danger')
740            self.redirect(self.url(self.context))
741            return
742        applicantview = ApplicantBaseDisplayFormPage(self.context.__parent__,
743            self.request)
744        students_utils = getUtility(IStudentsUtils)
745        return students_utils.renderPDF(self,'payment_slip.pdf',
746            self.context.__parent__, applicantview, note=self.note)
747
748class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
749    """Captcha'd status checking page for applicants.
750    """
751    grok.template('applicantcheckstatus')
752
753class ScreeningInvitationActionButton(ManageActionButton):
754    grok.order(8) # This button should always be the last one.
755    grok.context(ICustomApplicant)
756    grok.view(CustomApplicantDisplayFormPage)
757    grok.require('waeup.viewApplication')
758    icon = 'actionicon_pdf.png'
759    text = _('Download screening invitation letter')
760    target = 'screening_invitation.pdf'
761
762    @property
763    def target_url(self):
764        if not self.context.screening_date or not self.context.state in (
765            'submitted', 'admitted', 'created'):
766            return ''
767        return self.view.url(self.view.context, self.target)
768
769class ExportScreeningInvitationLetter(UtilityView, grok.View):
770    """Deliver a slip with only screening data.
771    This form page is available only in AAUE.
772    """
773    grok.context(ICustomApplicant)
774    grok.name('screening_invitation.pdf')
775    grok.require('waeup.viewApplication')
776    prefix = 'form'
777
778    label = u'Screening Invitation Letter'
779
780    form_fields = []
781
782    @property
783    def note(self):
784        if self.context.screening_date:
785            year = self.context.__parent__.year
786            session = '%s/%s' % (year, year + 1)
787            sdate = self.context.screening_date
788            stime = ''
789            if '@' in self.context.screening_date:
790                sdate = self.context.screening_date.split('@')[0].strip()
791                stime = self.context.screening_date.split('@')[1].strip()
792            return """
793<br /><br /><br /><br /><font size='12'>
794Dear %s,
795<br /><br />
796You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
797<br /><br />
798<strong>Date: %s
799<br /><br />
800Time: %s
801<br /><br />
802Venue: %s
803</strong>
804<br /><br />
805Please bring this letter of invitation and the downloaded application form along with you on your screening date.
806<br /><br />
807You are expected to be available 30 minutes before the commencement of your Screening.
808</font>
809
810""" % (
811       self.context.display_fullname,
812       session,
813       sdate,
814       stime,
815       self.context.screening_venue)
816        return
817
818    @property
819    def title(self):
820        return None
821
822    def update(self):
823        if not self.context.screening_date or not self.context.state in (
824            'submitted', 'admitted', 'created'):
825            self.flash(_('Forbidden'), type="warning")
826            self.redirect(self.url(self.context))
827
828    def render(self):
829        applicantview = ApplicantBaseDisplayFormPage(self.context, self.request)
830        students_utils = getUtility(IStudentsUtils)
831        return students_utils.renderPDF(self,'screening_data.pdf',
832            self.context, applicantview, note=self.note)
833
834class CustomRefereeReportAddFormPage(RefereeReportAddFormPage):
835    """Add-form to add an referee report. This form
836    is protected by a mandate.
837    """
838    form_fields = grok.AutoFields(
839        ICustomApplicantRefereeReport).omit('creation_date')
840
841class CustomRefereeReportDisplayFormPage(RefereeReportDisplayFormPage):
842    """A display view for referee reports.
843    """
844    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
845    form_fields[
846        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
847
848class CustomRefereeReportManageFormPage(RefereeReportManageFormPage):
849    """A displaymanage for referee reports.
850    """
851    form_fields = grok.AutoFields(ICustomApplicantRefereeReport).omit('creation_date')
852
853class CustomExportPDFReportSlipPage(ExportPDFReportSlipPage):
854    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
855    form_fields[
856        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
857
858class CustomExportPDFReportSlipPage2(ExportPDFReportSlipPage2):
859    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
860    form_fields[
861        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
862
863class StateResult(AdditionalFile):
864    """Renders the pdf form extension for applicants.
865    """
866    grok.name('stateresult')
867
868class VerificationDoc(AdditionalFile):
869    """Renders the pdf form extension for applicants.
870    """
871    grok.name('verificationdoc')
Note: See TracBrowser for help on using the repository browser.