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

Last change on this file since 16958 was 16958, checked in by Henrik Bettermann, 2 years ago

Add ref_number field.

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