source: main/waeup.uniben/trunk/src/waeup/uniben/applicants/interfaces.py @ 16783

Last change on this file since 16783 was 16775, checked in by Henrik Bettermann, 3 years ago

Fix if statement.

  • Property svn:keywords set to Id
File size: 23.0 KB
Line 
1# -*- coding: utf-8 -*-
2## $Id: interfaces.py 16775 2022-02-02 13:08:50Z 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
22#from grok import getSite
23from zope import schema
24from zope.interface import invariant, Invalid
25from zope.component import getUtility
26from zope.catalog.interfaces import ICatalog
27from zc.sourcefactory.basic import BasicSourceFactory
28from waeup.kofa.applicants.interfaces import (
29    IApplicantBaseData,
30    AppCatCertificateSource, CertificateSource)
31from waeup.kofa.university.vocabularies import StudyModeSource
32from waeup.kofa.students.vocabularies import (
33    nats_vocab, GenderSource, StudyLevelSource)
34from waeup.kofa.schoolgrades import ResultEntryField
35from waeup.kofa.interfaces import (
36    SimpleKofaVocabulary, academic_sessions_vocab, validate_email,
37    IKofaObject, ContextualDictSourceFactoryBase)
38from waeup.kofa.schema import FormattedDate, TextLineChoice, PhoneNumber
39from waeup.kofa.students.vocabularies import (
40    nats_vocab, GenderSource)
41from waeup.kofa.refereeentries import RefereeEntryField
42from waeup.kofa.applicants.interfaces import contextual_reg_num_source
43from kofacustom.nigeria.interfaces import DisabilitiesSource
44from kofacustom.nigeria.applicants.interfaces import (
45    LGASource, high_qual, high_grade, exam_types,
46    programme_types_vocab, jambsubjects,
47    INigeriaUGApplicant, INigeriaPGApplicant,
48    INigeriaApplicantOnlinePayment,
49    INigeriaUGApplicantEdit, INigeriaPGApplicantEdit,
50    INigeriaApplicantUpdateByRegNo,
51    IPUTMEApplicantEdit,
52    IBankAccount,
53    )
54from waeup.uniben.interfaces import MessageFactory as _
55from waeup.uniben.payments.interfaces import ICustomOnlinePayment
56
57class TranscriptCertificateSource(CertificateSource):
58    """Include Department and Faculty in Title.
59    """
60    def getValues(self, context):
61        catalog = getUtility(ICatalog, name='certificates_catalog')
62        resultset = catalog.searchResults(code=(None, None))
63        resultlist = sorted(resultset, key=lambda
64            value: value.__parent__.__parent__.__parent__.code +
65            value.__parent__.__parent__.code +
66            value.code)
67        return resultlist
68
69    def getTitle(self, context, value):
70        """
71        """
72        try: title = "%s / %s / %s (%s)" % (
73            value.__parent__.__parent__.__parent__.title,
74            value.__parent__.__parent__.title,
75            value.title, value.code)
76        except AttributeError:
77            title = "NA / %s (%s)" % (value.title, value.code)
78        return title
79
80REGISTRATION_CATS = {
81    'corporate': ('Corporate Registration', 250000, 1),
82    'group': ('Group Registration', 200000, 2),
83    'individual': ('Individual Registration', 45000, 3),
84    'student': ('Student Registration', 5000, 4),
85    'fullpage': ('Full Page Advert', 250000, 5),
86    'halfpage': ('Half Page Advert', 150000, 6),
87    'quarterpage': ('Quarter Page Advert', 100000, 7),
88    }
89
90class RegTypesSource(BasicSourceFactory):
91    """A source that delivers all kinds of registrations.
92    """
93    def getValues(self):
94        sorted_items = sorted(REGISTRATION_CATS.items(),
95                              key=lambda element: element[1][2])
96        return [item[0] for item in sorted_items]
97
98    def getTitle(self, value):
99        return u"%s @ ₦ %s" % (
100            REGISTRATION_CATS[value][0],
101            REGISTRATION_CATS[value][1])
102
103DESTINATION_COST = {
104    #'none': ('To the moon', 1000000000.0, 1),
105    'nigeria': ('Within Nigeria', 20000.0, 1),
106    'africa': ('Within Africa ', 30000.0, 2),
107    'inter': ('International', 35000.0, 3),
108    'cert_nigeria': ('Certified Copy - Within Nigeria', 13000.0, 4),
109    'cert_africa': ('Certified Copy - Within Africa', 23000.0, 5),
110    'cert_inter': ('Certified Copy - International', 28000.0, 6),
111    }
112
113class DestinationCostSource(BasicSourceFactory):
114    """A source that delivers continents and shipment costs.
115    """
116    def getValues(self):
117        sorted_items = sorted(DESTINATION_COST.items(),
118                              key=lambda element: element[1][2])
119        return [item[0] for item in sorted_items]
120
121    def getToken(self, value):
122        return value
123
124    def getTitle(self, value):
125        return u"%s (₦ %s)" % (
126            DESTINATION_COST[value][0],
127            DESTINATION_COST[value][1])
128
129class OrderSource(BasicSourceFactory):
130    """
131    """
132    def getValues(self):
133        return ['o', 'c']
134
135    def getToken(self, value):
136        return value
137
138    def getTitle(self, value):
139        if value == 'o':
140            return _('Original')
141        if value == 'c':
142            return _('Certified True Copy')
143
144class IUnibenRegistration(IKofaObject):
145    """A Uniben registrant.
146    """
147
148    suspended = schema.Bool(
149        title = _(u'Account suspended'),
150        default = False,
151        required = False,
152        )
153
154    locked = schema.Bool(
155        title = _(u'Form locked'),
156        default = False,
157        required = False,
158        )
159
160    applicant_id = schema.TextLine(
161        title = _(u'Registrant Id'),
162        required = False,
163        readonly = False,
164        )
165
166    firstname = schema.TextLine(
167        title = _(u'First Name'),
168        required = True,
169        )
170
171    middlename = schema.TextLine(
172        title = _(u'Middle Name'),
173        required = False,
174        )
175
176    lastname = schema.TextLine(
177        title = _(u'Last Name (Surname)'),
178        required = True,
179        )
180
181    sex = schema.Choice(
182        title = _(u'Sex'),
183        source = GenderSource(),
184        required = True,
185        )
186
187    nationality = schema.Choice(
188        vocabulary = nats_vocab,
189        title = _(u'Nationality'),
190        required = False,
191        )
192
193    email = schema.ASCIILine(
194        title = _(u'Email Address'),
195        required = True,
196        constraint=validate_email,
197        )
198
199    phone = PhoneNumber(
200        title = _(u'Phone'),
201        description = u'',
202        required = False,
203        )
204
205    #perm_address = schema.Text(
206    #    title = _(u'Current Local Address'),
207    #    required = False,
208    #    readonly = False,
209    #    )
210
211    institution = schema.TextLine(
212        title = _(u'Institution/Organisation'),
213        required = False,
214        readonly = False,
215        )
216
217    city = schema.TextLine(
218        title = _(u'City'),
219        required = False,
220        readonly = False,
221        )
222
223    lga = schema.Choice(
224        source = LGASource(),
225        title = _(u'State/LGA'),
226        required = False,
227        )
228
229    matric_number = schema.TextLine(
230        title = _(u'Uniben Matriculation Number'),
231        required = False,
232        readonly = False,
233        )
234
235    registration_cats = schema.List(
236        title = _(u'Registration Categories'),
237        value_type = schema.Choice(source=RegTypesSource()),
238        required = True,
239        defaultFactory=list,
240        )
241
242#    @invariant
243#    def matric_number_exists(applicant):
244#        if applicant.matric_number:
245#            catalog = getUtility(ICatalog, name='students_catalog')
246#            accommodation_session = getSite()['hostels'].accommodation_session
247#            student = catalog.searchResults(matric_number=(
248#                applicant.matric_number, applicant.matric_number))
249#            if len(student) != 1:
250#                raise Invalid(_("Matriculation number not found."))
251
252class ITranscriptApplicant(IKofaObject):
253    """A transcript applicant.
254    """
255
256    suspended = schema.Bool(
257        title = _(u'Account suspended'),
258        default = False,
259        required = False,
260        )
261
262    locked = schema.Bool(
263        title = _(u'Form locked'),
264        default = False,
265        required = False,
266        )
267
268    applicant_id = schema.TextLine(
269        title = _(u'Transcript Application Id'),
270        required = False,
271        readonly = False,
272        )
273
274    student_id = schema.TextLine(
275        title = _(u'Kofa Student Id'),
276        required = False,
277        readonly = False,
278        )
279
280    matric_number = schema.TextLine(
281        title = _(u'Matriculation Number'),
282        readonly = False,
283        required = True,
284        )
285
286    firstname = schema.TextLine(
287        title = _(u'First Name in School'),
288        required = True,
289        )
290
291    middlename = schema.TextLine(
292        title = _(u'Middle Name in School'),
293        required = False,
294        )
295
296    lastname = schema.TextLine(
297        title = _(u'Surname in School'),
298        required = True,
299        )
300
301    date_of_birth = FormattedDate(
302        title = _(u'Date of Birth'),
303        required = False,
304        #date_format = u'%d/%m/%Y', # Use grok-instance-wide default
305        show_year = True,
306        )
307
308    sex = schema.Choice(
309        title = _(u'Gender'),
310        source = GenderSource(),
311        required = True,
312        )
313
314    #nationality = schema.Choice(
315    #    vocabulary = nats_vocab,
316    #    title = _(u'Nationality'),
317    #    required = False,
318    #    )
319
320    email = schema.ASCIILine(
321        title = _(u'Email Address'),
322        required = True,
323        constraint=validate_email,
324        )
325
326    phone = PhoneNumber(
327        title = _(u'Phone'),
328        description = u'',
329        required = False,
330        )
331
332    #perm_address = schema.Text(
333    #    title = _(u'Current Local Address'),
334    #    required = False,
335    #    readonly = False,
336    #    )
337
338    collected = schema.Bool(
339        title = _(u'Have you collected transcript before?'),
340        default = False,
341        required = False,
342        )
343
344    entry_session = schema.Choice(
345        title = _(u'Academic Session of Entry'),
346        source = academic_sessions_vocab,
347        required = False,
348        readonly = False,
349        )
350
351    end_session = schema.Choice(
352        title = _(u'Academic Session of Graduation'),
353        source = academic_sessions_vocab,
354        required = False,
355        readonly = False,
356        )
357
358    entry_mode = schema.Choice(
359        title = _(u'Mode of Entry'),
360        source = StudyModeSource(),
361        required = False,
362        readonly = False,
363        )
364
365    course_studied = schema.Choice(
366        title = _(u'Course of Study'),
367        source = TranscriptCertificateSource(),
368        description = u'Faculty / Department / Course',
369        required = True,
370        readonly = False,
371        )
372
373    course_changed = schema.Choice(
374        title = _(u'Change of Study Course / Transfer'),
375        description = u'If yes, select previous course of study.',
376        source = TranscriptCertificateSource(),
377        readonly = False,
378        required = False,
379        )
380
381    spillover_level = schema.Choice(
382        title = _(u'Spill-over'),
383        description = u'Any spill-over? If yes, select session of spill-over.',
384        source = academic_sessions_vocab,
385        required = False,
386        readonly = False,
387        )
388
389    purpose = schema.TextLine(
390        title = _(u'Transcript Purpose'),
391        required = False,
392        )
393
394    order = schema.Choice(
395        source = OrderSource(),
396        title = _(u'Type of Order'),
397        required = True,
398        )
399
400    dispatch_address = schema.Text(
401        title = _(u'Recipient Body'),
402        description = u'Addresses (including email address and phone number) '
403                       'to which transcripts should be posted. '
404                       'All addresses must involve same courier charges.',
405        required = True,
406        readonly = False,
407        )
408
409    charge = schema.Choice(
410        title = _(u'Transcript Charge'),
411        source = DestinationCostSource(),
412        required = False,
413        readonly = False,
414        )
415
416    no_copies = schema.Choice(
417        title = _(u'Number of Copies'),
418        description = u'Must correspond with the number of dispatch addresses above.',
419        values=[1, 2, 3, 4],
420        required = False,
421        readonly = False,
422        default = 1,
423        )
424
425    courier_tno = schema.TextLine(
426        title = _(u'Courier Tracking Number'),
427        required = False,
428        )
429
430    proc_date = FormattedDate(
431        title = _(u'Processing Date'),
432        required = False,
433        #date_format = u'%d/%m/%Y', # Use grok-instance-wide default
434        show_year = True,
435        )
436
437    @invariant
438    def type_of_order(applicant):
439        if not applicant.collected and applicant.order != 'o':
440            raise Invalid(_("If you haven't collected transcript before, type of order must be 'original'."))
441        if applicant.order == 'o' and applicant.charge.startswith('cert_'):
442            raise Invalid(_("You've selected the wrong transcript charge."))
443        if applicant.order == 'c' and not applicant.charge.startswith('cert_'):
444            raise Invalid(_("You've selected the wrong transcript charge."))
445
446
447class ICustomUGApplicant(IApplicantBaseData, IBankAccount):
448    """An undergraduate applicant.
449
450    This interface defines the least common multiple of all fields
451    in ug application forms. In customized forms, fields can be excluded by
452    adding them to the UG_OMIT* tuples.
453    """
454
455    disabilities = schema.Choice(
456        title = _(u'Disabilities'),
457        source = DisabilitiesSource(),
458        required = False,
459        )
460    nationality = schema.Choice(
461        source = nats_vocab,
462        title = _(u'Nationality'),
463        required = False,
464        )
465    lga = schema.Choice(
466        source = LGASource(),
467        title = _(u'State/LGA (Nigerians only)'),
468        required = False,
469        )
470    #perm_address = schema.Text(
471    #    title = _(u'Permanent Address'),
472    #    required = False,
473    #    )
474    course1 = schema.Choice(
475        title = _(u'1st Choice Course of Study'),
476        source = AppCatCertificateSource(),
477        required = True,
478        )
479    course2 = schema.Choice(
480        title = _(u'2nd Choice Course of Study'),
481        source = AppCatCertificateSource(),
482        required = False,
483        )
484
485    programme_type = schema.Choice(
486        title = _(u'Programme Type'),
487        vocabulary = programme_types_vocab,
488        required = False,
489        )
490
491    hq_type = schema.Choice(
492        title = _(u'Qualification Obtained'),
493        required = False,
494        readonly = False,
495        vocabulary = high_qual,
496        )
497    hq_matric_no = schema.TextLine(
498        title = _(u'Former Matric Number'),
499        required = False,
500        readonly = False,
501        )
502    hq_degree = schema.Choice(
503        title = _(u'Class of Degree'),
504        required = False,
505        readonly = False,
506        vocabulary = high_grade,
507        )
508    hq_school = schema.TextLine(
509        title = _(u'Institution Attended'),
510        required = False,
511        readonly = False,
512        )
513    hq_session = schema.TextLine(
514        title = _(u'Years Attended'),
515        required = False,
516        readonly = False,
517        )
518    hq_disc = schema.TextLine(
519        title = _(u'Discipline'),
520        required = False,
521        readonly = False,
522        )
523    fst_sit_fname = schema.TextLine(
524        title = _(u'Full Name'),
525        required = False,
526        readonly = False,
527        )
528    fst_sit_no = schema.TextLine(
529        title = _(u'Exam Number'),
530        required = False,
531        readonly = False,
532        )
533    fst_sit_date = FormattedDate(
534        title = _(u'Exam Date'),
535        required = False,
536        readonly = False,
537        show_year = True,
538        )
539    fst_sit_type = schema.Choice(
540        title = _(u'Exam Type'),
541        required = False,
542        readonly = False,
543        vocabulary = exam_types,
544        )
545    fst_sit_results = schema.List(
546        title = _(u'Exam Results'),
547        value_type = ResultEntryField(),
548        required = False,
549        readonly = False,
550        defaultFactory=list,
551        )
552    scd_sit_fname = schema.TextLine(
553        title = _(u'Full Name'),
554        required = False,
555        readonly = False,
556        )
557    scd_sit_no = schema.TextLine(
558        title = _(u'Exam Number'),
559        required = False,
560        readonly = False,
561        )
562    scd_sit_date = FormattedDate(
563        title = _(u'Exam Date'),
564        required = False,
565        readonly = False,
566        show_year = True,
567        )
568    scd_sit_type = schema.Choice(
569        title = _(u'Exam Type'),
570        required = False,
571        readonly = False,
572        vocabulary = exam_types,
573        )
574    scd_sit_results = schema.List(
575        title = _(u'Exam Results'),
576        value_type = ResultEntryField(),
577        required = False,
578        readonly = False,
579        defaultFactory=list,
580        )
581    jamb_subjects = schema.Text(
582        title = _(u'Subjects and Scores'),
583        required = False,
584        )
585    jamb_subjects_list = schema.List(
586        title = _(u'JAMB Subjects'),
587        required = False,
588        defaultFactory=list,
589        value_type = schema.Choice(
590            vocabulary = jambsubjects
591            #source = JAMBSubjectSource(),
592            ),
593        )
594    jamb_score = schema.Float(
595        title = _(u'Total JAMB Score'),
596        required = False,
597        )
598    #jamb_age = schema.Int(
599    #    title = _(u'Age (provided by JAMB)'),
600    #    required = False,
601    #    )
602    jamb_reg_number = schema.TextLine(
603        title = _(u'JAMB Registration Number'),
604        required = False,
605        )
606    notice = schema.Text(
607        title = _(u'Notice'),
608        required = False,
609        )
610    screening_venue = schema.TextLine(
611        title = _(u'Screening Venue'),
612        required = False,
613        )
614    screening_date = schema.TextLine(
615        title = _(u'Screening Date'),
616        required = False,
617        )
618    screening_score = schema.Float(
619        title = _(u'Screening Score (%)'),
620        required = False,
621        )
622    aggregate = schema.Float(
623        title = _(u'Aggregate Score (%)'),
624        description = _(u'(average of relative JAMB and PUTME scores)'),
625        required = False,
626        )
627    result_uploaded = schema.Bool(
628        title = _(u'Result uploaded'),
629        default = False,
630        required = False,
631        )
632    student_id = schema.TextLine(
633        title = _(u'Student Id'),
634        required = False,
635        readonly = False,
636        )
637    course_admitted = schema.Choice(
638        title = _(u'Admitted Course of Study'),
639        source = CertificateSource(),
640        required = False,
641        )
642    locked = schema.Bool(
643        title = _(u'Form locked'),
644        default = False,
645        required = False,
646        )
647
648ICustomUGApplicant[
649    'locked'].order =  IApplicantBaseData['suspended'].order
650ICustomUGApplicant[
651    'result_uploaded'].order =  ICustomUGApplicant['suspended'].order
652
653class ICustomPGApplicant(INigeriaPGApplicant):
654    """A postgraduate applicant.
655
656    This interface defines the least common multiple of all fields
657    in pg application forms. In customized forms, fields can be excluded by
658    adding them to the PG_OMIT* tuples.
659    """
660
661    referees = schema.List(
662        title = _(u'Referees'),
663        value_type = RefereeEntryField(),
664        required = False,
665        defaultFactory=list,
666        )
667
668ICustomPGApplicant[
669    'referees'].order =  INigeriaPGApplicant['emp2_reason'].order
670
671class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant,
672    IUnibenRegistration, ITranscriptApplicant):
673    """An interface for both types of applicants.
674
675    Attention: The ICustomPGApplicant field seetings will be overwritten
676    by ICustomPGApplicant field settings. If a field is defined
677    in both interfaces zope.schema validates only against the
678    constraints in ICustomUGApplicant. This does not affect the forms
679    since they are build on either ICustomUGApplicant or ICustomPGApplicant.
680    """
681
682    def writeLogMessage(view, comment):
683        """Adds an INFO message to the log file
684        """
685
686    def createStudent():
687        """Create a student object from applicant data
688        and copy applicant object.
689        """
690
691class ICustomUGApplicantEdit(ICustomUGApplicant):
692    """An undergraduate applicant interface for edit forms.
693
694    Here we can repeat the fields from base data and set the
695    `required` and `readonly` attributes to True to further restrict
696    the data access. Or we can allow only certain certificates to be
697    selected by choosing the appropriate source.
698
699    We cannot omit fields here. This has to be done in the
700    respective form page.
701    """
702
703    email = schema.ASCIILine(
704        title = _(u'Email Address'),
705        required = True,
706        constraint=validate_email,
707        )
708    date_of_birth = FormattedDate(
709        title = _(u'Date of Birth'),
710        required = True,
711        show_year = True,
712        )
713
714ICustomUGApplicantEdit[
715    'date_of_birth'].order = ICustomUGApplicant['date_of_birth'].order
716ICustomUGApplicantEdit[
717    'email'].order = ICustomUGApplicant['email'].order
718
719class ICustomPGApplicantEdit(INigeriaPGApplicantEdit):
720    """A postgraduate applicant interface for editing.
721
722    Here we can repeat the fields from base data and set the
723    `required` and `readonly` attributes to True to further restrict
724    the data access. Or we can allow only certain certificates to be
725    selected by choosing the appropriate source.
726
727    We cannot omit fields here. This has to be done in the
728    respective form page.
729    """
730
731    referees = schema.List(
732        title = _(u'Referees'),
733        value_type = RefereeEntryField(),
734        required = False,
735        defaultFactory=list,
736        )
737
738ICustomPGApplicantEdit[
739    'referees'].order =  INigeriaPGApplicantEdit['emp2_reason'].order
740
741class ICustomApplicantOnlinePayment(INigeriaApplicantOnlinePayment):
742    """An applicant payment via payment gateways.
743
744    """
745
746class IPUTMEApplicantEdit(ICustomUGApplicant):
747    """An undergraduate applicant interface for editing.
748
749    Here we can repeat the fields from base data and set the
750    `required` and `readonly` attributes to True to further restrict
751    the data access. Or we can allow only certain certificates to be
752    selected by choosing the appropriate source.
753
754    We cannot omit fields here. This has to be done in the
755    respective form page.
756    """
757
758    email = schema.ASCIILine(
759        title = _(u'Email Address'),
760        required = True,
761        constraint=validate_email,
762        )
763    date_of_birth = FormattedDate(
764        title = _(u'Date of Birth'),
765        required = True,
766        show_year = True,
767        )
768    nationality = schema.Choice(
769        source = nats_vocab,
770        title = _(u'Nationality'),
771        required = True,
772        )
773
774IPUTMEApplicantEdit[
775    'date_of_birth'].order =  ICustomUGApplicant['date_of_birth'].order
776IPUTMEApplicantEdit[
777    'email'].order =  ICustomUGApplicant['email'].order
778IPUTMEApplicantEdit[
779    'nationality'].order =  ICustomUGApplicant['nationality'].order
780
781class ICustomApplicantUpdateByRegNo(INigeriaApplicantUpdateByRegNo):
782    """Representation of an applicant.
783
784    Skip regular reg_number validation if reg_number is used for finding
785    the applicant object.
786    """
Note: See TracBrowser for help on using the repository browser.