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

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

Remove course_admitted from application slip.

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