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

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

It's not the parent object.

  • Property svn:keywords set to Id
File size: 19.8 KB
Line 
1## $Id: browser.py 14465 2017-01-26 12:00:58Z 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')
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')
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            return form_fields
417        if self.target is not None and self.target == 'cert':
418            form_fields = grok.AutoFields(ICertificateRequest).omit(
419                'locked', 'suspended')
420            form_fields['applicant_id'].for_display = True
421            return form_fields
422        # AAUE is using the same interface for all regular applications.
423        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
424        if self.target is not None and self.target.startswith('pg'):
425            for field in PG_OMIT_EDIT_FIELDS:
426                form_fields = form_fields.omit(field)
427        elif self.target is not None and self.target in ('ptee',):
428            for field in PTEE_OMIT_EDIT_FIELDS:
429                form_fields = form_fields.omit(field)
430        elif self.target is not None and self.target in ('ude',):
431            for field in UDE_OMIT_EDIT_FIELDS:
432                form_fields = form_fields.omit(field)
433        else:
434            for field in UG_OMIT_EDIT_FIELDS:
435                form_fields = form_fields.omit(field)
436        # Additional omissions
437        if self.target is not None and self.target in ('ude', 'utme'):
438            for field in UPDATE_OMIT_FIELDS:
439                form_fields[field].for_display = True
440        form_fields['applicant_id'].for_display = True
441        form_fields['reg_number'].for_display = True
442        return form_fields
443
444class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
445    """Captcha'd registration page for applicants.
446    """
447
448    @property
449    def form_fields(self):
450        form_fields = None
451        if self.context.mode == 'update':
452            form_fields = grok.AutoFields(IApplicantRegisterUpdate).select(
453                'lastname','reg_number','email')
454            target = getattr(self.context, 'prefix', None)
455            if target in ('trans', 'cert'):
456                form_fields.get('reg_number').field.title = u'Matriculation Number'
457        else: #if self.context.mode == 'create':
458            form_fields = grok.AutoFields(ICustomUGApplicantEdit).select(
459                'firstname', 'middlename', 'lastname', 'email', 'phone')
460        return form_fields
461
462    def _redirect(self, email, password, applicant_id):
463        # Forward email and credentials to landing page.
464        self.redirect(self.url(self.context, 'registration_complete',
465            data = dict(email=email, password=password,
466            applicant_id=applicant_id)))
467        return
468
469class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
470
471    @property
472    def payment_slip_download_warning(self):
473        return ''
474
475class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
476    """Captcha'd status checking page for applicants.
477    """
478    grok.template('applicantcheckstatus')
479
480class PaymentReceiptActionButton(ManageActionButton):
481    grok.order(8) # This button should always be the last one.
482    grok.context(ICustomApplicant)
483    grok.view(CustomApplicantDisplayFormPage)
484    grok.require('waeup.viewApplication')
485    icon = 'actionicon_pdf.png'
486    text = _('Download screening invitation letter')
487    target = 'screening_invitation.pdf'
488
489    @property
490    def target_url(self):
491        if not self.context.screening_date:
492            return ''
493        return self.view.url(self.view.context, self.target)
494
495class ExportScreeningInvitationLetter(UtilityView, grok.View):
496    """Deliver a slip with only screening data.
497    This form page is available only in AAUE.
498    """
499    grok.context(ICustomApplicant)
500    grok.name('screening_invitation.pdf')
501    grok.require('waeup.viewApplication')
502    prefix = 'form'
503
504    label = u'Screening Invitation Letter'
505
506    form_fields = []
507
508    @property
509    def note(self):
510        if self.context.screening_date:
511            year = self.context.__parent__.year
512            session = '%s/%s' % (year, year + 1)
513            sdate = self.context.screening_date
514            stime = ''
515            if '@' in self.context.screening_date:
516                sdate = self.context.screening_date.split('@')[0].strip()
517                stime = self.context.screening_date.split('@')[1].strip()
518            return """
519<br /><br /><br /><br /><font size='12'>
520Dear %s,
521<br /><br />
522You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
523<br /><br />
524<strong>Date: %s
525<br /><br />
526Time: %s
527<br /><br />
528Venue: %s
529</strong>
530<br /><br />
531Please bring this letter of invitation and the downloaded application form along with you on your screening date.
532<br /><br />
533You are expected to be available 30 minutes before the commencement of your Screening.
534</font>
535
536""" % (
537       self.context.display_fullname,
538       session,
539       sdate,
540       stime,
541       self.context.screening_venue)
542        return
543
544    @property
545    def title(self):
546        return None
547
548    def update(self):
549        if not self.context.screening_date:
550            self.flash(_('Forbidden'), type="warning")
551            self.redirect(self.url(self.context))
552
553    def render(self):
554        applicantview = ApplicantBaseDisplayFormPage(self.context, self.request)
555        students_utils = getUtility(IStudentsUtils)
556        return students_utils.renderPDF(self,'screening_data.pdf',
557            self.context, applicantview, note=self.note)
Note: See TracBrowser for help on using the repository browser.