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

Last change on this file since 16672 was 16548, checked in by Henrik Bettermann, 3 years ago

Adjust to changes in base package.

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