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

Last change on this file since 17633 was 17632, checked in by Henrik Bettermann, 14 months ago

See ticket #773.

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