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

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

Omit certain fields only if application is in update mode (= ude, utme).

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