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

Last change on this file since 16276 was 16276, checked in by Henrik Bettermann, 4 years ago

Email addresses must be unique in IUO.

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