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

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

Add upload viewlet.

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