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

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

Allow file upload also in cert containers.

  • Property svn:keywords set to Id
File size: 24.6 KB
Line 
1## $Id: browser.py 15117 2018-09-03 07:00:16Z 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 ('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 ('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 ('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        if not self.target[:4] in ('cert', 'tran'):
451            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
452                return _('No passport picture uploaded.')
453            if not self.request.form.get('confirm_passport', False):
454                return _('Passport picture confirmation box not ticked.')
455        if self.view.target in ('trans', 'cert') and \
456            not store.getFileByContext(self.context, attr=u'stateresult.pdf'):
457            return _('No statement of result pdf file uploaded.')
458
459        return False
460
461    # AAUE applicants never see the 'Remove Selected Tickets' button.
462    @property
463    def display_actions(self):
464        # If the form is unlocked, applicants are allowed to save the form
465        # and remove unused tickets.
466        actions = [[_('Save')], []]
467        # Only in state started they can also add tickets.
468        if self.context.state == STARTED:
469            actions = [[_('Save')],
470                [_('Add online payment ticket')]]
471        # In state paid, they can submit the data and further add tickets
472        # if the application is special.
473        elif self.context.special and self.context.state == PAID:
474            actions = [[_('Save'), _('Finally Submit')],
475                [_('Add online payment ticket')]]
476        elif self.context.state == PAID:
477            actions = [[_('Save'), _('Finally Submit')], []]
478        return actions
479
480    @property
481    def form_fields(self):
482        if self.target is not None and self.target == 'trans':
483            form_fields = grok.AutoFields(ITranscriptApplicant).omit(
484                'locked', 'suspended')
485            form_fields['applicant_id'].for_display = True
486            form_fields['reg_number'].for_display = True
487            return form_fields
488        if self.target is not None and self.target == 'cert':
489            form_fields = grok.AutoFields(ICertificateRequest).omit(
490                'locked', 'suspended')
491            form_fields['applicant_id'].for_display = True
492            form_fields['reg_number'].for_display = True
493            # Additional omissions
494            if self.context.__parent__.code == 'cert5':
495                for field in ('firstname', 'middlename', 'lastname'):
496                    form_fields[field].for_display = True
497            return form_fields
498        # AAUE is using the same interface for all regular applications.
499        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
500        if self.target is not None and self.target.startswith('pg'):
501            for field in PG_OMIT_EDIT_FIELDS:
502                form_fields = form_fields.omit(field)
503        elif self.target is not None and self.target in ('ptee',):
504            for field in PTEE_OMIT_EDIT_FIELDS:
505                form_fields = form_fields.omit(field)
506        elif self.target is not None and self.target in ('ude',):
507            for field in UDE_OMIT_EDIT_FIELDS:
508                form_fields = form_fields.omit(field)
509        else:
510            for field in UG_OMIT_EDIT_FIELDS:
511                form_fields = form_fields.omit(field)
512        # Additional omissions
513        if self.target is not None and self.target in ('ude', 'utme'):
514            for field in UPDATE_OMIT_FIELDS:
515                form_fields[field].for_display = True
516        form_fields['applicant_id'].for_display = True
517        form_fields['reg_number'].for_display = True
518        return form_fields
519
520    def update(self):
521        if self.context.locked or (
522            self.context.__parent__.expired and
523            self.context.__parent__.strict_deadline):
524            self.emit_lock_message()
525            return
526        super(CustomApplicantEditFormPage, self).update()
527        upload_stateresult = self.request.form.get('form.stateresult', None)
528        if upload_stateresult:
529            # We got a fresh stateresult upload
530            success = handle_file_upload(
531                upload_stateresult, self.context, self, attr='stateresult.pdf')
532            if not success:
533                self.upload_success = False
534        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
535        return
536
537class CustomApplicantRegistrationPage(NigeriaApplicantRegistrationPage):
538    """Captcha'd registration page for applicants.
539    """
540
541    @property
542    def form_fields(self):
543        form_fields = None
544        if self.context.mode == 'update':
545            form_fields = grok.AutoFields(IApplicantRegisterUpdate).select(
546                'lastname','reg_number','email')
547            target = getattr(self.context, 'prefix', None)
548            if target in ('trans', 'cert'):
549                form_fields.get('reg_number').field.title = u'Matriculation Number'
550        else: #if self.context.mode == 'create':
551            form_fields = grok.AutoFields(ICustomUGApplicantEdit).select(
552                'firstname', 'middlename', 'lastname', 'email', 'phone')
553        return form_fields
554
555    def _redirect(self, email, password, applicant_id):
556        # Forward email and credentials to landing page.
557        self.redirect(self.url(self.context, 'registration_complete',
558            data = dict(email=email, password=password,
559            applicant_id=applicant_id)))
560        return
561
562    @property
563    def _postfix(self):
564        """Alumni records have to be imported into several containers.
565        Therefore a string must be added to their registration number
566        to make it unique.
567        """
568        if self.context.prefix in ('trans', 'cert'):
569            return self.context.code
570        return ''
571
572class CustomExportPDFPaymentSlipPage(NigeriaExportPDFPaymentSlipPage):
573
574    @property
575    def payment_slip_download_warning(self):
576        return ''
577
578class CustomApplicantCheckStatusPage(ApplicantCheckStatusPage):
579    """Captcha'd status checking page for applicants.
580    """
581    grok.template('applicantcheckstatus')
582
583class ScreeningInvitationActionButton(ManageActionButton):
584    grok.order(8) # This button should always be the last one.
585    grok.context(ICustomApplicant)
586    grok.view(CustomApplicantDisplayFormPage)
587    grok.require('waeup.viewApplication')
588    icon = 'actionicon_pdf.png'
589    text = _('Download screening invitation letter')
590    target = 'screening_invitation.pdf'
591
592    @property
593    def target_url(self):
594        if not self.context.screening_date or not self.context.state in (
595            'submitted', 'admitted', 'created'):
596            return ''
597        return self.view.url(self.view.context, self.target)
598
599class ExportScreeningInvitationLetter(UtilityView, grok.View):
600    """Deliver a slip with only screening data.
601    This form page is available only in AAUE.
602    """
603    grok.context(ICustomApplicant)
604    grok.name('screening_invitation.pdf')
605    grok.require('waeup.viewApplication')
606    prefix = 'form'
607
608    label = u'Screening Invitation Letter'
609
610    form_fields = []
611
612    @property
613    def note(self):
614        if self.context.screening_date:
615            year = self.context.__parent__.year
616            session = '%s/%s' % (year, year + 1)
617            sdate = self.context.screening_date
618            stime = ''
619            if '@' in self.context.screening_date:
620                sdate = self.context.screening_date.split('@')[0].strip()
621                stime = self.context.screening_date.split('@')[1].strip()
622            return """
623<br /><br /><br /><br /><font size='12'>
624Dear %s,
625<br /><br />
626You are invited to the Ambrose Alli University %s Admissions Screening Exercise.
627<br /><br />
628<strong>Date: %s
629<br /><br />
630Time: %s
631<br /><br />
632Venue: %s
633</strong>
634<br /><br />
635Please bring this letter of invitation and the downloaded application form along with you on your screening date.
636<br /><br />
637You are expected to be available 30 minutes before the commencement of your Screening.
638</font>
639
640""" % (
641       self.context.display_fullname,
642       session,
643       sdate,
644       stime,
645       self.context.screening_venue)
646        return
647
648    @property
649    def title(self):
650        return None
651
652    def update(self):
653        if not self.context.screening_date or not self.context.state in (
654            'submitted', 'admitted', 'created'):
655            self.flash(_('Forbidden'), type="warning")
656            self.redirect(self.url(self.context))
657
658    def render(self):
659        applicantview = ApplicantBaseDisplayFormPage(self.context, self.request)
660        students_utils = getUtility(IStudentsUtils)
661        return students_utils.renderPDF(self,'screening_data.pdf',
662            self.context, applicantview, note=self.note)
663
664class StateResult(grok.View):
665    """Renders the pdf form extension for applicants.
666    """
667    grok.name('stateresult.pdf')
668    grok.context(ICustomApplicant)
669    grok.require('waeup.viewApplication')
670
671    def render(self):
672        pdf = getUtility(IExtFileStore).getFileByContext(
673            self.context, attr='stateresult.pdf')
674        self.response.setHeader('Content-Type', 'application/pdf')
675        return pdf
Note: See TracBrowser for help on using the repository browser.