source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/applicants/interfaces.py @ 13264

Last change on this file since 13264 was 13163, checked in by Henrik Bettermann, 10 years ago

Require exactly 4 jamb subjects when saved with the edit form page.

Testing this is a nightmare because the testbrowser does not support Javascript.

  • Property svn:keywords set to Id
File size: 20.7 KB
Line 
1## $Id: interfaces.py 13163 2015-07-12 17:17:48Z 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"""Customized interfaces of the university application package.
19"""
20
21from zope import schema
22from zope.component import getUtility
23from waeup.kofa.applicants.interfaces import (
24    contextual_reg_num_source,
25    IApplicantBaseData,
26    AppCatCertificateSource, CertificateSource)
27from waeup.kofa.schoolgrades import ResultEntryField
28from waeup.kofa.interfaces import (
29    SimpleKofaVocabulary,
30    academic_sessions_vocab,
31    validate_email,
32    SubjectSource,
33    IKofaUtils)
34from waeup.kofa.schema import FormattedDate, TextLineChoice
35from waeup.kofa.students.vocabularies import nats_vocab, GenderSource
36from kofacustom.nigeria.interfaces import (
37    LGASource, high_qual, high_grade, exam_types)
38from kofacustom.nigeria.interfaces import MessageFactory as _
39from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
40
41jambsubjects = SimpleKofaVocabulary(
42    (_('Use of English'),'english_language'),
43    (_('Agricultural Science'),'agricultural_science'),
44    (_('Arabic'),'arabic'),
45    (_('Biology'),'biology'),
46    (_('Book Keeping'),'book_keeping'),
47    (_('Chemistry'),'chemistry'),
48    (_('Christian Religious Studies'),'christian_religious_studies'),
49    (_('Commerce'),'commerce'),
50    (_('Economics'),'economics'),
51    (_('Financial Accounting'),'financial_accounting'),
52    (_('Fine Art'),'fine_art'),
53    (_('Food and Nutrition'),'food_and_nutrition'),
54    (_('French'),'french'),
55    (_('Geography'),'geography'),
56    (_('German'),'german'),
57    (_('Government'),'government'),
58    (_('Hausa'),'hausa'),
59    (_('Home Economics'),'home_economics'),
60    (_('History'),'history'),
61    (_('Igbo'),'igbo'),
62    (_('Literature in English'),'literature_in_english'),
63    (_('Literature in Nigerian Languages'),'literature_in_nigerian_languages'),
64    (_('Mathematics'),'mathematics'),
65    (_('Music'),'music'),
66    (_('Physics'),'physics'),
67    (_('Yoruba'),'yoruba'),
68    )
69
70# Define a validation method for jamb subjects
71class NotExactNumberOfItems(schema.ValidationError):
72    __doc__ = u"Not exactly 4 items selected."
73
74def four_items(value):
75    if len(value) != 4:
76        raise NotExactNumberOfItems(value)
77    return True
78
79class JAMBSubjectSource(SubjectSource):
80    """A source for school subjects used in exam documentation.
81    """
82
83    def getTitle(self, value):
84        subjects_dict = getUtility(IKofaUtils).EXAM_SUBJECTS_DICT
85        return "%s" % subjects_dict[value]
86
87# Fields to be omitted in all display forms. course_admitted is
88# rendered separately.
89
90OMIT_DISPLAY_FIELDS = ('locked', 'course_admitted',
91    'result_uploaded', 'suspended', 'special_application')
92
93# UG students are all undergraduate students.
94UG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + ('jamb_subjects_list',)
95UG_OMIT_PDF_FIELDS = UG_OMIT_DISPLAY_FIELDS + ('phone',)
96UG_OMIT_MANAGE_FIELDS = ('special_application','jamb_subjects_list',)
97UG_OMIT_EDIT_FIELDS = UG_OMIT_MANAGE_FIELDS + OMIT_DISPLAY_FIELDS + (
98    'student_id',
99    'notice',
100    'screening_score',
101    'screening_venue',
102    'screening_date',
103    'jamb_age',
104    'jamb_subjects',
105    'jamb_score',
106    'jamb_reg_number',
107    'aggregate')
108
109# CBT is a subgroup of UG with the same interface.
110CBT_OMIT_FIELDS = (
111    'hq_type', 'hq_matric_no',
112    'hq_degree', 'hq_school',
113    'hq_session', 'hq_disc',
114    'aggregate', 'jamb_subjects')
115CBT_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + CBT_OMIT_FIELDS
116CBT_OMIT_MANAGE_FIELDS = CBT_OMIT_FIELDS + ('special_application',)
117CBT_OMIT_EDIT_FIELDS = OMIT_DISPLAY_FIELDS + CBT_OMIT_FIELDS + (
118    'special_application',
119    'student_id',
120    'notice',
121    'screening_score',
122    'screening_venue',
123    'screening_date',
124    #'jamb_age',
125    #'jamb_subjects',
126    #'jamb_score',
127    #'jamb_reg_number',
128    )
129CBT_OMIT_PDF_FIELDS = CBT_OMIT_DISPLAY_FIELDS + ('phone',)
130
131# PUTME is a subgroup of UG with the same interface.
132PUTME_OMIT_FIELDS = (
133    'hq_type', 'hq_matric_no',
134    'hq_degree', 'hq_school',
135    'hq_session', 'hq_disc', 'jamb_subjects_list')
136PUTME_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + PUTME_OMIT_FIELDS
137PUTME_OMIT_MANAGE_FIELDS = UG_OMIT_MANAGE_FIELDS + PUTME_OMIT_FIELDS
138PUTME_OMIT_EDIT_FIELDS = UG_OMIT_EDIT_FIELDS + PUTME_OMIT_FIELDS + (
139    'firstname', 'middlename', 'lastname', 'sex',
140    'course1', 'lga')
141PUTME_OMIT_PDF_FIELDS = PUTME_OMIT_DISPLAY_FIELDS + ('phone',)
142PUTME_OMIT_RESULT_SLIP_FIELDS = PUTME_OMIT_DISPLAY_FIELDS + (
143    'phone',
144    'date_of_birth', 'sex',
145    'nationality', 'lga', #'perm_address',
146    'course2', 'screening_venue',
147    'screening_date')
148
149# PUDE is a subgroup of UG with the same interface.
150PUDE_OMIT_FIELDS = (
151    'jamb_subjects','jamb_score', 'jamb_age', 'aggregate', 'jamb_subjects_list')
152PUDE_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS + PUDE_OMIT_FIELDS
153PUDE_OMIT_MANAGE_FIELDS = UG_OMIT_MANAGE_FIELDS + PUDE_OMIT_FIELDS
154PUDE_OMIT_EDIT_FIELDS = set(UG_OMIT_EDIT_FIELDS + PUDE_OMIT_FIELDS + (
155    'firstname', 'middlename', 'lastname', 'sex',
156    'course1', 'lga'))
157PUDE_OMIT_PDF_FIELDS = PUDE_OMIT_DISPLAY_FIELDS + ('phone',)
158PUDE_OMIT_RESULT_SLIP_FIELDS = PUDE_OMIT_DISPLAY_FIELDS + (
159    'phone',
160    'date_of_birth', 'sex',
161    'nationality', 'lga', #'perm_address',
162    'course2', 'screening_venue',
163    'screening_date')
164
165# PG has its own interface
166PG_OMIT_DISPLAY_FIELDS = OMIT_DISPLAY_FIELDS
167PG_OMIT_PDF_FIELDS = PG_OMIT_DISPLAY_FIELDS + ('phone',)
168PG_OMIT_MANAGE_FIELDS = ('special_application',)
169PG_OMIT_EDIT_FIELDS = PG_OMIT_MANAGE_FIELDS + PG_OMIT_DISPLAY_FIELDS + (
170    'student_id', 'notice',
171    'screening_score', 'screening_venue',
172    'screening_date',)
173
174class INigeriaUGApplicant(IApplicantBaseData):
175    """An undergraduate applicant.
176
177    This interface defines the least common multiple of all fields
178    in ug application forms. In customized forms, fields can be excluded by
179    adding them to the UG_OMIT* tuples.
180    """
181
182    nationality = schema.Choice(
183        source = nats_vocab,
184        title = _(u'Nationality'),
185        required = False,
186        )
187    lga = schema.Choice(
188        source = LGASource(),
189        title = _(u'State/LGA (Nigerians only)'),
190        required = False,
191        )
192    #perm_address = schema.Text(
193    #    title = _(u'Permanent Address'),
194    #    required = False,
195    #    )
196    course1 = schema.Choice(
197        title = _(u'1st Choice Course of Study'),
198        source = AppCatCertificateSource(),
199        required = True,
200        )
201    course2 = schema.Choice(
202        title = _(u'2nd Choice Course of Study'),
203        source = AppCatCertificateSource(),
204        required = False,
205        )
206    hq_type = schema.Choice(
207        title = _(u'Qualification Obtained'),
208        required = False,
209        readonly = False,
210        vocabulary = high_qual,
211        )
212    hq_matric_no = schema.TextLine(
213        title = _(u'Former Matric Number'),
214        required = False,
215        readonly = False,
216        )
217    hq_degree = schema.Choice(
218        title = _(u'Class of Degree'),
219        required = False,
220        readonly = False,
221        vocabulary = high_grade,
222        )
223    hq_school = schema.TextLine(
224        title = _(u'Institution Attended'),
225        required = False,
226        readonly = False,
227        )
228    hq_session = schema.TextLine(
229        title = _(u'Years Attended'),
230        required = False,
231        readonly = False,
232        )
233    hq_disc = schema.TextLine(
234        title = _(u'Discipline'),
235        required = False,
236        readonly = False,
237        )
238    jamb_subjects = schema.Text(
239        title = _(u'Subjects and Scores'),
240        required = False,
241        )
242    jamb_subjects_list = schema.List(
243        title = _(u'JAMB Subjects'),
244        required = False,
245        default = [],
246        value_type = schema.Choice(
247            vocabulary = jambsubjects
248            #source = JAMBSubjectSource(),
249            ),
250        )
251    jamb_score = schema.Int(
252        title = _(u'Total JAMB Score'),
253        required = False,
254        )
255    #jamb_age = schema.Int(
256    #    title = _(u'Age (provided by JAMB)'),
257    #    required = False,
258    #    )
259    jamb_reg_number = schema.TextLine(
260        title = _(u'JAMB Registration Number'),
261        required = False,
262        )
263    notice = schema.Text(
264        title = _(u'Notice'),
265        required = False,
266        )
267    screening_venue = schema.TextLine(
268        title = _(u'Screening Venue'),
269        required = False,
270        )
271    screening_date = schema.TextLine(
272        title = _(u'Screening Date'),
273        required = False,
274        )
275    screening_score = schema.Int(
276        title = _(u'Screening Score (%)'),
277        required = False,
278        )
279    aggregate = schema.Int(
280        title = _(u'Aggregate Score (%)'),
281        description = _(u'(average of relative JAMB and PUTME scores)'),
282        required = False,
283        )
284    result_uploaded = schema.Bool(
285        title = _(u'Result uploaded'),
286        default = False,
287        required = False,
288        )
289    student_id = schema.TextLine(
290        title = _(u'Student Id'),
291        required = False,
292        readonly = False,
293        )
294    course_admitted = schema.Choice(
295        title = _(u'Admitted Course of Study'),
296        source = CertificateSource(),
297        required = False,
298        )
299    locked = schema.Bool(
300        title = _(u'Form locked'),
301        default = False,
302        required = False,
303        )
304
305INigeriaUGApplicant[
306    'locked'].order =  IApplicantBaseData['suspended'].order
307INigeriaUGApplicant[
308    'result_uploaded'].order =  INigeriaUGApplicant['suspended'].order
309
310class INigeriaPGApplicant(IApplicantBaseData):
311    """A postgraduate applicant.
312
313    This interface defines the least common multiple of all fields
314    in pg application forms. In customized forms, fields can be excluded by
315    adding them to the PG_OMIT* tuples.
316    """
317
318    nationality = schema.Choice(
319        source = nats_vocab,
320        title = _(u'Nationality'),
321        required = True,
322        )
323    lga = schema.Choice(
324        source = LGASource(),
325        title = _(u'State/LGA (Nigerians only)'),
326        required = False,
327        )
328    #perm_address = schema.Text(
329    #    title = _(u'Permanent Address'),
330    #    required = False,
331    #    )
332    course1 = schema.Choice(
333        title = _(u'1st Choice Course of Study'),
334        source = AppCatCertificateSource(),
335        required = True,
336        )
337    course2 = schema.Choice(
338        title = _(u'2nd Choice Course of Study'),
339        source = AppCatCertificateSource(),
340        required = False,
341        )
342    hq_type = schema.Choice(
343        title = _(u'Qualification Obtained'),
344        required = False,
345        readonly = False,
346        vocabulary = high_qual,
347        )
348    hq_matric_no = schema.TextLine(
349        title = _(u'Former Matric Number'),
350        required = False,
351        readonly = False,
352        )
353    hq_degree = schema.Choice(
354        title = _(u'Class of Degree'),
355        required = False,
356        readonly = False,
357        vocabulary = high_grade,
358        )
359    hq_school = schema.TextLine(
360        title = _(u'Institution Attended'),
361        required = False,
362        readonly = False,
363        )
364    hq_session = schema.TextLine(
365        title = _(u'Years Attended'),
366        required = False,
367        readonly = False,
368        )
369    hq_disc = schema.TextLine(
370        title = _(u'Discipline'),
371        required = False,
372        readonly = False,
373        )
374    fst_sit_fname = schema.TextLine(
375        title = _(u'Full Name'),
376        required = False,
377        readonly = False,
378        )
379    fst_sit_no = schema.TextLine(
380        title = _(u'Exam Number'),
381        required = False,
382        readonly = False,
383        )
384    fst_sit_date = FormattedDate(
385        title = _(u'Exam Date'),
386        required = False,
387        readonly = False,
388        show_year = True,
389        )
390    fst_sit_type = schema.Choice(
391        title = _(u'Exam Type'),
392        required = False,
393        readonly = False,
394        vocabulary = exam_types,
395        )
396    fst_sit_results = schema.List(
397        title = _(u'Exam Results'),
398        value_type = ResultEntryField(),
399        required = False,
400        readonly = False,
401        default = [],
402        )
403    scd_sit_fname = schema.TextLine(
404        title = _(u'Full Name'),
405        required = False,
406        readonly = False,
407        )
408    scd_sit_no = schema.TextLine(
409        title = _(u'Exam Number'),
410        required = False,
411        readonly = False,
412        )
413    scd_sit_date = FormattedDate(
414        title = _(u'Exam Date'),
415        required = False,
416        readonly = False,
417        show_year = True,
418        )
419    scd_sit_type = schema.Choice(
420        title = _(u'Exam Type'),
421        required = False,
422        readonly = False,
423        vocabulary = exam_types,
424        )
425    scd_sit_results = schema.List(
426        title = _(u'Exam Results'),
427        value_type = ResultEntryField(),
428        required = False,
429        readonly = False,
430        default = [],
431        )
432    # Replaced by first and second sitting
433    #pp_school = schema.Choice(
434    #    title = _(u'Qualification Obtained'),
435    #    required = False,
436    #    readonly = False,
437    #    vocabulary = exam_types,
438    #    )
439    presently_inst = schema.TextLine(
440        title = _(u'If yes, name of institution'),
441        required = False,
442        readonly = False,
443        )
444    nysc_year = schema.Int(
445        title = _(u'Nysc Year'),
446        required = False,
447        readonly = False,
448        )
449    nysc_lga = schema.Choice(
450        source = LGASource(),
451        title = _(u'Nysc Location'),
452        required = False,
453        )
454    employer = schema.TextLine(
455        title = _(u'Employer'),
456        required = False,
457        readonly = False,
458        )
459    emp_position = schema.TextLine(
460        title = _(u'Employer Position'),
461        required = False,
462        readonly = False,
463        )
464    emp_start = FormattedDate(
465        title = _(u'Start Date'),
466        required = False,
467        readonly = False,
468        show_year = True,
469        )
470    emp_end = FormattedDate(
471        title = _(u'End Date'),
472        required = False,
473        readonly = False,
474        show_year = True,
475        )
476    emp_reason = schema.TextLine(
477        title = _(u'Reason for Leaving'),
478        required = False,
479        readonly = False,
480        )
481    employer2 = schema.TextLine(
482        title = _(u'2nd Employer'),
483        required = False,
484        readonly = False,
485        )
486    emp2_position = schema.TextLine(
487        title = _(u'2nd Employer Position'),
488        required = False,
489        readonly = False,
490        )
491    emp2_start = FormattedDate(
492        title = _(u'Start Date'),
493        required = False,
494        readonly = False,
495        show_year = True,
496        )
497    emp2_end = FormattedDate(
498        title = _(u'End Date'),
499        required = False,
500        readonly = False,
501        show_year = True,
502        )
503    emp2_reason = schema.TextLine(
504        title = _(u'Reason for Leaving'),
505        required = False,
506        readonly = False,
507        )
508    notice = schema.Text(
509        title = _(u'Notice'),
510        required = False,
511        readonly = False,
512        )
513    screening_venue = schema.TextLine(
514        title = _(u'Screening Venue'),
515        required = False,
516        )
517    screening_date = schema.TextLine(
518        title = _(u'Screening Date'),
519        required = False,
520        )
521    screening_score = schema.Int(
522        title = _(u'Screening Score (%)'),
523        required = False,
524        )
525    student_id = schema.TextLine(
526        title = _(u'Student Id'),
527        required = False,
528        readonly = False,
529        )
530    course_admitted = schema.Choice(
531        title = _(u'Admitted Course of Study'),
532        source = CertificateSource(),
533        required = False,
534        readonly = False,
535        )
536    locked = schema.Bool(
537        title = _(u'Form locked'),
538        default = False,
539        required = False,
540        )
541
542INigeriaPGApplicant[
543    'locked'].order =  IApplicantBaseData['suspended'].order
544
545class INigeriaApplicant(INigeriaUGApplicant, INigeriaPGApplicant):
546    """An interface for both types of applicants.
547
548    Attention: The INigeriaPGApplicant field seetings will be overwritten
549    by INigeriaPGApplicant field settings. If a field is defined
550    in both interfaces zope.schema validates only against the
551    constraints in INigeriaUGApplicant. This does not affect the forms
552    since they are build on either INigeriaUGApplicant or INigeriaPGApplicant.
553    """
554
555    def writeLogMessage(view, comment):
556        """Adds an INFO message to the log file
557        """
558
559    def createStudent():
560        """Create a student object from applicant data
561        and copy applicant object.
562        """
563
564class INigeriaUGApplicantEdit(INigeriaUGApplicant):
565    """An undergraduate applicant interface for edit forms.
566
567    Here we can repeat the fields from base data and set the
568    `required` and `readonly` attributes to True to further restrict
569    the data access. Or we can allow only certain certificates to be
570    selected by choosing the appropriate source.
571
572    We cannot omit fields here. This has to be done in the
573    respective form page.
574    """
575
576    email = schema.ASCIILine(
577        title = _(u'Email Address'),
578        required = True,
579        constraint=validate_email,
580        )
581    date_of_birth = FormattedDate(
582        title = _(u'Date of Birth'),
583        required = True,
584        show_year = True,
585        )
586    jamb_subjects_list = schema.List(
587        title = _(u'JAMB Subjects'),
588        description = _(u'Select four subjects.'),
589        required = True,
590        constraint = four_items,
591        value_type = schema.Choice(
592            vocabulary = jambsubjects
593            #source = JAMBSubjectSource(),
594            ),
595        )
596
597INigeriaUGApplicantEdit[
598    'date_of_birth'].order = INigeriaUGApplicant['date_of_birth'].order
599INigeriaUGApplicantEdit[
600    'email'].order = INigeriaUGApplicant['email'].order
601INigeriaUGApplicantEdit[
602    'jamb_subjects_list'].order = INigeriaUGApplicant['jamb_subjects_list'].order
603
604class INigeriaPGApplicantEdit(INigeriaPGApplicant):
605    """A postgraduate applicant interface for editing.
606
607    Here we can repeat the fields from base data and set the
608    `required` and `readonly` attributes to True to further restrict
609    the data access. Or we can allow only certain certificates to be
610    selected by choosing the appropriate source.
611
612    We cannot omit fields here. This has to be done in the
613    respective form page.
614    """
615
616    email = schema.ASCIILine(
617        title = _(u'Email Address'),
618        required = True,
619        constraint=validate_email,
620        )
621    date_of_birth = FormattedDate(
622        title = _(u'Date of Birth'),
623        required = True,
624        show_year = True,
625        )
626
627INigeriaPGApplicantEdit[
628    'date_of_birth'].order =  INigeriaPGApplicant['date_of_birth'].order
629INigeriaPGApplicantEdit[
630    'email'].order =  INigeriaPGApplicant['email'].order
631
632class INigeriaApplicantOnlinePayment(INigeriaOnlinePayment):
633    """An applicant payment via payment gateways.
634    """
635
636class IPUTMEApplicantEdit(INigeriaUGApplicant):
637    """An undergraduate applicant interface for editing.
638
639    Here we can repeat the fields from base data and set the
640    `required` and `readonly` attributes to True to further restrict
641    the data access. Or we can allow only certain certificates to be
642    selected by choosing the appropriate source.
643
644    We cannot omit fields here. This has to be done in the
645    respective form page.
646    """
647    email = schema.ASCIILine(
648        title = _(u'Email Address'),
649        required = True,
650        constraint=validate_email,
651        )
652    date_of_birth = FormattedDate(
653        title = _(u'Date of Birth'),
654        required = True,
655        show_year = True,
656        )
657    nationality = schema.Choice(
658        source = nats_vocab,
659        title = _(u'Nationality'),
660        required = True,
661        )
662
663IPUTMEApplicantEdit[
664    'date_of_birth'].order =  INigeriaUGApplicant['date_of_birth'].order
665IPUTMEApplicantEdit[
666    'email'].order =  INigeriaUGApplicant['email'].order
667IPUTMEApplicantEdit[
668    'nationality'].order =  INigeriaUGApplicant['nationality'].order
669
670class INigeriaApplicantUpdateByRegNo(INigeriaApplicant):
671    """Representation of an applicant.
672
673    Skip regular reg_number validation if reg_number is used for finding
674    the applicant object.
675    """
676    reg_number = schema.TextLine(
677        title = u'Registration Number',
678        required = False,
679        )
Note: See TracBrowser for help on using the repository browser.