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

Last change on this file since 16631 was 16566, checked in by Henrik Bettermann, 3 years ago

Finetune requirements for submission.

  • Property svn:keywords set to Id
File size: 16.9 KB
Line 
1## $Id: browser.py 16566 2021-08-12 06:40:29Z 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') \
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.__parent__.with_picture:
338            store = getUtility(IExtFileStore)
339            if not store.getFileByContext(self.context, attr=u'passport.jpg'):
340                return _('No passport picture uploaded.')
341        if self.context.subtype == 'transfer' \
342            and self.context.__parent__.code!= 'ug2020' \
343            and not store.getFileByContext(self.context, attr=u'res_stat.pdf'):
344            return _('No statement of result pdf file uploaded.')
345        return False
346
347    @property
348    def form_fields(self):
349        self.course_selector = False
350        if self.target is not None and self.target == 'tscf':
351            form_fields = grok.AutoFields(ITranscriptApplicant)
352            for field in TRANS_OMIT_FIELDS:
353                form_fields = form_fields.omit(field)
354                form_fields = form_fields.omit('locked')
355            return form_fields
356        if self.target is not None and self.target == 'tscs':
357            form_fields = grok.AutoFields(ITranscriptApplicant)
358            for field in TRANS_SHORT_OMIT_FIELDS:
359                form_fields = form_fields.omit(field)
360                form_fields = form_fields.omit('locked')
361            return form_fields
362        self.course_selector = True
363        if self.target is not None and self.target.startswith('pg'):
364            form_fields = grok.AutoFields(ICustomPGApplicantEdit)
365            for field in PG_OMIT_EDIT_FIELDS:
366                form_fields = form_fields.omit(field)
367        else:
368            form_fields = grok.AutoFields(ICustomUGApplicantEdit)
369            for field in UG_OMIT_EDIT_FIELDS:
370                form_fields = form_fields.omit(field)
371        if self.target is not None and self.target == 'pre':
372            for field in JUPEB_OMIT_FIELDS:
373                form_fields = form_fields.omit(field)
374        form_fields['applicant_id'].for_display = True
375        form_fields['reg_number'].for_display = True
376        return form_fields
377
378class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):
379
380    @property
381    def form_fields(self):
382        if self.target is not None and self.target.startswith('pg'):
383            form_fields = grok.AutoFields(ICustomPGApplicant)
384            for field in PG_OMIT_PDF_FIELDS:
385                form_fields = form_fields.omit(field)
386        else:
387            form_fields = grok.AutoFields(ICustomUGApplicant)
388            for field in UG_OMIT_PDF_FIELDS:
389                form_fields = form_fields.omit(field)
390        if not getattr(self.context, 'student_id'):
391            form_fields = form_fields.omit('student_id')
392        if not getattr(self.context, 'screening_score'):
393            form_fields = form_fields.omit('screening_score')
394        if not getattr(self.context, 'screening_venue'):
395            form_fields = form_fields.omit('screening_venue')
396        if not getattr(self.context, 'screening_date'):
397            form_fields = form_fields.omit('screening_date')
398        return form_fields
399
400class CustomApplicantRegistrationPage(ApplicantRegistrationPage):
401    """Captcha'd registration page for applicants.
402    """
403    @property
404    def form_fields(self):
405        form_fields = None
406        if self.context.mode == 'update':
407            form_fields = grok.AutoFields(ICustomApplicantRegisterUpdate).select(
408                'lastname','reg_number','email')
409        else: #if self.context.mode == 'create':
410            form_fields = grok.AutoFields(ICustomUGApplicant).select(
411                'firstname', 'middlename', 'lastname', 'email', 'phone')
412        return form_fields
413
414class CustomApplicantAddFormPage(ApplicantAddFormPage):
415    """Add-form to add an applicant.
416    """
417    form_fields = grok.AutoFields(ICustomApplicant).select(
418        'firstname', 'middlename', 'lastname',
419        'email', 'phone')
420
421class RefereeReportAddFormPage(RefereeReportAddFormPage):
422    """Add-form to add an referee report. This form
423    is protected by a mandate.
424    """
425    form_fields = grok.AutoFields(
426        ICustomApplicantRefereeReport).omit('creation_date')
427
428class CustomRefereeReportDisplayFormPage(RefereeReportDisplayFormPage):
429    """A display view for referee reports.
430    """
431    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
432    form_fields[
433        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
434
435
436class CustomExportPDFReportSlipPage(ExportPDFReportSlipPage):
437    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
438    form_fields[
439        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
440
441class CustomExportPDFReportSlipPage2(ExportPDFReportSlipPage2):
442    form_fields = grok.AutoFields(ICustomApplicantRefereeReport)
443    form_fields[
444        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
445
446class ResultStatement(AdditionalFile):
447    grok.name('res_stat')
448
449class JAMBResult(AdditionalFile):
450    grok.name('jamb')
451
452class FirstSitting(AdditionalFile):
453    grok.name('fst_sit_scan')
454
455class SecondSitting(AdditionalFile):
456    grok.name('scd_sit_scan')
457
458class HighQual(AdditionalFile):
459    grok.name('hq_scan')
460
461class AdvancedLevelResult(AdditionalFile):
462    grok.name('alr_scan')
463
464class NYSCCertificate(AdditionalFile):
465    grok.name('nysc')
466
467class PaymentReceipts(AdditionalFile):
468    grok.name('rmp')
Note: See TracBrowser for help on using the repository browser.