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

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

Configure transcript charge.

  • Property svn:keywords set to Id
File size: 22.1 KB
RevLine 
[13814]1# -*- coding: utf-8 -*-
[7853]2## $Id: interfaces.py 16182 2020-07-24 07:41:46Z 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
[13831]22#from grok import getSite
[8012]23from zope import schema
[13831]24#from zope.interface import invariant, Invalid
[16152]25from zope.component import getUtility
26from zope.catalog.interfaces import ICatalog
[13814]27from zc.sourcefactory.basic import BasicSourceFactory
[8051]28from waeup.kofa.applicants.interfaces import (
[8053]29    IApplicantBaseData,
[8051]30    AppCatCertificateSource, CertificateSource)
[16078]31from waeup.kofa.university.vocabularies import StudyModeSource
32from waeup.kofa.students.vocabularies import (
33    nats_vocab, GenderSource, StudyLevelSource)
[8051]34from waeup.kofa.schoolgrades import ResultEntryField
[8530]35from waeup.kofa.interfaces import (
[13814]36    SimpleKofaVocabulary, academic_sessions_vocab, validate_email,
[16131]37    IKofaObject, ContextualDictSourceFactoryBase)
[13814]38from waeup.kofa.schema import FormattedDate, TextLineChoice, PhoneNumber
[15490]39from waeup.kofa.students.vocabularies import (
40    nats_vocab, GenderSource)
[14106]41from waeup.kofa.refereeentries import RefereeEntryField
[8530]42from waeup.kofa.applicants.interfaces import contextual_reg_num_source
[15490]43from kofacustom.nigeria.interfaces import DisabilitiesSource
[8928]44from kofacustom.nigeria.applicants.interfaces import (
45    LGASource, high_qual, high_grade, exam_types,
[14140]46    programme_types_vocab, jambsubjects,
[8928]47    INigeriaUGApplicant, INigeriaPGApplicant,
48    INigeriaApplicantOnlinePayment,
[9006]49    INigeriaUGApplicantEdit, INigeriaPGApplicantEdit,
50    INigeriaApplicantUpdateByRegNo,
51    IPUTMEApplicantEdit,
[14140]52    IBankAccount,
[8928]53    )
[8020]54from waeup.uniben.interfaces import MessageFactory as _
[8247]55from waeup.uniben.payments.interfaces import ICustomOnlinePayment
[7853]56
[16152]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
[13814]68
[16152]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
[13814]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),
[13824]85    'fullpage': ('Full Page Advert', 250000, 5),
86    'halfpage': ('Half Page Advert', 150000, 6),
87    'quarterpage': ('Quarter Page Advert', 100000, 7),
[13814]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
[16131]103DESTINATION_COST = {
[16144]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),
[16182]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),
[16131]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
[16151]121    def getToken(self, value):
122        return value
123
[16131]124    def getTitle(self, value):
125        return u"%s (₦ %s)" % (
126            DESTINATION_COST[value][0],
127            DESTINATION_COST[value][1])
128
[16151]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
[13814]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
[13819]181    sex = schema.Choice(
182        title = _(u'Sex'),
183        source = GenderSource(),
184        required = True,
[13814]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
[13819]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'),
[13814]213        required = False,
214        readonly = False,
215        )
216
[13828]217    city = schema.TextLine(
218        title = _(u'City'),
219        required = False,
220        readonly = False,
221        )
222
[13819]223    lga = schema.Choice(
224        source = LGASource(),
225        title = _(u'State/LGA'),
226        required = False,
227        )
228
[13831]229    matric_number = schema.TextLine(
230        title = _(u'Uniben Matriculation Number'),
231        required = False,
232        readonly = False,
233        )
234
[13814]235    registration_cats = schema.List(
236        title = _(u'Registration Categories'),
237        value_type = schema.Choice(source=RegTypesSource()),
238        required = True,
[14020]239        defaultFactory=list,
[13814]240        )
241
[13831]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."))
[13814]251
[16078]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(
[16131]269        title = _(u'Transcript Application Id'),
[16078]270        required = False,
271        readonly = False,
272        )
273
[16131]274    student_id = schema.TextLine(
275        title = _(u'Kofa Student Id'),
276        required = False,
[16078]277        readonly = False,
[16131]278        )
279
280    matric_number = schema.TextLine(
281        title = _(u'Matriculation Number'),
282        readonly = False,
[16078]283        required = True,
284        )
285
286    firstname = schema.TextLine(
[16151]287        title = _(u'First Name in School'),
[16078]288        required = True,
289        )
290
291    middlename = schema.TextLine(
[16151]292        title = _(u'Middle Name in School'),
[16078]293        required = False,
294        )
295
296    lastname = schema.TextLine(
[16151]297        title = _(u'Surname in School'),
[16078]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
[16151]314    #nationality = schema.Choice(
315    #    vocabulary = nats_vocab,
316    #    title = _(u'Nationality'),
317    #    required = False,
318    #    )
[16078]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
[16151]332    #perm_address = schema.Text(
333    #    title = _(u'Current Local Address'),
334    #    required = False,
335    #    readonly = False,
336    #    )
337
[16153]338    collected = schema.Bool(
339        title = _(u'Have you collected transcript before?'),
340        default = False,
341        required = False,
342        )
343
[16151]344    entry_session = schema.Choice(
345        title = _(u'Academic Session of Entry'),
346        source = academic_sessions_vocab,
[16078]347        required = False,
348        readonly = False,
349        )
350
[16151]351    end_session = schema.Choice(
352        title = _(u'Academic Session of Graduation'),
353        source = academic_sessions_vocab,
[16078]354        required = False,
355        readonly = False,
356        )
357
358    entry_mode = schema.Choice(
[16151]359        title = _(u'Mode of Entry'),
[16078]360        source = StudyModeSource(),
361        required = False,
362        readonly = False,
363        )
364
365    course_studied = schema.Choice(
[16151]366        title = _(u'Course of Study'),
[16152]367        source = TranscriptCertificateSource(),
368        description = u'Faculty / Department / Study Course',
[16078]369        required = False,
370        readonly = False,
371        )
372
373    course_changed = schema.Choice(
[16151]374        title = _(u'Change of Study Course / Transfer'),
[16078]375        description = u'If yes, select previous course of study.',
[16152]376        source = TranscriptCertificateSource(),
[16078]377        readonly = False,
378        required = False,
379        )
380
[16153]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        )
[16151]388
389    purpose = schema.TextLine(
390        title = _(u'Transcript Purpose'),
[16078]391        required = False,
[16151]392        )
393
394    order = schema.Choice(
395        source = OrderSource(),
396        title = _(u'Type of Order'),
397        required = False,
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 = False,
[16078]406        readonly = False,
407        )
408
[16151]409    charge = schema.Choice(
[16182]410        title = _(u'Transcript Charge'),
[16151]411        source = DestinationCostSource(),
412        required = True,
413        )
414
[16078]415    no_copies = schema.Choice(
416        title = _(u'Number of Copies'),
417        description = u'Must correspond with the number of dispatch addresses above.',
418        values=[1, 2, 3, 4],
419        required = False,
420        readonly = False,
421        default = 1,
422        )
423
[14140]424class ICustomUGApplicant(IApplicantBaseData, IBankAccount):
[8012]425    """An undergraduate applicant.
426
[8519]427    This interface defines the least common multiple of all fields
428    in ug application forms. In customized forms, fields can be excluded by
429    adding them to the UG_OMIT* tuples.
[8012]430    """
431
[15490]432    disabilities = schema.Choice(
433        title = _(u'Disabilities'),
434        source = DisabilitiesSource(),
435        required = False,
436        )
[14140]437    nationality = schema.Choice(
438        source = nats_vocab,
439        title = _(u'Nationality'),
440        required = False,
441        )
442    lga = schema.Choice(
443        source = LGASource(),
444        title = _(u'State/LGA (Nigerians only)'),
445        required = False,
446        )
447    #perm_address = schema.Text(
448    #    title = _(u'Permanent Address'),
449    #    required = False,
450    #    )
451    course1 = schema.Choice(
452        title = _(u'1st Choice Course of Study'),
453        source = AppCatCertificateSource(),
454        required = True,
455        )
456    course2 = schema.Choice(
457        title = _(u'2nd Choice Course of Study'),
458        source = AppCatCertificateSource(),
459        required = False,
460        )
461
462    programme_type = schema.Choice(
463        title = _(u'Programme Type'),
464        vocabulary = programme_types_vocab,
465        required = False,
466        )
467
468    hq_type = schema.Choice(
469        title = _(u'Qualification Obtained'),
470        required = False,
471        readonly = False,
472        vocabulary = high_qual,
473        )
474    hq_matric_no = schema.TextLine(
475        title = _(u'Former Matric Number'),
476        required = False,
477        readonly = False,
478        )
479    hq_degree = schema.Choice(
480        title = _(u'Class of Degree'),
481        required = False,
482        readonly = False,
483        vocabulary = high_grade,
484        )
485    hq_school = schema.TextLine(
486        title = _(u'Institution Attended'),
487        required = False,
488        readonly = False,
489        )
490    hq_session = schema.TextLine(
491        title = _(u'Years Attended'),
492        required = False,
493        readonly = False,
494        )
495    hq_disc = schema.TextLine(
496        title = _(u'Discipline'),
497        required = False,
498        readonly = False,
499        )
[14141]500    fst_sit_fname = schema.TextLine(
501        title = _(u'Full Name'),
502        required = False,
503        readonly = False,
504        )
505    fst_sit_no = schema.TextLine(
506        title = _(u'Exam Number'),
507        required = False,
508        readonly = False,
509        )
510    fst_sit_date = FormattedDate(
511        title = _(u'Exam Date'),
512        required = False,
513        readonly = False,
514        show_year = True,
515        )
516    fst_sit_type = schema.Choice(
517        title = _(u'Exam Type'),
518        required = False,
519        readonly = False,
520        vocabulary = exam_types,
521        )
522    fst_sit_results = schema.List(
523        title = _(u'Exam Results'),
524        value_type = ResultEntryField(),
525        required = False,
526        readonly = False,
527        defaultFactory=list,
528        )
529    scd_sit_fname = schema.TextLine(
530        title = _(u'Full Name'),
531        required = False,
532        readonly = False,
533        )
534    scd_sit_no = schema.TextLine(
535        title = _(u'Exam Number'),
536        required = False,
537        readonly = False,
538        )
539    scd_sit_date = FormattedDate(
540        title = _(u'Exam Date'),
541        required = False,
542        readonly = False,
543        show_year = True,
544        )
545    scd_sit_type = schema.Choice(
546        title = _(u'Exam Type'),
547        required = False,
548        readonly = False,
549        vocabulary = exam_types,
550        )
551    scd_sit_results = schema.List(
552        title = _(u'Exam Results'),
553        value_type = ResultEntryField(),
554        required = False,
555        readonly = False,
556        defaultFactory=list,
557        )
[14140]558    jamb_subjects = schema.Text(
559        title = _(u'Subjects and Scores'),
560        required = False,
561        )
562    jamb_subjects_list = schema.List(
563        title = _(u'JAMB Subjects'),
564        required = False,
565        defaultFactory=list,
566        value_type = schema.Choice(
567            vocabulary = jambsubjects
568            #source = JAMBSubjectSource(),
569            ),
570        )
571    jamb_score = schema.Int(
572        title = _(u'Total JAMB Score'),
573        required = False,
574        )
575    #jamb_age = schema.Int(
576    #    title = _(u'Age (provided by JAMB)'),
577    #    required = False,
578    #    )
579    jamb_reg_number = schema.TextLine(
580        title = _(u'JAMB Registration Number'),
581        required = False,
582        )
583    notice = schema.Text(
584        title = _(u'Notice'),
585        required = False,
586        )
587    screening_venue = schema.TextLine(
588        title = _(u'Screening Venue'),
589        required = False,
590        )
591    screening_date = schema.TextLine(
592        title = _(u'Screening Date'),
593        required = False,
594        )
595    screening_score = schema.Int(
596        title = _(u'Screening Score (%)'),
597        required = False,
598        )
599    aggregate = schema.Int(
600        title = _(u'Aggregate Score (%)'),
601        description = _(u'(average of relative JAMB and PUTME scores)'),
602        required = False,
603        )
604    result_uploaded = schema.Bool(
605        title = _(u'Result uploaded'),
606        default = False,
607        required = False,
608        )
609    student_id = schema.TextLine(
610        title = _(u'Student Id'),
611        required = False,
612        readonly = False,
613        )
614    course_admitted = schema.Choice(
615        title = _(u'Admitted Course of Study'),
616        source = CertificateSource(),
617        required = False,
618        )
619    locked = schema.Bool(
620        title = _(u'Form locked'),
621        default = False,
622        required = False,
623        )
624
625ICustomUGApplicant[
626    'locked'].order =  IApplicantBaseData['suspended'].order
627ICustomUGApplicant[
628    'result_uploaded'].order =  ICustomUGApplicant['suspended'].order
629
[8928]630class ICustomPGApplicant(INigeriaPGApplicant):
[7853]631    """A postgraduate applicant.
632
[8519]633    This interface defines the least common multiple of all fields
634    in pg application forms. In customized forms, fields can be excluded by
635    adding them to the PG_OMIT* tuples.
[7866]636    """
637
[14106]638    referees = schema.List(
639        title = _(u'Referees'),
640        value_type = RefereeEntryField(),
641        required = False,
642        defaultFactory=list,
643        )
[8012]644
[14106]645ICustomPGApplicant[
646    'referees'].order =  INigeriaPGApplicant['emp2_reason'].order
647
[13814]648class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant,
[16078]649    IUnibenRegistration, ITranscriptApplicant):
[8012]650    """An interface for both types of applicants.
651
[8928]652    Attention: The ICustomPGApplicant field seetings will be overwritten
653    by ICustomPGApplicant field settings. If a field is defined
[8727]654    in both interfaces zope.schema validates only against the
[8928]655    constraints in ICustomUGApplicant. This does not affect the forms
656    since they are build on either ICustomUGApplicant or ICustomPGApplicant.
[8012]657    """
658
[8743]659    def writeLogMessage(view, comment):
[8053]660        """Adds an INFO message to the log file
661        """
662
663    def createStudent():
[8668]664        """Create a student object from applicant data
[8053]665        and copy applicant object.
666        """
667
[14212]668class ICustomUGApplicantEdit(ICustomUGApplicant):
[8727]669    """An undergraduate applicant interface for edit forms.
[8012]670
671    Here we can repeat the fields from base data and set the
672    `required` and `readonly` attributes to True to further restrict
673    the data access. Or we can allow only certain certificates to be
674    selected by choosing the appropriate source.
675
676    We cannot omit fields here. This has to be done in the
677    respective form page.
678    """
679
[14212]680    email = schema.ASCIILine(
681        title = _(u'Email Address'),
682        required = True,
683        constraint=validate_email,
684        )
685    date_of_birth = FormattedDate(
686        title = _(u'Date of Birth'),
687        required = True,
688        show_year = True,
689        )
690
691ICustomUGApplicantEdit[
692    'date_of_birth'].order = ICustomUGApplicant['date_of_birth'].order
693ICustomUGApplicantEdit[
694    'email'].order = ICustomUGApplicant['email'].order
695
[9056]696class ICustomPGApplicantEdit(INigeriaPGApplicantEdit):
[7866]697    """A postgraduate applicant interface for editing.
698
699    Here we can repeat the fields from base data and set the
700    `required` and `readonly` attributes to True to further restrict
701    the data access. Or we can allow only certain certificates to be
702    selected by choosing the appropriate source.
703
704    We cannot omit fields here. This has to be done in the
705    respective form page.
[8017]706    """
[8454]707
[14106]708    referees = schema.List(
709        title = _(u'Referees'),
710        value_type = RefereeEntryField(),
711        required = False,
712        defaultFactory=list,
713        )
[13814]714
[14106]715ICustomPGApplicantEdit[
716    'referees'].order =  INigeriaPGApplicantEdit['emp2_reason'].order
717
[8928]718class ICustomApplicantOnlinePayment(INigeriaApplicantOnlinePayment):
[8247]719    """An applicant payment via payment gateways.
720
721    """
[8530]722
[14153]723class IPUTMEApplicantEdit(ICustomUGApplicant):
[8530]724    """An undergraduate applicant interface for editing.
725
726    Here we can repeat the fields from base data and set the
727    `required` and `readonly` attributes to True to further restrict
728    the data access. Or we can allow only certain certificates to be
729    selected by choosing the appropriate source.
730
731    We cannot omit fields here. This has to be done in the
732    respective form page.
733    """
734
[14153]735    email = schema.ASCIILine(
736        title = _(u'Email Address'),
737        required = True,
738        constraint=validate_email,
739        )
740    date_of_birth = FormattedDate(
741        title = _(u'Date of Birth'),
742        required = True,
743        show_year = True,
744        )
745    nationality = schema.Choice(
746        source = nats_vocab,
747        title = _(u'Nationality'),
748        required = True,
749        )
750
751IPUTMEApplicantEdit[
752    'date_of_birth'].order =  ICustomUGApplicant['date_of_birth'].order
753IPUTMEApplicantEdit[
754    'email'].order =  ICustomUGApplicant['email'].order
755IPUTMEApplicantEdit[
756    'nationality'].order =  ICustomUGApplicant['nationality'].order
757
[9056]758class ICustomApplicantUpdateByRegNo(INigeriaApplicantUpdateByRegNo):
[8582]759    """Representation of an applicant.
760
761    Skip regular reg_number validation if reg_number is used for finding
762    the applicant object.
763    """
Note: See TracBrowser for help on using the repository browser.