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

Last change on this file since 17808 was 17777, checked in by Henrik Bettermann, 5 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.