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

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

Hide Admitted Course of Study from applicants.

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