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

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

Customize max_applicants.

  • Property svn:keywords set to Id
File size: 15.7 KB
Line 
1## $Id: browser.py 16328 2020-11-21 14:31:21Z 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)
33from waeup.kofa.applicants.interfaces import (
34    ISpecialApplicant, IApplicantsContainer, AppCatCertificateSource)
35from kofacustom.nigeria.applicants.browser import (
36    NigeriaApplicantDisplayFormPage,
37    NigeriaApplicantManageFormPage,
38    NigeriaApplicantEditFormPage,
39    NigeriaPDFApplicationSlip)
40from waeup.kofa.widgets.datewidget import (
41    FriendlyDateDisplayWidget,
42    FriendlyDatetimeDisplayWidget)
43from kofacustom.nigeria.applicants.interfaces import (
44    OMIT_DISPLAY_FIELDS,
45    #UG_OMIT_DISPLAY_FIELDS,
46    #UG_OMIT_PDF_FIELDS,
47    #UG_OMIT_MANAGE_FIELDS,
48    #UG_OMIT_EDIT_FIELDS,
49    #PG_OMIT_DISPLAY_FIELDS,
50    #PG_OMIT_PDF_FIELDS,
51    #PG_OMIT_MANAGE_FIELDS,
52    #PG_OMIT_EDIT_FIELDS,
53    )
54from kofacustom.iuokada.applicants.interfaces import (
55    ICustomPGApplicant, ICustomUGApplicant, ICustomApplicant,
56    ICustomPGApplicantEdit, ICustomUGApplicantEdit,
57    ICustomApplicantOnlinePayment, ICustomApplicantRefereeReport,
58    ITranscriptApplicant, ICustomApplicantRegisterUpdate
59    )
60from kofacustom.iuokada.interfaces import MessageFactory as _
61
62MAX_FILE_UPLOAD_SIZE = 1024 * 500
63
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',
72    'programme_type',
73    'course1',
74    'course2',)
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',
85    'aggregate',
86    )
87
88# PG has its own interface
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    )
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',
114    'course1',
115    'course2',
116    )
117PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + PG_OMIT_DISPLAY_FIELDS + (
118    'student_id',
119    'notice',
120    'screening_score',
121    'screening_venue',
122    'screening_date',)
123
124TRANS_OMIT_FIELDS = ('suspended', 'applicant_id',)
125
126TRANS_SHORT_OMIT_FIELDS = TRANS_OMIT_FIELDS + (
127    #'date_of_birth',
128    'sex',
129    'nationality',
130    #'entry_mode',
131    #'entry_session',
132    'end_session',
133    #'course_studied',
134    #'course_changed',
135    #'change_level',
136    )
137
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',
150                'application_slip_notice',
151                'application_fee', 'with_picture',
152                'startdate', 'enddate')
153        return form_fields
154
155class CustomApplicantsContainerManageFormPage(ApplicantsContainerManageFormPage):
156
157    max_applicants = 3000
158
159class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
160    """A display view for applicant data.
161    """
162
163    @property
164    def form_fields(self):
165        if self.target is not None and self.target == 'tscf':
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
170            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
171            return form_fields
172        if self.target is not None and self.target == 'tscs':
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
177            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
178            return form_fields
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)
183        else:
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')
197        return form_fields
198
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
210def saveCourses(view):
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    """
215    changed_courses = []
216    form = view.request.form
217    course1 = form.get('custom.course1', None)
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
230    course2 = form.get('custom.course2', None)
231    if course2:
232        results = list(
233            cat.searchResults(code=(course2, course2)))
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
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
256class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
257    """A full edit view for applicant data.
258    """
259
260    def getCerts(self, coursex):
261        return getCerts(self, coursex)
262
263    def saveCourses(self):
264        return saveCourses(self)
265
266    def display_fileupload(self, filename):
267        return display_fileupload(self, filename)
268
269    @property
270    def display_refereereports(self):
271        if self.context.refereereports:
272            return True
273        return False
274
275    @property
276    def form_fields(self):
277        self.course_selector = False
278        if self.target is not None and self.target == 'tscf':
279            form_fields = grok.AutoFields(ITranscriptApplicant)
280            for field in TRANS_OMIT_FIELDS:
281                form_fields = form_fields.omit(field)
282            return form_fields
283        if self.target is not None and self.target == 'tscs':
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
288        self.course_selector = True
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
305    def getCerts(self, coursex):
306        return getCerts(self, coursex)
307
308    def saveCourses(self):
309        return saveCourses(self)
310
311    def display_fileupload(self, filename):
312        return display_fileupload(self, filename)
313
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.')
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'):
323            return _('No statement of result pdf file uploaded.')
324        return False
325
326    @property
327    def form_fields(self):
328        self.course_selector = False
329        if self.target is not None and self.target == 'tscf':
330            form_fields = grok.AutoFields(ITranscriptApplicant)
331            for field in TRANS_OMIT_FIELDS:
332                form_fields = form_fields.omit(field)
333                form_fields = form_fields.omit('locked')
334            return form_fields
335        if self.target is not None and self.target == 'tscs':
336            form_fields = grok.AutoFields(ITranscriptApplicant)
337            for field in TRANS_SHORT_OMIT_FIELDS:
338                form_fields = form_fields.omit(field)
339                form_fields = form_fields.omit('locked')
340            return form_fields
341        self.course_selector = True
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
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
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
415class ResultStatement(AdditionalFile):
416    grok.name('res_stat.pdf')
417
418class JAMBResult(AdditionalFile):
419    grok.name('jamb.pdf')
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')
429
430class AdvancedLevelResult(AdditionalFile):
431    grok.name('alr_scan.pdf')
432
433class NYSCCertificate(AdditionalFile):
434    grok.name('nysc.pdf')
Note: See TracBrowser for help on using the repository browser.