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

Last change on this file since 15409 was 15276, checked in by Henrik Bettermann, 6 years ago

Find another way to set the required attribute of some fields on CustomApplicantEditFormPage?.

  • Property svn:keywords set to Id
File size: 26.0 KB
Line 
1## $Id: browser.py 15276 2018-12-19 16:15:51Z 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', 'alr_results',
119      'hq_type2', 'hq_fname2', 'hq_matric_no2',
120      'hq_degree2', 'hq_school2', 'hq_session2', 'hq_disc2',
121      'hq_type3', 'hq_fname3', 'hq_matric_no3',
122      'hq_degree3', 'hq_school3', 'hq_session3', 'hq_disc3',
123      'notice')
124UDE_OMIT_MANAGE_FIELDS = (
125    'special_application','jamb_subjects_list',) + UDE_OMIT_FIELDS
126UDE_OMIT_EDIT_FIELDS = UDE_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
127    'student_id',
128    'notice',
129    'jamb_age',
130    'jamb_subjects',
131    'jamb_score',
132    'jamb_reg_number',
133    'aggregate',
134    'master_sheet_number',
135    'screening_venue',
136    'screening_score',
137    'screening_date'
138    )
139
140#UG_OMIT_PDF_FIELDS = tuple([
141#    element for element in UG_OMIT_PDF_FIELDS if not element == 'phone'])
142
143#UG_OMIT_PDF_FIELDS += (
144#      'reg_number','alr_fname', 'alr_no', 'alr_date',
145#      'alr_results', 'notice'
146#      )
147
148PG_OMIT_FIELDS = (
149    'fst_sit_fname',
150    'fst_sit_no',
151    'fst_sit_date',
152    'fst_sit_type',
153    'fst_sit_results',
154    'scd_sit_fname',
155    'scd_sit_no',
156    'scd_sit_date',
157    'scd_sit_type',
158    'scd_sit_results',
159    #'programme_type',
160    'jamb_age',
161    'jamb_subjects',
162    'jamb_score',
163    'jamb_reg_number',
164    'aggregate'
165    )
166PG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
167    'jamb_subjects_list',) + PG_OMIT_FIELDS
168PG_OMIT_PDF_FIELDS = PG_OMIT_DISPLAY_FIELDS + PG_OMIT_FIELDS + (
169      'reg_number','alr_fname', 'alr_no', 'alr_date',
170      'alr_results', 'notice',
171      'nysc_year',
172      'nysc_location',
173      'nysc_lga',
174      'former_matric',
175      )
176PG_OMIT_MANAGE_FIELDS = (
177    'special_application','jamb_subjects_list',) + PG_OMIT_FIELDS
178PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
179    'student_id',
180    'notice',
181    )
182
183PTEE_OMIT_FIELDS = (
184    'jamb_age',
185    'jamb_subjects',
186    'jamb_score',
187    'jamb_reg_number',
188    'aggregate'
189    )
190PTEE_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
191    'jamb_subjects_list',) + PTEE_OMIT_FIELDS
192PTEE_OMIT_PDF_FIELDS = PTEE_OMIT_DISPLAY_FIELDS + PTEE_OMIT_FIELDS + (
193      'reg_number','alr_fname', 'alr_no', 'alr_date',
194      'alr_results', 'notice',
195      'nysc_year',
196      'nysc_location',
197      'nysc_lga',
198      'employer',
199      'emp_position',
200      'emp_start',
201      'emp_end',
202      'emp_reason',
203      'employer2',
204      'emp2_position',
205      'emp2_start',
206      'emp2_end',
207      'emp2_reason',
208      'former_matric',
209    )
210PTEE_OMIT_MANAGE_FIELDS = (
211    'special_application','jamb_subjects_list',) + PTEE_OMIT_FIELDS
212PTEE_OMIT_EDIT_FIELDS = PTEE_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
213    'student_id',
214    'notice',
215    )
216
217UPDATE_OMIT_FIELDS = (
218    'firstname',
219    'middlename',
220    'lastname',
221    'sex',
222    'lga',
223    'course1',
224    )
225
226MAX_FILE_UPLOAD_SIZE = 1024 * 500
227
228def handle_file_upload(upload, context, view, attr=None):
229    """Handle upload of applicant files.
230
231    Returns `True` in case of success or `False`.
232
233    Please note that file pointer passed in (`upload`) most probably
234    points to end of file when leaving this function.
235    """
236    size = file_size(upload)
237    if size > MAX_FILE_UPLOAD_SIZE:
238        view.flash(_('Uploaded file is too big!'))
239        return False
240    dummy, ext = os.path.splitext(upload.filename)
241    ext.lower()
242    if ext != '.pdf':
243        view.flash(_('pdf file extension expected.'))
244        return False
245    upload.seek(0) # file pointer moved when determining size
246    store = getUtility(IExtFileStore)
247    file_id = IFileStoreNameChooser(context).chooseName(attr=attr)
248    store.createFile(file_id, upload)
249    return True
250
251class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
252    """A display view for applicant data.
253    """
254
255    @property
256    def file_links(self):
257        html = ''
258        pdf = getUtility(IExtFileStore).getFileByContext(
259            self.context, attr='stateresult.pdf')
260        if pdf:
261            html += '<a href="stateresult.pdf">Statement of Result</a>'
262        return html
263
264    @property
265    def form_fields(self):
266        if self.target is not None and self.target == 'trans':
267            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
268                'locked', 'suspended')
269            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
270            form_fields['perm_address'].custom_widget = BytesDisplayWidget
271            return form_fields
272        if self.target is not None and self.target == 'cert':
273            form_fields = grok.AutoFields(ICertificateRequest).omit(
274                'locked', 'suspended')
275            #form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
276            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
277            return form_fields
278        # AAUE is using the same interface for all regular applications.
279        form_fields = grok.AutoFields(ICustomUGApplicant)
280        if self.target is not None and self.target.startswith('pg'):
281            for field in PG_OMIT_DISPLAY_FIELDS:
282                form_fields = form_fields.omit(field)
283        elif self.target is not None and self.target in ('ptee',):
284            for field in PTEE_OMIT_DISPLAY_FIELDS:
285                form_fields = form_fields.omit(field)
286        elif self.target is not None and self.target in ('bridge', 'ude',):
287            for field in UDE_OMIT_DISPLAY_FIELDS:
288                form_fields = form_fields.omit(field)
289        else:
290            for field in UG_OMIT_DISPLAY_FIELDS:
291                form_fields = form_fields.omit(field)
292        form_fields['perm_address'].custom_widget = BytesDisplayWidget
293        form_fields['notice'].custom_widget = BytesDisplayWidget
294        if not getattr(self.context, 'student_id'):
295            form_fields = form_fields.omit('student_id')
296        if not getattr(self.context, 'screening_score'):
297            form_fields = form_fields.omit('screening_score')
298        if not getattr(self.context, 'screening_venue') or \
299            self.context.state not in ('submitted', 'admitted', 'created'):
300            form_fields = form_fields.omit('screening_venue')
301        if not getattr(self.context, 'screening_date') or \
302            self.context.state not in ('submitted', 'admitted', 'created'):
303            form_fields = form_fields.omit('screening_date')
304        return form_fields
305
306    def getCourseAdmitted(self):
307        """Return link, title and code in html format to the certificate
308           admitted.
309        """
310        if self.layout.isApplicant():
311            return ''
312        course_admitted = self.context.course_admitted
313        if getattr(course_admitted, '__parent__',None):
314            url = self.url(course_admitted)
315            title = course_admitted.title
316            code = course_admitted.code
317            return '<a href="%s">%s - %s</a>' %(url,code,title)
318        return ''
319
320    def update(self):
321        super(CustomApplicantDisplayFormPage, self).update()
322        self.extraform_url = self.url(self.context, 'stateresult.pdf')
323        return
324
325class CustomPDFActionButton(PDFActionButton):
326
327    @property
328    def target_url(self):
329        if self.context.state in ('initialized', 'started', 'paid') \
330            or self.context.special or self.view.target in ('trans', 'cert'):
331            return
332        return self.view.url(self.view.context, self.target)
333
334
335class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
336
337    column_two_fields = ('applicant_id', 'reg_number',
338        'firstname', 'middlename', 'lastname', 'sex', 'date_of_birth')
339    #two_columns_design_fields = [
340    #    'fst_sit_fname', 'fst_sit_no', 'fst_sit_date',
341    #    'fst_sit_type', 'fst_sit_results',
342    #    'scd_sit_fname', 'scd_sit_no', 'scd_sit_date',
343    #    'scd_sit_type', 'scd_sit_results']
344
345    def _getCourseAdmittedLink(self, view):
346        return None
347
348    def _getDeptAndFaculty(self):
349        return [None, None]
350
351    @property
352    def note(self):
353        note = getattr(self.context.__parent__, 'application_slip_notice', None)
354        if note:
355            return '<br /><br />' + note
356        if self.context.sex == 'm':
357            pronoun = 'he'
358        else:
359            pronoun = 'she'
360        return '''
361The applicant has acknowledged that, if discovered at any time that %s does not possess
362any of the qualifications which %s claims %s has obtained, %s will be expelled from the
363University not be re-admitted for the same or any other programme, even if %s has
364upgraded previous qualifications or possess additional qualifications.
365
366''' % (
367    pronoun, pronoun, pronoun, pronoun, pronoun)
368
369    @property
370    def form_fields(self):
371        # AAUE is using the same interface for all regular applications.
372        form_fields = grok.AutoFields(ICustomUGApplicant)
373        if self.target is not None and self.target.startswith('pg'):
374            for field in PG_OMIT_PDF_FIELDS:
375                form_fields = form_fields.omit(field)
376        elif self.target is not None and self.target in ('ptee',):
377            for field in PTEE_OMIT_PDF_FIELDS:
378                form_fields = form_fields.omit(field)
379        elif self.target is not None and self.target in ('bridge', 'ude',):
380            for field in UDE_OMIT_PDF_FIELDS:
381                form_fields = form_fields.omit(field)
382        else:
383            for field in UG_OMIT_PDF_FIELDS:
384                form_fields = form_fields.omit(field)
385        if not getattr(self.context, 'student_id'):
386            form_fields = form_fields.omit('student_id')
387        if not getattr(self.context, 'screening_score'):
388            form_fields = form_fields.omit('screening_score')
389        if not getattr(self.context, 'screening_venue'):
390            form_fields = form_fields.omit('screening_venue')
391        if not getattr(self.context, 'screening_date'):
392            form_fields = form_fields.omit('screening_date')
393        return form_fields
394
395class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
396    """A full edit view for applicant data.
397    """
398
399    @property
400    def form_fields(self):
401        if self.target is not None and self.target == 'trans':
402            form_fields = grok.AutoFields(ITranscriptApplicant)
403            form_fields['applicant_id'].for_display = True
404            return form_fields
405        if self.target is not None and self.target == 'cert':
406            form_fields = grok.AutoFields(ICertificateRequest)
407            form_fields['applicant_id'].for_display = True
408            return form_fields
409        # AAUE is using the same interface for all regular applications.
410        form_fields = grok.AutoFields(ICustomUGApplicant)
411        if self.target is not None and self.target.startswith('pg'):
412            for field in PG_OMIT_MANAGE_FIELDS:
413                form_fields = form_fields.omit(field)
414        elif self.target is not None and self.target in ('ptee',):
415            for field in PTEE_OMIT_MANAGE_FIELDS:
416                form_fields = form_fields.omit(field)
417        elif self.target is not None and self.target in ('bridge', 'ude',):
418            for field in UDE_OMIT_MANAGE_FIELDS:
419                form_fields = form_fields.omit(field)
420        else:
421            for field in UG_OMIT_MANAGE_FIELDS:
422                form_fields = form_fields.omit(field)
423        form_fields['student_id'].for_display = True
424        form_fields['applicant_id'].for_display = True
425        return form_fields
426
427    def update(self):
428        super(CustomApplicantManageFormPage, self).update()
429        upload_stateresult = self.request.form.get('form.stateresult', None)
430        if upload_stateresult:
431            # We got a fresh stateresult upload
432            success = handle_file_upload(
433                upload_stateresult, self.context, self, attr='stateresult.pdf')
434            if success:
435                self.context.writeLogMessage(self, 'saved: stateresult')
436            else:
437                self.upload_success = False
438        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
439        return
440
441class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
442    """An applicant-centered edit view for applicant data.
443    """
444
445    def unremovable(self, ticket):
446        return True
447
448    def dataNotComplete(self):
449        store = getUtility(IExtFileStore)
450        # Temporarily enable passport upload also for cert and trans
451        # applications.
452        if True: # not self.target[:4] in ('cert', 'tran'):
453            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
454                return _('No passport picture uploaded.')
455            if not self.target[:4] in ('cert', 'tran') and \
456                not self.request.form.get('confirm_passport', False):
457                return _('Passport picture confirmation box not ticked.')
458        if self.target in ('trans', 'cert') and \
459            not store.getFileByContext(self.context, attr=u'stateresult.pdf'):
460            return _('No statement of result pdf file uploaded.')
461
462        return False
463
464    # AAUE applicants never see the 'Remove Selected Tickets' button.
465    @property
466    def display_actions(self):
467        # If the form is unlocked, applicants are allowed to save the form
468        # and remove unused tickets.
469        actions = [[_('Save')], []]
470        # Only in state started they can also add tickets.
471        if self.context.state == STARTED:
472            actions = [[_('Save')],
473                [_('Add online payment ticket')]]
474        # In state paid, they can submit the data and further add tickets
475        # if the application is special.
476        elif self.context.special and self.context.state == PAID:
477            actions = [[_('Save'), _('Finally Submit')],
478                [_('Add online payment ticket')]]
479        elif self.context.state == PAID:
480            actions = [[_('Save'), _('Finally Submit')], []]
481        return actions
482
483    @property
484    def form_fields(self):
485        if self.target is not None and self.target == 'trans':
486            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
487                'locked', 'suspended')
488            form_fields['applicant_id'].for_display = True
489            form_fields['reg_number'].for_display = True
490            form_fields['place_of_birth'].field.required = True
491            form_fields['date_of_birth'].field.required = True
492            form_fields['nationality'].field.required = True
493            form_fields['email'].field.required = True
494            form_fields['phone'].field.required = True
495            form_fields['perm_address'].field.required = True
496            form_fields['dispatch_address'].field.required = True
497            form_fields['entry_mode'].field.required = True
498            form_fields['entry_session'].field.required = True
499            form_fields['end_session'].field.required = True
500            form_fields['course_studied'].field.required = True
501            return form_fields
502        if self.target is not None and self.target == 'cert':
503            form_fields = grok.AutoFields(ICertificateRequest).omit(
504                'locked', 'suspended')
505            form_fields['applicant_id'].for_display = True
506            form_fields['reg_number'].for_display = True
507            form_fields['place_of_birth'].field.required = True
508            form_fields['date_of_birth'].field.required = True
509            form_fields['nationality'].field.required = True
510            form_fields['email'].field.required = True
511            form_fields['phone'].field.required = True
512            form_fields['entry_session'].field.required = True
513            form_fields['end_session'].field.required = True
514            form_fields['course_studied'].field.required = True
515            form_fields['certificate_type'].field.required = True
516            # Additional omissions
517            if self.context.__parent__.code == 'cert5':
518                for field in ('firstname', 'middlename', 'lastname'):
519                    form_fields[field].for_display = True
520            return form_fields
521        # AAUE is using the same interface for all regular applications.
522        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
523        if self.target is not None and self.target.startswith('pg'):
524            for field in PG_OMIT_EDIT_FIELDS:
525                form_fields = form_fields.omit(field)
526        elif self.target is not None and self.target in ('ptee',):
527            for field in PTEE_OMIT_EDIT_FIELDS:
528                form_fields = form_fields.omit(field)
529        elif self.target is not None and self.target in ('bridge', 'ude',):
530            for field in UDE_OMIT_EDIT_FIELDS:
531                form_fields = form_fields.omit(field)
532        else:
533            for field in UG_OMIT_EDIT_FIELDS:
534                form_fields = form_fields.omit(field)
535        # Additional omissions
536        if self.target is not None and self.target in ('ude', 'utme'):
537            for field in UPDATE_OMIT_FIELDS:
538                form_fields[field].for_display = True
539        form_fields['applicant_id'].for_display = True
540        form_fields['reg_number'].for_display = True
541        return form_fields
542
543    def update(self):
544        if self.context.locked or (
545            self.context.__parent__.expired and
546            self.context.__parent__.strict_deadline):
547            self.emit_lock_message()
548            return
549        super(CustomApplicantEditFormPage, self).update()
550        upload_stateresult = self.request.form.get('form.stateresult', None)
551        if upload_stateresult:
552            # We got a fresh stateresult upload
553            success = handle_file_upload(
554                upload_stateresult, self.context, self, attr='stateresult.pdf')
555            if not success:
556                self.upload_success = False
557        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
558        return
559
560class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
561    """Captcha'd registration page for applicants.
562    """
563
564    @property
565    def form_fields(self):
566        form_fields = None
567        if self.context.mode == 'update':
568            form_fields = grok.AutoFields(IApplicantRegisterUpdate).select(
569                'lastname','reg_number','email')
570            target = getattr(self.context, 'prefix', None)
571            if target in ('trans', 'cert'):
572                form_fields.get('reg_number').field.title = u'Matriculation Number'
573        else: #if self.context.mode == 'create':
574            form_fields = grok.AutoFields(ICustomUGApplicantEdit).select(
575                'firstname', 'middlename', 'lastname', 'email', 'phone')
576        return form_fields
577
578    def _redirect(self, email, password, applicant_id):
579        # Forward email and credentials to landing page.
580        self.redirect(self.url(self.context, 'registration_complete',
581            data = dict(email=email, password=password,
582            applicant_id=applicant_id)))
583        return
584
585    @property
586    def _postfix(self):
587        """Alumni records have to be imported into several containers.
588        Therefore a string must be added to their registration number
589        to make it unique.
590        """
591        if self.context.prefix in ('trans', 'cert'):
592            return self.context.code
593        return ''
594
595class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
596
597    @property
598    def payment_slip_download_warning(self):
599        return ''
600
601class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
602    """Captcha'd status checking page for applicants.
603    """
604    grok.template('applicantcheckstatus')
605
606class ScreeningInvitationActionButton(ManageActionButton):
607    grok.order(8) # This button should always be the last one.
608    grok.context(ICustomApplicant)
609    grok.view(CustomApplicantDisplayFormPage)
610    grok.require('waeup.viewApplication')
611    icon = 'actionicon_pdf.png'
612    text = _('Download screening invitation letter')
613    target = 'screening_invitation.pdf'
614
615    @property
616    def target_url(self):
617        if not self.context.screening_date or not self.context.state in (
618            'submitted', 'admitted', 'created'):
619            return ''
620        return self.view.url(self.view.context, self.target)
621
622class ExportScreeningInvitationLetter(UtilityView, grok.View):
623    """Deliver a slip with only screening data.
624    This form page is available only in AAUE.
625    """
626    grok.context(ICustomApplicant)
627    grok.name('screening_invitation.pdf')
628    grok.require('waeup.viewApplication')
629    prefix = 'form'
630
631    label = u'Screening Invitation Letter'
632
633    form_fields = []
634
635    @property
636    def note(self):
637        if self.context.screening_date:
638            year = self.context.__parent__.year
639            session = '%s/%s' % (year, year + 1)
640            sdate = self.context.screening_date
641            stime = ''
642            if '@' in self.context.screening_date:
643                sdate = self.context.screening_date.split('@')[0].strip()
644                stime = self.context.screening_date.split('@')[1].strip()
645            return """
646<br /><br /><br /><br /><font size='12'>
647Dear %s,
648<br /><br />
649You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
650<br /><br />
651<strong>Date: %s
652<br /><br />
653Time: %s
654<br /><br />
655Venue: %s
656</strong>
657<br /><br />
658Please bring this letter of invitation and the downloaded application form along with you on your screening date.
659<br /><br />
660You are expected to be available 30 minutes before the commencement of your Screening.
661</font>
662
663""" % (
664       self.context.display_fullname,
665       session,
666       sdate,
667       stime,
668       self.context.screening_venue)
669        return
670
671    @property
672    def title(self):
673        return None
674
675    def update(self):
676        if not self.context.screening_date or not self.context.state in (
677            'submitted', 'admitted', 'created'):
678            self.flash(_('Forbidden'), type="warning")
679            self.redirect(self.url(self.context))
680
681    def render(self):
682        applicantview = ApplicantBaseDisplayFormPage(self.context, self.request)
683        students_utils = getUtility(IStudentsUtils)
684        return students_utils.renderPDF(self,'screening_data.pdf',
685            self.context, applicantview, note=self.note)
686
687class StateResult(grok.View):
688    """Renders the pdf form extension for applicants.
689    """
690    grok.name('stateresult.pdf')
691    grok.context(ICustomApplicant)
692    grok.require('waeup.viewApplication')
693
694    def render(self):
695        pdf = getUtility(IExtFileStore).getFileByContext(
696            self.context, attr='stateresult.pdf')
697        self.response.setHeader('Content-Type', 'application/pdf')
698        return pdf
Note: See TracBrowser for help on using the repository browser.