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

Last change on this file since 14557 was 14486, checked in by Henrik Bettermann, 8 years ago

Make some fields required and hide reg_number on display page.

  • Property svn:keywords set to Id
File size: 20.0 KB
Line 
1## $Id: browser.py 14486 2017-02-01 06:46:52Z 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 hurry.workflow.interfaces import IWorkflowState
25from waeup.kofa.interfaces import (
26    IExtFileStore, IFileStoreNameChooser, IKofaUtils)
27from zope.formlib.textwidgets import BytesDisplayWidget
28from waeup.kofa.utils.helpers import string_from_bytes, file_size
29from waeup.kofa.applicants.browser import (
30    ApplicantCheckStatusPage, ApplicantBaseDisplayFormPage)
31from waeup.kofa.applicants.workflow import STARTED, PAID
32from waeup.kofa.applicants.viewlets import PDFActionButton
33from waeup.kofa.applicants.interfaces import IApplicantRegisterUpdate
34from waeup.kofa.browser.layout import UtilityView
35from waeup.kofa.students.interfaces import IStudentsUtils
36from waeup.kofa.interfaces import IPDF
37from waeup.kofa.browser.viewlets import ManageActionButton
38from waeup.aaue.interfaces import MessageFactory as _
39from kofacustom.nigeria.applicants.browser import (
40    NigeriaApplicantDisplayFormPage,
41    NigeriaApplicantManageFormPage,
42    NigeriaApplicantEditFormPage,
43    NigeriaPDFApplicationSlip,
44    NigeriaApplicantRegistrationPage,
45    NigeriaExportPDFPaymentSlipPage,
46    )
47from kofacustom.nigeria.applicants.interfaces import OMIT_DISPLAY_FIELDS
48from waeup.aaue.applicants.interfaces import (
49    ICustomUGApplicant,
50    ICustomUGApplicantEdit,
51    ITranscriptApplicant,
52    ICertificateRequest,
53    ICustomApplicant
54    )
55
56UG_OMIT_FIELDS = (
57      'hq_type', 'hq_fname', 'hq_matric_no',
58      'hq_degree', 'hq_school', 'hq_session', 'hq_disc',
59      'hq_type2', 'hq_fname2', 'hq_matric_no2',
60      'hq_degree2', 'hq_school2', 'hq_session2', 'hq_disc2',
61      'hq_type3', 'hq_fname3', 'hq_matric_no3',
62      'hq_degree3', 'hq_school3', 'hq_session3', 'hq_disc3',
63      'nysc_year',
64      'nysc_location',
65      'nysc_lga',
66      'employer',
67      'emp_position',
68      'emp_start',
69      'emp_end',
70      'emp_reason',
71      'employer2',
72      'emp2_position',
73      'emp2_start',
74      'emp2_end',
75      'emp2_reason',
76      'former_matric',
77      )
78UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
79    'jamb_subjects_list', 'master_sheet_number') + UG_OMIT_FIELDS
80UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + UG_OMIT_FIELDS + (
81      'alr_fname', 'alr_no', 'alr_date',
82      'alr_results', 'notice')
83UG_OMIT_MANAGE_FIELDS = (
84    'special_application','jamb_subjects_list',) + UG_OMIT_FIELDS
85UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
86    'student_id',
87    'notice',
88    'jamb_age',
89    'jamb_subjects',
90    'jamb_score',
91    'jamb_reg_number',
92    'aggregate',
93    'master_sheet_number',
94    'screening_venue',
95    'screening_score',
96    'screening_date'
97    )
98
99UDE_OMIT_FIELDS = (
100      'nysc_year',
101      'nysc_location',
102      'nysc_lga',
103      'employer',
104      'emp_position',
105      'emp_start',
106      'emp_end',
107      'emp_reason',
108      'employer2',
109      'emp2_position',
110      'emp2_start',
111      'emp2_end',
112      'emp2_reason',
113      'former_matric',
114      )
115UDE_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
116    'jamb_subjects_list', 'master_sheet_number') + UDE_OMIT_FIELDS
117UDE_OMIT_PDF_FIELDS = UDE_OMIT_DISPLAY_FIELDS + UDE_OMIT_FIELDS + (
118      'alr_fname', 'alr_no', 'alr_date',
119      'alr_results', 'notice')
120UDE_OMIT_MANAGE_FIELDS = (
121    'special_application','jamb_subjects_list',) + UDE_OMIT_FIELDS
122UDE_OMIT_EDIT_FIELDS = UDE_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
123    'student_id',
124    'notice',
125    'jamb_age',
126    'jamb_subjects',
127    'jamb_score',
128    'jamb_reg_number',
129    'aggregate',
130    'master_sheet_number',
131    'screening_venue',
132    'screening_score',
133    'screening_date'
134    )
135
136#UG_OMIT_PDF_FIELDS = tuple([
137#    element for element in UG_OMIT_PDF_FIELDS if not element == 'phone'])
138
139#UG_OMIT_PDF_FIELDS += (
140#      'reg_number','alr_fname', 'alr_no', 'alr_date',
141#      'alr_results', 'notice'
142#      )
143
144PG_OMIT_FIELDS = (
145    'fst_sit_fname',
146    'fst_sit_no',
147    'fst_sit_date',
148    'fst_sit_type',
149    'fst_sit_results',
150    'scd_sit_fname',
151    'scd_sit_no',
152    'scd_sit_date',
153    'scd_sit_type',
154    'scd_sit_results',
155    #'programme_type',
156    'jamb_age',
157    'jamb_subjects',
158    'jamb_score',
159    'jamb_reg_number',
160    'aggregate'
161    )
162PG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
163    'jamb_subjects_list',) + PG_OMIT_FIELDS
164PG_OMIT_PDF_FIELDS = PG_OMIT_DISPLAY_FIELDS + PG_OMIT_FIELDS + (
165      'reg_number','alr_fname', 'alr_no', 'alr_date',
166      'alr_results', 'notice',
167      'nysc_year',
168      'nysc_location',
169      'nysc_lga',
170      'former_matric',
171      )
172PG_OMIT_MANAGE_FIELDS = (
173    'special_application','jamb_subjects_list',) + PG_OMIT_FIELDS
174PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
175    'student_id',
176    'notice',
177    )
178
179PTEE_OMIT_FIELDS = (
180    'jamb_age',
181    'jamb_subjects',
182    'jamb_score',
183    'jamb_reg_number',
184    'aggregate'
185    )
186PTEE_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
187    'jamb_subjects_list',) + PTEE_OMIT_FIELDS
188PTEE_OMIT_PDF_FIELDS = PTEE_OMIT_DISPLAY_FIELDS + PTEE_OMIT_FIELDS + (
189      'reg_number','alr_fname', 'alr_no', 'alr_date',
190      'alr_results', 'notice',
191      'nysc_year',
192      'nysc_location',
193      'nysc_lga',
194      'employer',
195      'emp_position',
196      'emp_start',
197      'emp_end',
198      'emp_reason',
199      'employer2',
200      'emp2_position',
201      'emp2_start',
202      'emp2_end',
203      'emp2_reason',
204      'former_matric',
205    )
206PTEE_OMIT_MANAGE_FIELDS = (
207    'special_application','jamb_subjects_list',) + PTEE_OMIT_FIELDS
208PTEE_OMIT_EDIT_FIELDS = PTEE_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
209    'student_id',
210    'notice',
211    )
212
213UPDATE_OMIT_FIELDS = (
214    'firstname',
215    'middlename',
216    'lastname',
217    'sex',
218    'lga',
219    'course1',
220    )
221
222class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
223    """A display view for applicant data.
224    """
225
226    @property
227    def form_fields(self):
228        if self.target is not None and self.target == 'trans':
229            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
230                'locked', 'suspended', 'reg_number')
231            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
232            form_fields['perm_address'].custom_widget = BytesDisplayWidget
233            return form_fields
234        if self.target is not None and self.target == 'cert':
235            form_fields = grok.AutoFields(ICertificateRequest).omit(
236                'locked', 'suspended', 'reg_number')
237            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
238            form_fields['perm_address'].custom_widget = BytesDisplayWidget
239            return form_fields
240        # AAUE is using the same interface for all regular applications.
241        form_fields = grok.AutoFields(ICustomUGApplicant)
242        if self.target is not None and self.target.startswith('pg'):
243            for field in PG_OMIT_DISPLAY_FIELDS:
244                form_fields = form_fields.omit(field)
245        elif self.target is not None and self.target in ('ptee',):
246            for field in PTEE_OMIT_DISPLAY_FIELDS:
247                form_fields = form_fields.omit(field)
248        elif self.target is not None and self.target in ('ude',):
249            for field in UDE_OMIT_DISPLAY_FIELDS:
250                form_fields = form_fields.omit(field)
251        else:
252            for field in UG_OMIT_DISPLAY_FIELDS:
253                form_fields = form_fields.omit(field)
254        form_fields['perm_address'].custom_widget = BytesDisplayWidget
255        form_fields['notice'].custom_widget = BytesDisplayWidget
256        if not getattr(self.context, 'student_id'):
257            form_fields = form_fields.omit('student_id')
258        if not getattr(self.context, 'screening_score'):
259            form_fields = form_fields.omit('screening_score')
260        if not getattr(self.context, 'screening_venue'):
261            form_fields = form_fields.omit('screening_venue')
262        if not getattr(self.context, 'screening_date'):
263            form_fields = form_fields.omit('screening_date')
264        return form_fields
265
266    def getCourseAdmitted(self):
267        """Return link, title and code in html format to the certificate
268           admitted.
269        """
270        if self.layout.isApplicant():
271            return ''
272        course_admitted = self.context.course_admitted
273        if getattr(course_admitted, '__parent__',None):
274            url = self.url(course_admitted)
275            title = course_admitted.title
276            code = course_admitted.code
277            return '<a href="%s">%s - %s</a>' %(url,code,title)
278        return ''
279
280class CustomPDFActionButton(PDFActionButton):
281
282    @property
283    def target_url(self):
284        if self.context.state in ('initialized', 'started', 'paid') \
285            or self.context.special or self.view.target in ('trans', 'cert'):
286            return
287        return self.view.url(self.view.context, self.target)
288
289
290class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
291
292    column_two_fields = ('applicant_id', 'reg_number',
293        'firstname', 'middlename', 'lastname', 'sex', 'date_of_birth')
294    #two_columns_design_fields = [
295    #    'fst_sit_fname', 'fst_sit_no', 'fst_sit_date',
296    #    'fst_sit_type', 'fst_sit_results',
297    #    'scd_sit_fname', 'scd_sit_no', 'scd_sit_date',
298    #    'scd_sit_type', 'scd_sit_results']
299
300
301    def _getCourseAdmittedLink(self, view):
302        return None
303
304    def _getDeptAndFaculty(self):
305        return [None, None]
306
307    @property
308    def note(self):
309        note = getattr(self.context.__parent__, 'application_slip_notice', None)
310        if note:
311            return '<br /><br />' + note
312        if self.context.sex == 'm':
313            pronoun = 'he'
314        else:
315            pronoun = 'she'
316        return '''
317The applicant has acknowledged that, if discovered at any time that %s does not possess
318any of the qualifications which %s claims %s has obtained, %s will be expelled from the
319University not be re-admitted for the same or any other programme, even if %s has
320upgraded previous qualifications or possess additional qualifications.
321
322''' % (
323    pronoun, pronoun, pronoun, pronoun, pronoun)
324
325    @property
326    def form_fields(self):
327        # AAUE is using the same interface for all regular applications.
328        form_fields = grok.AutoFields(ICustomUGApplicant)
329        if self.target is not None and self.target.startswith('pg'):
330            for field in PG_OMIT_PDF_FIELDS:
331                form_fields = form_fields.omit(field)
332        elif self.target is not None and self.target in ('ptee',):
333            for field in PTEE_OMIT_PDF_FIELDS:
334                form_fields = form_fields.omit(field)
335        elif self.target is not None and self.target in ('ude',):
336            for field in UDE_OMIT_PDF_FIELDS:
337                form_fields = form_fields.omit(field)
338        else:
339            for field in UG_OMIT_PDF_FIELDS:
340                form_fields = form_fields.omit(field)
341        if not getattr(self.context, 'student_id'):
342            form_fields = form_fields.omit('student_id')
343        if not getattr(self.context, 'screening_score'):
344            form_fields = form_fields.omit('screening_score')
345        if not getattr(self.context, 'screening_venue'):
346            form_fields = form_fields.omit('screening_venue')
347        if not getattr(self.context, 'screening_date'):
348            form_fields = form_fields.omit('screening_date')
349        return form_fields
350
351class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
352    """A full edit view for applicant data.
353    """
354
355    @property
356    def form_fields(self):
357        if self.target is not None and self.target == 'trans':
358            form_fields = grok.AutoFields(ITranscriptApplicant)
359            form_fields['applicant_id'].for_display = True
360            return form_fields
361        if self.target is not None and self.target == 'cert':
362            form_fields = grok.AutoFields(ICertificateRequest)
363            form_fields['applicant_id'].for_display = True
364            return form_fields
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_MANAGE_FIELDS:
369                form_fields = form_fields.omit(field)
370        elif self.target is not None and self.target in ('ptee',):
371            for field in PTEE_OMIT_MANAGE_FIELDS:
372                form_fields = form_fields.omit(field)
373        elif self.target is not None and self.target in ('ude',):
374            for field in UDE_OMIT_MANAGE_FIELDS:
375                form_fields = form_fields.omit(field)
376        else:
377            for field in UG_OMIT_MANAGE_FIELDS:
378                form_fields = form_fields.omit(field)
379        form_fields['student_id'].for_display = True
380        form_fields['applicant_id'].for_display = True
381        return form_fields
382
383class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
384    """An applicant-centered edit view for applicant data.
385    """
386
387    def unremovable(self, ticket):
388        return True
389
390    # AAUE applicants never see the 'Remove Selected Tickets' button.
391    @property
392    def display_actions(self):
393        state = IWorkflowState(self.context).getState()
394        # If the form is unlocked, applicants are allowed to save the form
395        # and remove unused tickets.
396        actions = [[_('Save')], []]
397        # Only in state started they can also add tickets.
398        if state == STARTED:
399            actions = [[_('Save')],
400                [_('Add online payment ticket')]]
401        # In state paid, they can submit the data and further add tickets
402        # if the application is special.
403        elif self.context.special and state == PAID:
404            actions = [[_('Save'), _('Finally Submit')],
405                [_('Add online payment ticket')]]
406        elif state == PAID:
407            actions = [[_('Save'), _('Finally Submit')], []]
408        return actions
409
410    @property
411    def form_fields(self):
412        if self.target is not None and self.target == 'trans':
413            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
414                'locked', 'suspended')
415            form_fields['applicant_id'].for_display = True
416            form_fields['reg_number'].for_display = True
417            return form_fields
418        if self.target is not None and self.target == 'cert':
419            form_fields = grok.AutoFields(ICertificateRequest).omit(
420                'locked', 'suspended')
421            form_fields['applicant_id'].for_display = True
422            form_fields['reg_number'].for_display = True
423            return form_fields
424        # AAUE is using the same interface for all regular applications.
425        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
426        if self.target is not None and self.target.startswith('pg'):
427            for field in PG_OMIT_EDIT_FIELDS:
428                form_fields = form_fields.omit(field)
429        elif self.target is not None and self.target in ('ptee',):
430            for field in PTEE_OMIT_EDIT_FIELDS:
431                form_fields = form_fields.omit(field)
432        elif self.target is not None and self.target in ('ude',):
433            for field in UDE_OMIT_EDIT_FIELDS:
434                form_fields = form_fields.omit(field)
435        else:
436            for field in UG_OMIT_EDIT_FIELDS:
437                form_fields = form_fields.omit(field)
438        # Additional omissions
439        if self.target is not None and self.target in ('ude', 'utme'):
440            for field in UPDATE_OMIT_FIELDS:
441                form_fields[field].for_display = True
442        form_fields['applicant_id'].for_display = True
443        form_fields['reg_number'].for_display = True
444        return form_fields
445
446class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
447    """Captcha'd registration page for applicants.
448    """
449
450    @property
451    def form_fields(self):
452        form_fields = None
453        if self.context.mode == 'update':
454            form_fields = grok.AutoFields(IApplicantRegisterUpdate).select(
455                'lastname','reg_number','email')
456            target = getattr(self.context, 'prefix', None)
457            if target in ('trans', 'cert'):
458                form_fields.get('reg_number').field.title = u'Matriculation Number'
459        else: #if self.context.mode == 'create':
460            form_fields = grok.AutoFields(ICustomUGApplicantEdit).select(
461                'firstname', 'middlename', 'lastname', 'email', 'phone')
462        return form_fields
463
464    def _redirect(self, email, password, applicant_id):
465        # Forward email and credentials to landing page.
466        self.redirect(self.url(self.context, 'registration_complete',
467            data = dict(email=email, password=password,
468            applicant_id=applicant_id)))
469        return
470
471class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
472
473    @property
474    def payment_slip_download_warning(self):
475        return ''
476
477class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
478    """Captcha'd status checking page for applicants.
479    """
480    grok.template('applicantcheckstatus')
481
482class PaymentReceiptActionButton(ManageActionButton):
483    grok.order(8) # This button should always be the last one.
484    grok.context(ICustomApplicant)
485    grok.view(CustomApplicantDisplayFormPage)
486    grok.require('waeup.viewApplication')
487    icon = 'actionicon_pdf.png'
488    text = _('Download screening invitation letter')
489    target = 'screening_invitation.pdf'
490
491    @property
492    def target_url(self):
493        if not self.context.screening_date:
494            return ''
495        return self.view.url(self.view.context, self.target)
496
497class ExportScreeningInvitationLetter(UtilityView, grok.View):
498    """Deliver a slip with only screening data.
499    This form page is available only in AAUE.
500    """
501    grok.context(ICustomApplicant)
502    grok.name('screening_invitation.pdf')
503    grok.require('waeup.viewApplication')
504    prefix = 'form'
505
506    label = u'Screening Invitation Letter'
507
508    form_fields = []
509
510    @property
511    def note(self):
512        if self.context.screening_date:
513            year = self.context.__parent__.year
514            session = '%s/%s' % (year, year + 1)
515            sdate = self.context.screening_date
516            stime = ''
517            if '@' in self.context.screening_date:
518                sdate = self.context.screening_date.split('@')[0].strip()
519                stime = self.context.screening_date.split('@')[1].strip()
520            return """
521<br /><br /><br /><br /><font size='12'>
522Dear %s,
523<br /><br />
524You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
525<br /><br />
526<strong>Date: %s
527<br /><br />
528Time: %s
529<br /><br />
530Venue: %s
531</strong>
532<br /><br />
533Please bring this letter of invitation and the downloaded application form along with you on your screening date.
534<br /><br />
535You are expected to be available 30 minutes before the commencement of your Screening.
536</font>
537
538""" % (
539       self.context.display_fullname,
540       session,
541       sdate,
542       stime,
543       self.context.screening_venue)
544        return
545
546    @property
547    def title(self):
548        return None
549
550    def update(self):
551        if not self.context.screening_date:
552            self.flash(_('Forbidden'), type="warning")
553            self.redirect(self.url(self.context))
554
555    def render(self):
556        applicantview = ApplicantBaseDisplayFormPage(self.context, self.request)
557        students_utils = getUtility(IStudentsUtils)
558        return students_utils.renderPDF(self,'screening_data.pdf',
559            self.context, applicantview, note=self.note)
Note: See TracBrowser for help on using the repository browser.