source: main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/applicants/interfaces.py @ 16142

Last change on this file since 16142 was 16142, checked in by Henrik Bettermann, 5 years ago

Implement transcript application.

  • Property svn:keywords set to Id
File size: 21.7 KB
Line 
1# -*- coding: utf-8 -*-
2## $Id: interfaces.py 16142 2020-07-03 07:11:31Z henrik $
3##
4## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
5## This program is free software; you can redistribute it and/or modify
6## it under the terms of the GNU General Public License as published by
7## the Free Software Foundation; either version 2 of the License, or
8## (at your option) any later version.
9##
10## This program is distributed in the hope that it will be useful,
11## but WITHOUT ANY WARRANTY; without even the implied warranty of
12## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13## GNU General Public License for more details.
14##
15## You should have received a copy of the GNU General Public License
16## along with this program; if not, write to the Free Software
17## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18##
19"""Customized interfaces of the university application package.
20"""
21
22from zope import schema
23from zc.sourcefactory.basic import BasicSourceFactory
24from waeup.kofa.applicants.interfaces import (
25    IApplicantBaseData,
26    AppCatCertificateSource, CertificateSource)
27from waeup.kofa.schoolgrades import ResultEntryField
28from waeup.kofa.university.vocabularies import StudyModeSource
29from waeup.kofa.interfaces import (
30    SimpleKofaVocabulary, academic_sessions_vocab, validate_email,
31    IKofaObject)
32from waeup.kofa.schema import FormattedDate, TextLineChoice, PhoneNumber
33from waeup.kofa.students.vocabularies import (
34    nats_vocab, GenderSource, StudyLevelSource)
35from waeup.kofa.applicants.interfaces import (
36    contextual_reg_num_source, IApplicantBaseData, IApplicantRefereeReport)
37from waeup.kofa.refereeentries import RefereeEntryField
38from kofacustom.nigeria.applicants.interfaces import (
39    LGASource, high_qual, high_grade, exam_types, DisabilitiesSource,
40    programme_types_vocab, jambsubjects, validate_jamb_reg_number,
41    INigeriaUGApplicant, INigeriaPGApplicant,
42    INigeriaApplicantOnlinePayment,
43    INigeriaUGApplicantEdit, INigeriaPGApplicantEdit,
44    INigeriaApplicantUpdateByRegNo,
45    IPUTMEApplicantEdit,
46    )
47from kofacustom.iuokada.interfaces import MessageFactory as _
48from kofacustom.iuokada.payments.interfaces import ICustomOnlinePayment
49
50sponsors_vocab = SimpleKofaVocabulary(
51    (_('Bauchi Government'), 'bauchi'),
52    (_('Company'), 'company'),
53    (_('Federal Government of Nigeria'), 'federalgov'),
54    #(_('Dangote Group'), 'dangote'),
55    (_('Kano Government'), 'kano'),
56    (_('Parent/Guardian'), 'parent'),
57    (_('Rosula Organization'), 'rosula'),
58    (_('Self'), 'self'),
59    #(_('Social Impact Project'), 'social'),
60    )
61
62heard_about_types_vocab = SimpleKofaVocabulary(
63    (_('Facebook/Twitter/Other Social Media'), 'socmedia'),
64    (_('From a Friend'), 'friend'),
65    (_('Newspaper Advertisement'), 'newspaper'),
66    (_('Radio Advertisement'), 'radio'),
67    (_('Television Advertisement'), 'television'),
68    (_('SMS'), 'sms'),
69    )
70
71subtype_vocab = SimpleKofaVocabulary(
72    (_('UTME'), 'utme'),
73    (_('Direct Entry'), 'de'),
74    (_('Inter Uni Transfer'), 'transfer'),
75    )
76
77rating_vocab = SimpleKofaVocabulary(
78    (_('Excellent'), 'e'),
79    (_('Very good'), 'vg'),
80    (_('Good'), 'g'),
81    (_('Slightly above average'), 'saa'),
82    (_('Average'), 'a'),
83    (_('Below average'), 'ba'),
84    (_('Unable to assess'), 'unable'),
85    )
86
87
88overallpromise_vocab = SimpleKofaVocabulary(
89    (_('Very good (highest 10%)'), 'vg'),
90    (_('Above average (next 15%)'), 'aa'),
91    (_('Average (middle 20%)'), 'a'),
92    (_('Below average (middle 40%)'), 'ba'),
93    )
94
95DESTINATION_COST = {
96    'none': ('To the moon', 1000000000.0, 1),
97    #'nigeria': ('Nigeria', 2000.0, 1),
98    #'africa': ('Africa ', 3000.0, 2),
99    #'eurasia': ('Europe/Asia ', 3000.0, 3),
100    }
101
102class DestinationCostSource(BasicSourceFactory):
103    """A source that delivers continents and shipment costs.
104    """
105    def getValues(self):
106        sorted_items = sorted(DESTINATION_COST.items(),
107                              key=lambda element: element[1][2])
108        return [item[0] for item in sorted_items]
109
110    def getTitle(self, value):
111        return u"%s (₦ %s)" % (
112            DESTINATION_COST[value][0],
113            DESTINATION_COST[value][1])
114
115class ICustomUGApplicant(IApplicantBaseData):
116    """An undergraduate applicant.
117
118    This interface defines the least common multiple of all fields
119    in ug application forms. In customized forms, fields can be excluded by
120    adding them to the UG_OMIT* tuples.
121    """
122
123    subtype = schema.Choice(
124        title = _(u'Application Subtype'),
125        vocabulary = subtype_vocab,
126        required = False,
127        )
128    disabilities = schema.Choice(
129        title = _(u'Disability'),
130        source = DisabilitiesSource(),
131        required = False,
132        )
133    nationality = schema.Choice(
134        source = nats_vocab,
135        title = _(u'Nationality'),
136        required = False,
137        )
138    lga = schema.Choice(
139        source = LGASource(),
140        title = _(u'State/LGA (Nigerians only)'),
141        required = False,
142        )
143    sponsor = schema.Choice(
144        title = _(u'Sponsor'),
145        vocabulary = sponsors_vocab,
146        required = False,
147        )
148    heard_about = schema.Choice(
149        title = _(u'How did you hear about IUO?'),
150        vocabulary = heard_about_types_vocab,
151        required = False,
152        )
153    #perm_address = schema.Text(
154    #    title = _(u'Permanent Address'),
155    #    required = False,
156    #    )
157    parents_name = schema.TextLine(
158        title = _(u'Full Name'),
159        required = False,
160        readonly = False,
161        )
162    parents_email = schema.ASCIILine(
163        title = _(u'Email Address'),
164        required = False,
165        constraint=validate_email,
166        )
167    parents_phone = PhoneNumber(
168        title = _(u'Phone'),
169        required = False,
170        )
171    course1 = schema.Choice(
172        title = _(u'1st Choice Course of Study'),
173        source = AppCatCertificateSource(),
174        required = True,
175        )
176    course2 = schema.Choice(
177        title = _(u'2nd Choice Course of Study'),
178        source = AppCatCertificateSource(),
179        required = False,
180        )
181    programme_type = schema.Choice(
182        title = _(u'Programme Type'),
183        vocabulary = programme_types_vocab,
184        required = False,
185        )
186    fst_sit_fname = schema.TextLine(
187        title = _(u'Full Name'),
188        required = False,
189        readonly = False,
190        )
191    fst_sit_no = schema.TextLine(
192        title = _(u'Exam Number'),
193        required = False,
194        readonly = False,
195        )
196    fst_sit_date = FormattedDate(
197        title = _(u'Exam Date'),
198        required = False,
199        readonly = False,
200        show_year = True,
201        )
202    fst_sit_type = schema.Choice(
203        title = _(u'Exam Type'),
204        required = False,
205        readonly = False,
206        vocabulary = exam_types,
207        )
208    fst_sit_results = schema.List(
209        title = _(u'Exam Results'),
210        value_type = ResultEntryField(),
211        required = False,
212        readonly = False,
213        defaultFactory=list,
214        )
215    scd_sit_fname = schema.TextLine(
216        title = _(u'Full Name'),
217        required = False,
218        readonly = False,
219        )
220    scd_sit_no = schema.TextLine(
221        title = _(u'Exam Number'),
222        required = False,
223        readonly = False,
224        )
225    scd_sit_date = FormattedDate(
226        title = _(u'Exam Date'),
227        required = False,
228        readonly = False,
229        show_year = True,
230        )
231    scd_sit_type = schema.Choice(
232        title = _(u'Exam Type'),
233        required = False,
234        readonly = False,
235        vocabulary = exam_types,
236        )
237    scd_sit_results = schema.List(
238        title = _(u'Exam Results'),
239        value_type = ResultEntryField(),
240        required = False,
241        readonly = False,
242        defaultFactory=list,
243        )
244    hq_type = schema.Choice(
245        title = _(u'Qualification Obtained'),
246        required = False,
247        readonly = False,
248        vocabulary = high_qual,
249        )
250    hq_matric_no = schema.TextLine(
251        title = _(u'Former Matric Number'),
252        required = False,
253        readonly = False,
254        )
255    hq_degree = schema.Choice(
256        title = _(u'Class of Degree'),
257        required = False,
258        readonly = False,
259        vocabulary = high_grade,
260        )
261    hq_school = schema.TextLine(
262        title = _(u'Institution Attended'),
263        required = False,
264        readonly = False,
265        )
266    hq_session = schema.TextLine(
267        title = _(u'Years Attended'),
268        required = False,
269        readonly = False,
270        )
271    hq_disc = schema.TextLine(
272        title = _(u'Discipline'),
273        required = False,
274        readonly = False,
275        )
276    #jamb_subjects = schema.Text(
277    #    title = _(u'Subjects and Scores'),
278    #    required = False,
279    #    )
280    jamb_subjects_list = schema.List(
281        title = _(u'JAMB Subjects'),
282        required = False,
283        defaultFactory=list,
284        value_type = schema.Choice(
285            vocabulary = jambsubjects
286            #source = JAMBSubjectSource(),
287            ),
288        )
289    jamb_score = schema.Int(
290        title = _(u'Total JAMB Score'),
291        required = False,
292        )
293    #jamb_age = schema.Int(
294    #    title = _(u'Age (provided by JAMB)'),
295    #    required = False,
296    #    )
297    jamb_reg_number = schema.TextLine(
298        title = _(u'JAMB Registration Number'),
299        required = False,
300        constraint=validate_jamb_reg_number,
301        )
302    notice = schema.Text(
303        title = _(u'Notice'),
304        required = False,
305        )
306    screening_venue = schema.TextLine(
307        title = _(u'Screening Venue'),
308        required = False,
309        )
310    screening_date = schema.TextLine(
311        title = _(u'Screening Date'),
312        required = False,
313        )
314    screening_score = schema.Int(
315        title = _(u'Screening Score (%)'),
316        required = False,
317        )
318    aggregate = schema.Int(
319        title = _(u'Aggregate Score (%)'),
320        description = _(u'(average of relative JAMB and PUTME scores)'),
321        required = False,
322        )
323    result_uploaded = schema.Bool(
324        title = _(u'Result uploaded'),
325        default = False,
326        required = False,
327        )
328    student_id = schema.TextLine(
329        title = _(u'Student Id'),
330        required = False,
331        readonly = False,
332        )
333    course_admitted = schema.Choice(
334        title = _(u'Admitted Course of Study'),
335        source = CertificateSource(),
336        required = False,
337        )
338    locked = schema.Bool(
339        title = _(u'Form locked'),
340        default = False,
341        required = False,
342        )
343
344ICustomUGApplicant[
345    'subtype'].order =  ICustomUGApplicant['lga'].order
346ICustomUGApplicant[
347    'locked'].order =  ICustomUGApplicant['suspended'].order
348ICustomUGApplicant[
349    'result_uploaded'].order =  ICustomUGApplicant['suspended'].order
350
351class ICustomPGApplicant(INigeriaPGApplicant):
352    """A postgraduate applicant.
353
354    This interface defines the least common multiple of all fields
355    in pg application forms. In customized forms, fields can be excluded by
356    adding them to the PG_OMIT* tuples.
357    """
358
359    sponsor = schema.Choice(
360        title = _(u'Sponsor'),
361        vocabulary = sponsors_vocab,
362        required = False,
363        )
364
365    heard_about = schema.Choice(
366        title = _(u'How did you hear about IU?'),
367        vocabulary = heard_about_types_vocab,
368        required = False,
369        )
370
371    nysc_number = schema.Int(
372        title = _(u'Nysc Number'),
373        required = False,
374        readonly = False,
375        )
376
377    referees = schema.List(
378        title = _(u'Referees'),
379        value_type = RefereeEntryField(),
380        required = False,
381        defaultFactory=list,
382        )
383
384ICustomPGApplicant[
385    'referees'].order =  INigeriaPGApplicant['emp2_reason'].order
386ICustomPGApplicant[
387    'sponsor'].order =  ICustomPGApplicant['lga'].order
388ICustomPGApplicant[
389    'heard_about'].order =  ICustomPGApplicant['lga'].order
390ICustomPGApplicant[
391    'sponsor'].order =  ICustomPGApplicant['lga'].order
392ICustomPGApplicant[
393    'lga'].order =  ICustomPGApplicant['nationality'].order
394ICustomPGApplicant[
395    'nysc_number'].order =  ICustomPGApplicant['nysc_year'].order
396
397class ITranscriptApplicant(IKofaObject):
398    """A transcript applicant.
399    """
400
401    suspended = schema.Bool(
402        title = _(u'Account suspended'),
403        default = False,
404        required = False,
405        )
406
407    locked = schema.Bool(
408        title = _(u'Form locked'),
409        default = False,
410        required = False,
411        )
412
413    applicant_id = schema.TextLine(
414        title = _(u'Transcript Application Id'),
415        required = False,
416        readonly = False,
417        )
418
419    #student_id = schema.TextLine(
420    #    title = _(u'Kofa Student Id'),
421    #    required = False,
422    #    readonly = False,
423    #    )
424
425    #reg_number = schema.TextLine(
426    #    title = _(u'Registration Number'),
427    #    readonly = False,
428    #    required = False,
429    #    )
430
431    matric_number = schema.TextLine(
432        title = _(u'Matriculation Number'),
433        readonly = False,
434        required = True,
435        )
436
437    firstname = schema.TextLine(
438        title = _(u'First Name'),
439        required = True,
440        )
441
442    middlename = schema.TextLine(
443        title = _(u'Middle Name'),
444        required = False,
445        )
446
447    lastname = schema.TextLine(
448        title = _(u'Last Name (Surname)'),
449        required = True,
450        )
451
452    date_of_birth = FormattedDate(
453        title = _(u'Date of Birth'),
454        required = False,
455        #date_format = u'%d/%m/%Y', # Use grok-instance-wide default
456        show_year = True,
457        )
458
459    sex = schema.Choice(
460        title = _(u'Gender'),
461        source = GenderSource(),
462        required = True,
463        )
464
465    nationality = schema.Choice(
466        vocabulary = nats_vocab,
467        title = _(u'Nationality'),
468        required = False,
469        )
470
471    email = schema.ASCIILine(
472        title = _(u'Email Address'),
473        required = True,
474        constraint=validate_email,
475        )
476
477    phone = PhoneNumber(
478        title = _(u'Phone'),
479        description = u'',
480        required = False,
481        )
482
483    perm_address = schema.Text(
484        title = _(u'Current Local Address'),
485        required = False,
486        readonly = False,
487        )
488
489    dispatch_address = schema.Text(
490        title = _(u'Dispatch Addresses'),
491        description = u'Addresses to which transcripts should be posted. '
492                       'Addresses must involve same courier charges.',
493        required = False,
494        readonly = False,
495        )
496
497    charge = schema.Choice(
498        title = _(u'Courier Charge'),
499        source = DestinationCostSource(),
500        required = True,
501        )
502
503    entry_mode = schema.Choice(
504        title = _(u'Entry Mode'),
505        source = StudyModeSource(),
506        required = False,
507        readonly = False,
508        )
509
510    entry_session = schema.Choice(
511        title = _(u'Entry Session'),
512        source = academic_sessions_vocab,
513        required = False,
514        readonly = False,
515        )
516
517    end_session = schema.Choice(
518        title = _(u'End Session'),
519        source = academic_sessions_vocab,
520        required = False,
521        readonly = False,
522        )
523
524    course_studied = schema.Choice(
525        title = _(u'Course of Study / Degree'),
526        source = CertificateSource(),
527        required = False,
528        readonly = False,
529        )
530
531    course_changed = schema.Choice(
532        title = _(u'Change of Study Course'),
533        description = u'If yes, select previous course of study.',
534        source = CertificateSource(),
535        readonly = False,
536        required = False,
537        )
538
539    change_level = schema.Choice(
540        title = _(u'Change Level'),
541        description = u'If yes, select level at which you changed course of study.',
542        source = StudyLevelSource(),
543        required = False,
544        readonly = False,
545        )
546
547    no_copies = schema.Choice(
548        title = _(u'Number of Copies'),
549        description = u'Must correspond with the number of dispatch addresses above.',
550        values=[1, 2, 3, 4],
551        required = False,
552        readonly = False,
553        default = 1,
554        )
555
556class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant,
557    ITranscriptApplicant):
558    """An interface for both types of applicants.
559
560    Attention: The ICustomPGApplicant field seetings will be overwritten
561    by ICustomPGApplicant field settings. If a field is defined
562    in both interfaces zope.schema validates only against the
563    constraints in ICustomUGApplicant. This does not affect the forms
564    since they are build on either ICustomUGApplicant or ICustomPGApplicant.
565    """
566
567    def writeLogMessage(view, comment):
568        """Adds an INFO message to the log file
569        """
570
571    def createStudent():
572        """Create a student object from applicant data
573        and copy applicant object.
574        """
575
576class ICustomUGApplicantEdit(ICustomUGApplicant):
577    """An undergraduate applicant interface for edit forms.
578
579    Here we can repeat the fields from base data and set the
580    `required` and `readonly` attributes to True to further restrict
581    the data access. Or we can allow only certain certificates to be
582    selected by choosing the appropriate source.
583
584    We cannot omit fields here. This has to be done in the
585    respective form page.
586    """
587
588    phone = PhoneNumber(
589        title = _(u'Phone'),
590        description = u'',
591        required = True,
592        )
593    email = schema.ASCIILine(
594        title = _(u'Email Address'),
595        required = True,
596        constraint=validate_email,
597        )
598    date_of_birth = FormattedDate(
599        title = _(u'Date of Birth'),
600        required = True,
601        show_year = True,
602        )
603
604ICustomUGApplicantEdit[
605    'date_of_birth'].order = ICustomUGApplicant['date_of_birth'].order
606ICustomUGApplicantEdit[
607    'email'].order = ICustomUGApplicant['email'].order
608ICustomUGApplicantEdit[
609    'phone'].order =  ICustomUGApplicantEdit['email'].order
610
611class ICustomPGApplicantEdit(ICustomPGApplicant):
612    """A postgraduate applicant interface for editing.
613
614    Here we can repeat the fields from base data and set the
615    `required` and `readonly` attributes to True to further restrict
616    the data access. Or we can allow only certain certificates to be
617    selected by choosing the appropriate source.
618
619    We cannot omit fields here. This has to be done in the
620    respective form page.
621    """
622
623    phone = PhoneNumber(
624        title = _(u'Phone'),
625        description = u'',
626        required = True,
627        )
628    email = schema.ASCIILine(
629        title = _(u'Email Address'),
630        required = True,
631        constraint=validate_email,
632        )
633    date_of_birth = FormattedDate(
634        title = _(u'Date of Birth'),
635        required = True,
636        show_year = True,
637        )
638
639ICustomPGApplicantEdit[
640    'date_of_birth'].order = ICustomPGApplicant['date_of_birth'].order
641ICustomPGApplicantEdit[
642    'email'].order = ICustomPGApplicant['email'].order
643ICustomPGApplicantEdit[
644    'phone'].order =  ICustomPGApplicantEdit['email'].order
645
646class ICustomApplicantOnlinePayment(INigeriaApplicantOnlinePayment):
647    """An applicant payment via payment gateways.
648
649    """
650
651class IPUTMEApplicantEdit(IPUTMEApplicantEdit):
652    """An undergraduate applicant interface for editing.
653
654    Here we can repeat the fields from base data and set the
655    `required` and `readonly` attributes to True to further restrict
656    the data access. Or we can allow only certain certificates to be
657    selected by choosing the appropriate source.
658
659    We cannot omit fields here. This has to be done in the
660    respective form page.
661    """
662
663class ICustomApplicantUpdateByRegNo(INigeriaApplicantUpdateByRegNo):
664    """Representation of an applicant.
665
666    Skip regular reg_number validation if reg_number is used for finding
667    the applicant object.
668    """
669
670class ICustomApplicantRefereeReport(IApplicantRefereeReport):
671    """A referee report.
672    """
673
674    duration = schema.Text(
675        title = _(u'How long and in what capacity have you known the candidate?'),
676        required = False,
677        )
678
679    itellectual = schema.Choice(
680        title = _(u'Intellectual Capacity'),
681        required = False,
682        readonly = False,
683        vocabulary = rating_vocab,
684        )
685
686    persistent = schema.Choice(
687        title = _(u'Capacity for Persistent and Independent Academic Study'),
688        required = False,
689        readonly = False,
690        vocabulary = rating_vocab,
691        )
692
693    imaginative = schema.Choice(
694        title = _(u'Ability for Imaginative Thought'),
695        required = False,
696        readonly = False,
697        vocabulary = rating_vocab,
698        )
699
700    productive = schema.Choice(
701        title = _(u'Promise of Productive Scholarship'),
702        required = False,
703        readonly = False,
704        vocabulary = rating_vocab,
705        )
706
707    previous = schema.Choice(
708        title = _(u'Quality of Previous Work'),
709        required = False,
710        readonly = False,
711        vocabulary = rating_vocab,
712        )
713
714    expression = schema.Choice(
715        title = _(u'Oral and Written Expression in English'),
716        required = False,
717        readonly = False,
718        vocabulary = rating_vocab,
719        )
720
721    personality = schema.Text(
722        title = _(u'Please comment on the candidate\'s personality '
723            'with particular reference to his/her moral character, emotional '
724            'and physical stabilty'),
725        required = False,
726        )
727
728    promise = schema.Choice(
729        title = _(u'Candidate\'s overall promise'),
730        required = False,
731        readonly = False,
732        vocabulary = overallpromise_vocab,
733        )
734
735    report = schema.Text(
736        title = _(u'Any other relevant information which would help '
737            'in determining the candidate\'s suitability?'),
738        required = False,
739        )
740
741    objection = schema.Text(
742        title = _(u'Have you any objection to the contents of this '
743            'evaluation being disclosed to any award-given body if '
744            'the need arises?'),
745        required = False,
746        )
Note: See TracBrowser for help on using the repository browser.