source: main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/applicants/browser.py @ 17938

Last change on this file since 17938 was 17701, checked in by Henrik Bettermann, 9 months ago

No fields required on CDL portal.

  • Property svn:keywords set to Id
File size: 17.6 KB
Line 
1## $Id: browser.py 17701 2024-02-21 12:53:14Z 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, queryUtility
23from zope.catalog.interfaces import ICatalog
24from zope.formlib.textwidgets import BytesDisplayWidget
25from waeup.kofa.interfaces import (
26    IExtFileStore, IFileStoreNameChooser)
27from waeup.kofa.utils.helpers import string_from_bytes, file_size, now
28from waeup.kofa.applicants.browser import (
29    ApplicantRegistrationPage, ApplicantsContainerPage, AdditionalFile,
30    RefereeReportAddFormPage, ExportPDFReportSlipPage, ExportPDFReportSlipPage2,
31    RefereeReportDisplayFormPage,
32    ApplicantsContainerManageFormPage,
33    ApplicantAddFormPage,
34    ApplicantsRootPage)
35from waeup.kofa.applicants.interfaces import (
36    ISpecialApplicant, IApplicantsContainer, AppCatCertificateSource)
37from kofacustom.nigeria.applicants.browser import (
38    NigeriaApplicantDisplayFormPage,
39    NigeriaApplicantManageFormPage,
40    NigeriaApplicantEditFormPage,
41    NigeriaPDFApplicationSlip)
42from waeup.kofa.widgets.datewidget import (
43    FriendlyDateDisplayWidget,
44    FriendlyDatetimeDisplayWidget)
45from kofacustom.nigeria.applicants.interfaces import (
46    OMIT_DISPLAY_FIELDS,
47    #UG_OMIT_DISPLAY_FIELDS,
48    #UG_OMIT_PDF_FIELDS,
49    #UG_OMIT_MANAGE_FIELDS,
50    #UG_OMIT_EDIT_FIELDS,
51    #PG_OMIT_DISPLAY_FIELDS,
52    #PG_OMIT_PDF_FIELDS,
53    #PG_OMIT_MANAGE_FIELDS,
54    #PG_OMIT_EDIT_FIELDS,
55    )
56from kofacustom.iuokada.applicants.interfaces import (
57    ICustomPGApplicant, ICustomUGApplicant, ICustomApplicant,
58    ICustomPGApplicantEdit, ICustomUGApplicantEdit,
59    ICustomApplicantOnlinePayment, ICustomApplicantRefereeReport,
60    ITranscriptApplicant, ICustomApplicantRegisterUpdate
61    )
62from kofacustom.iuokada.interfaces import MessageFactory as _
63
64MAX_FILE_UPLOAD_SIZE = 1024 * 500
65
66# UG students are all undergraduate students.
67UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
68    #'jamb_subjects_list',
69    'programme_type',)
70UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + ('phone',)
71UG_OMIT_MANAGE_FIELDS = (
72    'special_application',
73    #'jamb_subjects_list',
74    'programme_type',
75    'course1',
76    'course2',)
77UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
78    'student_id',
79    'notice',
80    'screening_score',
81    'screening_venue',
82    'screening_date',
83    #'jamb_age',
84    #'jamb_subjects',
85    #'jamb_score',
86    #'jamb_reg_number',
87    'aggregate',
88    )
89
90JUPEB_OMIT_FIELDS = (
91    'jamb_age',
92    'jamb_subjects',
93    'jamb_score',
94    'jamb_reg_number',
95    'jamb_subjects_list',
96    'jamb_fname',
97    )
98
99# PG has its own interface
100PG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + (
101    'employer',
102    'emp_position',
103    'emp_start',
104    'emp_end',
105    'emp_reason',
106    'employer2',
107    'emp2_position',
108    'emp2_start',
109    'emp2_end',
110    'emp2_reason',
111    )
112PG_OMIT_PDF_FIELDS = PG_OMIT_DISPLAY_FIELDS + ('phone',)
113PG_OMIT_MANAGE_FIELDS = (
114    'special_application',
115    'employer',
116    'emp_position',
117    'emp_start',
118    'emp_end',
119    'emp_reason',
120    'employer2',
121    'emp2_position',
122    'emp2_start',
123    'emp2_end',
124    'emp2_reason',
125    'course1',
126    'course2',
127    )
128PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + PG_OMIT_DISPLAY_FIELDS + (
129    'student_id',
130    'notice',
131    'screening_score',
132    'screening_venue',
133    'screening_date',)
134
135TRANS_OMIT_FIELDS = ('suspended', 'applicant_id',)
136
137TRANS_SHORT_OMIT_FIELDS = TRANS_OMIT_FIELDS + (
138    #'date_of_birth',
139    'sex',
140    'nationality',
141    #'entry_mode',
142    #'entry_session',
143    'end_session',
144    #'course_studied',
145    #'course_changed',
146    #'change_level',
147    )
148
149class CustomApplicantsRootPage(ApplicantsRootPage):
150   
151    grok.template('applicantsrootpage')
152
153class CustomApplicantsContainerPage(ApplicantsContainerPage):
154    """The standard view for regular applicant containers.
155    """
156
157    @property
158    def form_fields(self):
159        form_fields = grok.AutoFields(IApplicantsContainer).omit(
160            'title', 'description')
161        if self.request.principal.id == 'zope.anybody':
162            form_fields = form_fields.omit(
163                'code', 'prefix', 'year', 'mode', 'hidden',
164                'strict_deadline', 'application_category',
165                'application_slip_notice',
166                'application_fee', 'with_picture',
167                'startdate', 'enddate')
168        return form_fields
169
170class CustomApplicantsContainerManageFormPage(ApplicantsContainerManageFormPage):
171
172    max_applicants = 5000
173
174class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
175    """A display view for applicant data.
176    """
177
178    @property
179    def form_fields(self):
180        if self.target is not None and self.target == 'tscf':
181            form_fields = grok.AutoFields(ITranscriptApplicant)
182            for field in TRANS_OMIT_FIELDS:
183                form_fields = form_fields.omit(field)
184            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
185            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
186            return form_fields
187        if self.target is not None and self.target == 'tscs':
188            form_fields = grok.AutoFields(ITranscriptApplicant)
189            for field in TRANS_SHORT_OMIT_FIELDS:
190                form_fields = form_fields.omit(field)
191            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
192            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
193            return form_fields
194        if self.target is not None and self.target.startswith('pg'):
195            form_fields = grok.AutoFields(ICustomPGApplicant)
196            for field in PG_OMIT_DISPLAY_FIELDS:
197                form_fields = form_fields.omit(field)
198        else:
199            form_fields = grok.AutoFields(ICustomUGApplicant)
200            for field in UG_OMIT_DISPLAY_FIELDS:
201                form_fields = form_fields.omit(field)
202        if self.target is not None and self.target == 'pre':
203            for field in JUPEB_OMIT_FIELDS:
204                form_fields = form_fields.omit(field)
205        #form_fields['perm_address'].custom_widget = BytesDisplayWidget
206        form_fields['notice'].custom_widget = BytesDisplayWidget
207        if not getattr(self.context, 'student_id'):
208            form_fields = form_fields.omit('student_id')
209        if not getattr(self.context, 'screening_score'):
210            form_fields = form_fields.omit('screening_score')
211        if not getattr(self.context, 'screening_venue') or self._not_paid():
212            form_fields = form_fields.omit('screening_venue')
213        if not getattr(self.context, 'screening_date') or self._not_paid():
214            form_fields = form_fields.omit('screening_date')
215        return form_fields
216
217def getCerts(view, coursex):
218    yield(dict(code='', title='--', selected=''))
219    appcatcertificatesource = AppCatCertificateSource().factory
220    for cert in appcatcertificatesource.getValues(view.context):
221        selected = ''
222        course = getattr(view.context, coursex)
223        if course is not None and course.code == cert.code:
224            selected = 'selected'
225        title = appcatcertificatesource.getTitle(view.context, cert)
226        yield(dict(code=cert.code, title=title, selected=selected))
227
228def saveCourses(view):
229    """In custom packages we needed to customize the certificate
230    select widget. We just save course1 and course2 if these customized
231    fields appear in the form.
232    """
233    changed_courses = []
234    form = view.request.form
235    course1 = form.get('custom.course1', None)
236    if not course1:
237        return 'Please select your 1st Choice Course of Study.', None
238    cat = queryUtility(ICatalog, name='certificates_catalog')
239    results = list(
240        cat.searchResults(code=(course1, course1)))
241    new_course1 = results[0]
242    old_course1 = view.context.course1
243    if old_course1 != new_course1:
244        view.context.course1 = new_course1
245        changed_courses.append('course1')
246    new_course2 = None
247    old_course2 = view.context.course2
248    course2 = form.get('custom.course2', None)
249    if course2:
250        results = list(
251            cat.searchResults(code=(course2, course2)))
252        new_course2 = results[0]
253    if old_course2 != new_course2:
254        view.context.course2 = new_course2
255        changed_courses.append('course2')
256    return None, changed_courses
257
258def display_fileupload(view, filename):
259    if view.target.startswith('tsc'):
260        return False
261    if filename[1] == 'res_stat.pdf':
262        if view.context.subtype != 'transfer':
263            return False
264    if filename[1] == 'jamb.pdf' \
265        and view.target is not None \
266        and view.target.startswith('pg'):
267        return False
268    if filename[1] == 'nysc.pdf' \
269        and view.target is not None \
270        and not view.target.startswith('pg'):
271        return False
272    return True
273
274class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
275    """A full edit view for applicant data.
276    """
277
278    def getCerts(self, coursex):
279        return getCerts(self, coursex)
280
281    def saveCourses(self):
282        return saveCourses(self)
283
284    def display_fileupload(self, filename):
285        return display_fileupload(self, filename)
286
287    @property
288    def display_refereereports(self):
289        if self.context.refereereports:
290            return True
291        return False
292
293    @property
294    def form_fields(self):
295        self.course_selector = False
296        if self.target is not None and self.target == 'tscf':
297            form_fields = grok.AutoFields(ITranscriptApplicant)
298            for field in TRANS_OMIT_FIELDS:
299                form_fields = form_fields.omit(field)
300            return form_fields
301        if self.target is not None and self.target == 'tscs':
302            form_fields = grok.AutoFields(ITranscriptApplicant)
303            for field in TRANS_SHORT_OMIT_FIELDS:
304                form_fields = form_fields.omit(field)
305            return form_fields
306        self.course_selector = True
307        if self.target is not None and self.target.startswith('pg'):
308            form_fields = grok.AutoFields(ICustomPGApplicant)
309            for field in PG_OMIT_MANAGE_FIELDS:
310                form_fields = form_fields.omit(field)
311        else:
312            form_fields = grok.AutoFields(ICustomUGApplicant)
313            for field in UG_OMIT_MANAGE_FIELDS:
314                form_fields = form_fields.omit(field)
315        if self.target is not None and self.target == 'pre':
316            for field in JUPEB_OMIT_FIELDS:
317                form_fields = form_fields.omit(field)
318        form_fields['student_id'].for_display = True
319        form_fields['applicant_id'].for_display = True
320        return form_fields
321
322class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
323    """An applicant-centered edit view for applicant data.
324    """
325
326    def getCerts(self, coursex):
327        return getCerts(self, coursex)
328
329    def saveCourses(self):
330        return saveCourses(self)
331
332    def display_fileupload(self, filename):
333        return display_fileupload(self, filename)
334
335    @property
336    def _finalsubmit_msg(self):
337        if self.context.subtype in ('transfer', 'de'):
338            return 'Form has been submitted. Please note: DE and Transfer applicants are to present their application form and the proof of JAMB local transfer form at the admissions office for application approval.'
339        return _('Form has been submitted.')
340
341    def dataNotComplete(self, data):
342        store = getUtility(IExtFileStore)
343        if self.context.__parent__.with_picture:
344            store = getUtility(IExtFileStore)
345            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
346                return _('No passport picture uploaded.')
347        if grok.getSite().__name__ == 'iuokada-cdl':
348            return False
349        if self.context.subtype \
350            and self.context.subtype not in ('transfer', 'de', 'jupeb') \
351            and (not self.context.jamb_fname
352                 or not self.context.jamb_reg_number):
353            return _('JAMB fields must be filled.')
354        if self.context.subtype in ('transfer', 'de') \
355            and not self.context.ref_number:
356            return _('Reference Number field must be filled.')
357        if self.context.subtype == 'transfer' \
358            and self.context.__parent__.code!= 'ug2020' \
359            and not store.getFileByContext(self.context, attr=u'res_stat.pdf'):
360            return _('No statement of result pdf file uploaded.')
361        return False
362
363    @property
364    def form_fields(self):
365        self.course_selector = False
366        if self.target is not None and self.target == 'tscf':
367            form_fields = grok.AutoFields(ITranscriptApplicant)
368            for field in TRANS_OMIT_FIELDS:
369                form_fields = form_fields.omit(field)
370                form_fields = form_fields.omit('locked')
371            return form_fields
372        if self.target is not None and self.target == 'tscs':
373            form_fields = grok.AutoFields(ITranscriptApplicant)
374            for field in TRANS_SHORT_OMIT_FIELDS:
375                form_fields = form_fields.omit(field)
376                form_fields = form_fields.omit('locked')
377            return form_fields
378        self.course_selector = True
379        if self.target is not None and self.target.startswith('pg'):
380            form_fields = grok.AutoFields(ICustomPGApplicantEdit)
381            for field in PG_OMIT_EDIT_FIELDS:
382                form_fields = form_fields.omit(field)
383        else:
384            form_fields = grok.AutoFields(ICustomUGApplicantEdit)
385            for field in UG_OMIT_EDIT_FIELDS:
386                form_fields = form_fields.omit(field)
387        if self.target is not None and self.target == 'pre':
388            for field in JUPEB_OMIT_FIELDS:
389                form_fields = form_fields.omit(field)
390        form_fields['applicant_id'].for_display = True
391        form_fields['reg_number'].for_display = True
392        return form_fields
393
394class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
395
396    @property
397    def form_fields(self):
398        if self.target is not None and self.target.startswith('pg'):
399            form_fields = grok.AutoFields(ICustomPGApplicant)
400            for field in PG_OMIT_PDF_FIELDS:
401                form_fields = form_fields.omit(field)
402        else:
403            form_fields = grok.AutoFields(ICustomUGApplicant)
404            for field in UG_OMIT_PDF_FIELDS:
405                form_fields = form_fields.omit(field)
406        if not getattr(self.context, 'student_id'):
407            form_fields = form_fields.omit('student_id')
408        if not getattr(self.context, 'screening_score'):
409            form_fields = form_fields.omit('screening_score')
410        if not getattr(self.context, 'screening_venue'):
411            form_fields = form_fields.omit('screening_venue')
412        if not getattr(self.context, 'screening_date'):
413            form_fields = form_fields.omit('screening_date')
414        return form_fields
415
416class CustomApplicantRegistrationPage(ApplicantRegistrationPage):
417    """Captcha'd registration page for applicants.
418    """
419    @property
420    def form_fields(self):
421        form_fields = None
422        if self.context.mode == 'update':
423            form_fields = grok.AutoFields(ICustomApplicantRegisterUpdate).select(
424                'lastname','reg_number','email')
425        else: #if self.context.mode == 'create':
426            form_fields = grok.AutoFields(ICustomUGApplicant).select(
427                'firstname', 'middlename', 'lastname', 'email', 'phone')
428        return form_fields
429
430class CustomApplicantAddFormPage(ApplicantAddFormPage):
431    """Add-form to add an applicant.
432    """
433    form_fields = grok.AutoFields(ICustomApplicant).select(
434        'firstname', 'middlename', 'lastname',
435        'email', 'phone')
436
437class RefereeReportAddFormPage(RefereeReportAddFormPage):
438    """Add-form to add an referee report. This form
439    is protected by a mandate.
440    """
441    form_fields = grok.AutoFields(
442        ICustomApplicantRefereeReport).omit('creation_date')
443
444class CustomRefereeReportDisplayFormPage(RefereeReportDisplayFormPage):
445    """A display view for referee reports.
446    """
447    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
448    form_fields[
449        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
450
451
452class CustomExportPDFReportSlipPage(ExportPDFReportSlipPage):
453    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
454    form_fields[
455        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
456
457class CustomExportPDFReportSlipPage2(ExportPDFReportSlipPage2):
458    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
459    form_fields[
460        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
461
462class ResultStatement(AdditionalFile):
463    grok.name('res_stat')
464
465class JAMBResult(AdditionalFile):
466    grok.name('jamb')
467
468class FirstSitting(AdditionalFile):
469    grok.name('fst_sit_scan')
470
471class SecondSitting(AdditionalFile):
472    grok.name('scd_sit_scan')
473
474class HighQual(AdditionalFile):
475    grok.name('hq_scan')
476
477class AdvancedLevelResult(AdditionalFile):
478    grok.name('alr_scan')
479
480class NYSCCertificate(AdditionalFile):
481    grok.name('nysc')
482
483class PaymentReceipts(AdditionalFile):
484    grok.name('rmp')
Note: See TracBrowser for help on using the repository browser.