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

Last change on this file since 18001 was 17777, checked in by Henrik Bettermann, 10 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
RevLine 
[10298]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
[13996]22from zope.component import getUtility, getAdapter
23from zope.i18n import translate
[15951]24from zope.catalog.interfaces import ICatalog
[14027]25from hurry.workflow.interfaces import IWorkflowState
[17632]26from zope.component import queryUtility
27from zope.catalog.interfaces import ICatalog
[10298]28from waeup.kofa.interfaces import (
[13996]29    IExtFileStore, IFileStoreNameChooser, IKofaUtils)
[10298]30from zope.formlib.textwidgets import BytesDisplayWidget
[16003]31from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
[10298]32from waeup.kofa.utils.helpers import string_from_bytes, file_size
[13996]33from waeup.kofa.applicants.browser import (
[16003]34    ApplicantCheckStatusPage,
[16786]35    AdditionalFile,
36    RefereeReportAddFormPage,
37    RefereeReportDisplayFormPage,
[16871]38    RefereeReportManageFormPage,
[16786]39    ExportPDFReportSlipPage,
40    ExportPDFReportSlipPage2)
[14027]41from waeup.kofa.applicants.workflow import STARTED, PAID
[13538]42from waeup.kofa.applicants.viewlets import PDFActionButton
[14460]43from waeup.kofa.applicants.interfaces import IApplicantRegisterUpdate
[15951]44from waeup.kofa.browser.layout import UtilityView, action
[13996]45from waeup.kofa.students.interfaces import IStudentsUtils
46from waeup.kofa.interfaces import IPDF
[13997]47from waeup.kofa.browser.viewlets import ManageActionButton
[10298]48from waeup.aaue.interfaces import MessageFactory as _
49from kofacustom.nigeria.applicants.browser import (
50    NigeriaApplicantDisplayFormPage,
51    NigeriaApplicantManageFormPage,
52    NigeriaApplicantEditFormPage,
53    NigeriaPDFApplicationSlip,
[10929]54    NigeriaApplicantRegistrationPage,
[11755]55    NigeriaExportPDFPaymentSlipPage,
[13545]56    )
57from kofacustom.nigeria.applicants.interfaces import OMIT_DISPLAY_FIELDS
[10298]58from waeup.aaue.applicants.interfaces import (
59    ICustomUGApplicant,
[16763]60    ICustomPGApplicant,
[13544]61    ICustomUGApplicantEdit,
[16763]62    ICustomPGApplicantEdit,
[13996]63    ITranscriptApplicant,
[14304]64    ICertificateRequest,
[15530]65    ICustomApplicant,
[15531]66    IVerificationRequest,
[15950]67    ISendByEmailRequest,
[15991]68    IFedexRequest,
69    IRecruitment,
[16003]70    ICustomApplicantOnlinePayment,
[16786]71    ICustomApplicantRefereeReport,
[17719]72    IResultReissuanceRequest,
[11291]73    )
[10298]74
[13545]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',
[13679]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',
[13545]96      )
[13546]97UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
[13977]98    'jamb_subjects_list', 'master_sheet_number') + UG_OMIT_FIELDS
[13545]99UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + UG_OMIT_FIELDS + (
[14363]100      'alr_fname', 'alr_no', 'alr_date',
[13545]101      'alr_results', 'notice')
[13546]102UG_OMIT_MANAGE_FIELDS = (
103    'special_application','jamb_subjects_list',) + UG_OMIT_FIELDS
104UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
[13545]105    'student_id',
106    'notice',
107    'jamb_age',
108    'jamb_subjects',
109    'jamb_score',
110    'jamb_reg_number',
[13679]111    'aggregate',
[13977]112    'master_sheet_number',
[13996]113    'screening_venue',
114    'screening_score',
115    'screening_date'
[13679]116    )
[10298]117
[14209]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 + (
[15091]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')
[14209]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
[13545]159#UG_OMIT_PDF_FIELDS = tuple([
160#    element for element in UG_OMIT_PDF_FIELDS if not element == 'phone'])
[11291]161
[13545]162#UG_OMIT_PDF_FIELDS += (
163#      'reg_number','alr_fname', 'alr_no', 'alr_date',
164#      'alr_results', 'notice'
165#      )
[13538]166
[13545]167PG_OMIT_FIELDS = (
[16763]168
[13545]169    )
170PG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
[16763]171    ) + PG_OMIT_FIELDS
[13545]172PG_OMIT_PDF_FIELDS = PG_OMIT_DISPLAY_FIELDS + PG_OMIT_FIELDS + (
[13679]173      )
[13545]174PG_OMIT_MANAGE_FIELDS = (
[16763]175    ) + PG_OMIT_FIELDS
[13546]176PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
177    )
[13545]178
[13679]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
[14150]213UPDATE_OMIT_FIELDS = (
214    'firstname',
215    'middlename',
216    'lastname',
217    'sex',
218    'lga',
219    'course1',
220    )
221
[15113]222MAX_FILE_UPLOAD_SIZE = 1024 * 500
223
[10298]224class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
225    """A display view for applicant data.
226    """
227
228    @property
229    def form_fields(self):
[13538]230        if self.target is not None and self.target == 'trans':
[13544]231            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
[14580]232                'locked', 'suspended')
[13544]233            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
234            form_fields['perm_address'].custom_widget = BytesDisplayWidget
235            return form_fields
[15530]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
[15950]241        if self.target is not None and self.target == 'fedex':
242            form_fields = grok.AutoFields(IFedexRequest).omit(
243                'locked', 'suspended')
[16003]244            return form_fields
[15991]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
[15994]249            form_fields['position'].custom_widget = BytesDisplayWidget
[15950]250            return form_fields
[15531]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
[17719]256        if self.target is not None and self.target == 'res':
257            form_fields = grok.AutoFields(IResultReissuanceRequest).omit(
[17777]258                'locked', 'suspended', 'request_type')
[17719]259            form_fields['body_address'].custom_widget = BytesDisplayWidget
260            return form_fields
[14304]261        if self.target is not None and self.target == 'cert':
262            form_fields = grok.AutoFields(ICertificateRequest).omit(
[14580]263                'locked', 'suspended')
[14304]264            return form_fields
[16763]265        if self.target is not None and self.target in ('ptee','dsh',):
266            form_fields = grok.AutoFields(ICustomUGApplicant)
[13679]267            for field in PTEE_OMIT_DISPLAY_FIELDS:
[10298]268                form_fields = form_fields.omit(field)
[15217]269        elif self.target is not None and self.target in ('bridge', 'ude',):
[16763]270            form_fields = grok.AutoFields(ICustomUGApplicant)
[14209]271            for field in UDE_OMIT_DISPLAY_FIELDS:
272                form_fields = form_fields.omit(field)
[16763]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)
[10298]277        else:
[16763]278            form_fields = grok.AutoFields(ICustomUGApplicant)
[10298]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')
[14840]285        if not getattr(self.context, 'screening_venue') or \
286            self.context.state not in ('submitted', 'admitted', 'created'):
[10298]287            form_fields = form_fields.omit('screening_venue')
[14840]288        if not getattr(self.context, 'screening_date') or \
289            self.context.state not in ('submitted', 'admitted', 'created'):
[10298]290            form_fields = form_fields.omit('screening_date')
291        return form_fields
292
[14371]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
[13538]307class CustomPDFActionButton(PDFActionButton):
308
309    @property
310    def target_url(self):
[15835]311        if self.context.state in ('initialized', 'started', 'paid'):
312            # or self.context.special or self.view.target in ('trans', 'cert'):
[13540]313            return
314        return self.view.url(self.view.context, self.target)
[13538]315
316
[10298]317class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
318
[10311]319    column_two_fields = ('applicant_id', 'reg_number',
320        'firstname', 'middlename', 'lastname', 'sex', 'date_of_birth')
[13679]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']
[10311]326
[14228]327    def _getCourseAdmittedLink(self, view):
328        return None
329
330    def _getDeptAndFaculty(self):
331        return [None, None]
332
[10301]333    @property
334    def note(self):
[14057]335        note = getattr(self.context.__parent__, 'application_slip_notice', None)
336        if note:
337            return '<br /><br />' + note
[15835]338        if self.target is not None and self.target in (
[16003]339            'trans', 'cert', 'ver', 'send', 'fedex'):
[15835]340            return
[10301]341        if self.context.sex == 'm':
342            pronoun = 'he'
343        else:
344            pronoun = 'she'
345        return '''
[10897]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
[14224]348University not be re-admitted for the same or any other programme, even if %s has
349upgraded previous qualifications or possess additional qualifications.
350
[10331]351''' % (
[10301]352    pronoun, pronoun, pronoun, pronoun, pronoun)
[10298]353
354    @property
355    def form_fields(self):
[13538]356        # AAUE is using the same interface for all regular applications.
[11291]357        form_fields = grok.AutoFields(ICustomUGApplicant)
[13538]358        if self.target is not None and self.target.startswith('pg'):
359            for field in PG_OMIT_PDF_FIELDS:
[16763]360                form_fields = grok.AutoFields(ICustomPGApplicant)
[13538]361                form_fields = form_fields.omit(field)
[15521]362        elif self.target is not None and self.target in ('ptee', 'dsh',):
[13679]363            for field in PTEE_OMIT_PDF_FIELDS:
[10298]364                form_fields = form_fields.omit(field)
[15217]365        elif self.target is not None and self.target in ('bridge', 'ude',):
[14209]366            for field in UDE_OMIT_PDF_FIELDS:
367                form_fields = form_fields.omit(field)
[15835]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')
[17719]377        if self.target is not None and self.target == 'res':
378            form_fields = grok.AutoFields(IResultReissuanceRequest).omit(
[17777]379                'locked', 'suspended', 'request_type')
[15835]380        elif self.target is not None and self.target == 'cert':
381            form_fields = grok.AutoFields(ICertificateRequest).omit(
382                'locked', 'suspended')
[16003]383        elif self.target is not None and self.target == 'fedex':
384            form_fields = grok.AutoFields(IFedexRequest).omit(
385                'locked', 'suspended')
[10298]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')
[16763]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')
[10298]411        return form_fields
412
413class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
414    """A full edit view for applicant data.
415    """
416
[15948]417    def display_fileupload(self, filename):
[16548]418        if filename[1] == 'stateresult':
[15948]419            if self.target in ('trans', 'cert'):
420                return True
[16548]421        if filename[1] == 'verificationdoc':
[15948]422            if self.target in ('ver', 'send'):
423                return True
424        return False
425
[10298]426    @property
427    def form_fields(self):
[13538]428        if self.target is not None and self.target == 'trans':
[13544]429            form_fields = grok.AutoFields(ITranscriptApplicant)
[13538]430            form_fields['applicant_id'].for_display = True
431            return form_fields
[14304]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
[15530]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
[15531]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
[17719]444        if self.target is not None and self.target == 'res':
[17777]445            form_fields = grok.AutoFields(IResultReissuanceRequest).omit(
446                'request_type')
[17719]447            form_fields['applicant_id'].for_display = True
448            return form_fields
[15950]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
[15991]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
[13538]457        # AAUE is using the same interface for all regular applications.
[11291]458        form_fields = grok.AutoFields(ICustomUGApplicant)
[13538]459        if self.target is not None and self.target.startswith('pg'):
[16763]460            form_fields = grok.AutoFields(ICustomPGApplicant)
[13538]461            for field in PG_OMIT_MANAGE_FIELDS:
462                form_fields = form_fields.omit(field)
[15521]463        elif self.target is not None and self.target in ('ptee', 'dsh',):
[13679]464            for field in PTEE_OMIT_MANAGE_FIELDS:
[10298]465                form_fields = form_fields.omit(field)
[15217]466        elif self.target is not None and self.target in ('bridge', 'ude',):
[14209]467            for field in UDE_OMIT_MANAGE_FIELDS:
468                form_fields = form_fields.omit(field)
[10298]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
[15948]480    def display_fileupload(self, filename):
[16548]481        if filename[1] == 'stateresult':
[15948]482            if self.target in ('trans', 'cert'):
483                return True
[16548]484        if filename[1] == 'verificationdoc':
[15948]485            if self.target in ('ver', 'send'):
486                return True
487        return False
488
[14027]489    def unremovable(self, ticket):
490        return True
491
[15639]492    def dataNotComplete(self, data):
[15099]493        store = getUtility(IExtFileStore)
[15265]494        # Temporarily enable passport upload also for cert and trans
495        # applications.
[17675]496        if self.picture_editable:
[15100]497            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
[15099]498                return _('No passport picture uploaded.')
[15991]499            if not self.target in ('cert', 'trans') and \
[15265]500                not self.request.form.get('confirm_passport', False):
[15099]501                return _('Passport picture confirmation box not ticked.')
[15132]502        if self.target in ('trans', 'cert') and \
[16548]503            not store.getFileByContext(self.context, attr=u'stateresult'):
[15113]504            return _('No statement of result pdf file uploaded.')
[15531]505        if self.target in ('ver',) and \
[16548]506            not store.getFileByContext(self.context, attr=u'verificationdoc'):
[15531]507            return _('No pdf file uploaded.')
[15954]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.')
[15099]514        return False
515
[14027]516    # AAUE applicants never see the 'Remove Selected Tickets' button.
[10298]517    @property
[14027]518    def display_actions(self):
519        # If the form is unlocked, applicants are allowed to save the form
[14029]520        # and remove unused tickets.
521        actions = [[_('Save')], []]
[14027]522        # Only in state started they can also add tickets.
[14822]523        if self.context.state == STARTED:
[14029]524            actions = [[_('Save')],
525                [_('Add online payment ticket')]]
[14027]526        # In state paid, they can submit the data and further add tickets
527        # if the application is special.
[14822]528        elif self.context.special and self.context.state == PAID:
[14027]529            actions = [[_('Save'), _('Finally Submit')],
[14029]530                [_('Add online payment ticket')]]
[14822]531        elif self.context.state == PAID:
[14029]532            actions = [[_('Save'), _('Finally Submit')], []]
[14027]533        return actions
534
535    @property
[10298]536    def form_fields(self):
[13538]537        if self.target is not None and self.target == 'trans':
[13544]538            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
539                'locked', 'suspended')
[13538]540            form_fields['applicant_id'].for_display = True
[14472]541            form_fields['reg_number'].for_display = True
[15276]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
[13538]553            return form_fields
[14304]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
[14472]558            form_fields['reg_number'].for_display = True
[15276]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
[14696]568            # Additional omissions
569            if self.context.__parent__.code == 'cert5':
570                for field in ('firstname', 'middlename', 'lastname'):
571                    form_fields[field].for_display = True
[14304]572            return form_fields
[15530]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
[15531]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
[17719]582        if self.target is not None and self.target == 'res':
583            form_fields = grok.AutoFields(IResultReissuanceRequest).omit(
[17777]584                'locked', 'suspended', 'request_type')
[17719]585            return form_fields
[15950]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
[15991]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
[13538]596        # AAUE is using the same interface for all regular applications.
[11291]597        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
[13538]598        if self.target is not None and self.target.startswith('pg'):
[16763]599            form_fields = grok.AutoFields(ICustomPGApplicantEdit)
[13538]600            for field in PG_OMIT_EDIT_FIELDS:
601                form_fields = form_fields.omit(field)
[16765]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
[16774]606            form_fields['notice'].for_display = True
[15521]607        elif self.target is not None and self.target in ('ptee','dsh',):
[13679]608            for field in PTEE_OMIT_EDIT_FIELDS:
[10298]609                form_fields = form_fields.omit(field)
[15217]610        elif self.target is not None and self.target in ('bridge', 'ude',):
[14209]611            for field in UDE_OMIT_EDIT_FIELDS:
612                form_fields = form_fields.omit(field)
[10298]613        else:
614            for field in UG_OMIT_EDIT_FIELDS:
615                form_fields = form_fields.omit(field)
[14150]616        # Additional omissions
[14696]617        if self.target is not None and self.target in ('ude', 'utme'):
[14150]618            for field in UPDATE_OMIT_FIELDS:
619                form_fields[field].for_display = True
[10298]620        form_fields['applicant_id'].for_display = True
621        form_fields['reg_number'].for_display = True
622        return form_fields
[10929]623
[15113]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
[17632]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')
[17638]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
[17632]661        if getattr(self.context.course1, 'code', 'nocourse') == course2_in_form:
[15459]662            self.flash(_('2nd choice course must differ from 1st choice course.'),
663                       type='danger')
664            self.redirect(self.url(self.context))
665            return
[17632]666        if getattr(self.context.course1, 'code', 'nocourse') == course3_in_form:
[15459]667            self.flash(_('3rd choice course must differ from 1st choice course.'),
668                       type='danger')
669            self.redirect(self.url(self.context))
670            return
[15113]671        super(CustomApplicantEditFormPage, self).update()
672        return
673
[10929]674class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
675    """Captcha'd registration page for applicants.
676    """
677
[14460]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')
[14465]684            target = getattr(self.context, 'prefix', None)
[14460]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
[10929]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)))
[11755]697        return
698
[14579]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
[16003]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
[11755]726class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
727
[16003]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
[11755]734    @property
735    def payment_slip_download_warning(self):
[13422]736        return ''
737
[16003]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
[13422]749class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
750    """Captcha'd status checking page for applicants.
751    """
752    grok.template('applicantcheckstatus')
[13996]753
[14822]754class ScreeningInvitationActionButton(ManageActionButton):
[13997]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'
[13996]762
[13997]763    @property
764    def target_url(self):
[14822]765        if not self.context.screening_date or not self.context.state in (
[14824]766            'submitted', 'admitted', 'created'):
[13997]767            return ''
768        return self.view.url(self.view.context, self.target)
769
[13996]770class ExportScreeningInvitationLetter(UtilityView, grok.View):
771    """Deliver a slip with only screening data.
772    This form page is available only in AAUE.
773    """
[13997]774    grok.context(ICustomApplicant)
[13996]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:
[13999]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()
[13996]793            return """
794<br /><br /><br /><br /><font size='12'>
795Dear %s,
796<br /><br />
[13999]797You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
[13996]798<br /><br />
[13999]799<strong>Date: %s
[13996]800<br /><br />
[13999]801Time: %s
802<br /><br />
[13997]803Venue: %s
804</strong>
[13996]805<br /><br />
[14015]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.
[13996]809</font>
810
[13999]811""" % (
812       self.context.display_fullname,
813       session,
814       sdate,
815       stime,
[13996]816       self.context.screening_venue)
817        return
818
819    @property
820    def title(self):
821        return None
822
823    def update(self):
[14822]824        if not self.context.screening_date or not self.context.state in (
[14824]825            'submitted', 'admitted', 'created'):
[13996]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',
[14015]833            self.context, applicantview, note=self.note)
[15113]834
[16786]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
[16871]849class CustomRefereeReportManageFormPage(RefereeReportManageFormPage):
850    """A displaymanage for referee reports.
851    """
852    form_fields = grok.AutoFields(ICustomApplicantRefereeReport).omit('creation_date')
853
[16786]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
[15948]864class StateResult(AdditionalFile):
[15113]865    """Renders the pdf form extension for applicants.
866    """
[16548]867    grok.name('stateresult')
[15113]868
[15948]869class VerificationDoc(AdditionalFile):
[15530]870    """Renders the pdf form extension for applicants.
871    """
[16548]872    grok.name('verificationdoc')
Note: See TracBrowser for help on using the repository browser.