source: main/kofacustom.edocons/trunk/src/kofacustom/edocons/applicants/interfaces.py @ 17053

Last change on this file since 17053 was 17053, checked in by Henrik Bettermann, 2 years ago

Fix fees.

  • Property svn:keywords set to Id
File size: 18.9 KB
Line 
1# -*- coding: utf-8 -*-
2## $Id: interfaces.py 17053 2022-08-02 13:40:59Z 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 zope.interface import invariant, Invalid
24from zope.component import getUtility
25from zope.catalog.interfaces import ICatalog
26from zc.sourcefactory.basic import BasicSourceFactory
27from waeup.kofa.university.vocabularies import StudyModeSource
28from waeup.kofa.applicants.interfaces import (
29    IApplicantBaseData,
30    AppCatCertificateSource, CertificateSource)
31from waeup.kofa.schoolgrades import ResultEntryField
32from waeup.kofa.interfaces import (
33    SimpleKofaVocabulary, academic_sessions_vocab, validate_email,
34    IKofaObject)
35from waeup.kofa.schema import FormattedDate, TextLineChoice, PhoneNumber
36from waeup.kofa.students.vocabularies import nats_vocab, GenderSource
37from waeup.kofa.applicants.interfaces import (
38    contextual_reg_num_source,
39    IApplicantBaseData)
40from kofacustom.nigeria.applicants.interfaces import (
41    LGASource, high_qual, high_grade, exam_types,
42    jambsubjects,
43    INigeriaUGApplicant, INigeriaPGApplicant,
44    INigeriaApplicantOnlinePayment,
45    INigeriaUGApplicantEdit, INigeriaPGApplicantEdit,
46    INigeriaApplicantUpdateByRegNo,
47    IPUTMEApplicantEdit,
48    )
49from kofacustom.nigeria.interfaces import (
50    LGASource, DisabilitiesSource,
51    high_qual, high_grade, exam_types, validate_jamb_reg_number)
52
53from kofacustom.edocons.interfaces import MessageFactory as _
54from kofacustom.edocons.payments.interfaces import ICustomOnlinePayment
55
56programme_types_vocab = SimpleKofaVocabulary(
57    (_('Post UTME'), 'putme'),
58    (_('Post DE'), 'pude'),
59    (_('Admission Screening Exercise'), 'ase'),
60    (_('not applicable'), 'na'),
61    )
62
63DESTINATION_COST = {
64    #'none': ('To the moon', 1000000000.0, 1),
65    'australia': ('Australia', 44500.0, 1),
66    'india': ('Arab Emirate/China/India/Saudi Arabia', 38500.0, 2),
67    'ghana': ('Benin/Ghana/South Africa',  37000.0, 3),
68    'isreal': ('Isreal/Turkey', 33500.0, 4),
69    'canada': ('Canada', 30500.0, 5),
70    'germany': ('Finland/France/Germany/Netherlands', 30000.0, 6),
71    'usa': ('USA', 29500.0, 7),
72    'uk': ('UK', 23500.0, 8),
73    'north': ('Nigeria North', 11800.0, 9),
74    'abuja': ('Abuja/Lokoja', 11200.0, 10),
75    'south': ('Nigeria South East/South/South West', 10700.0, 11),
76    }
77
78class DestinationCostSource(BasicSourceFactory):
79    """A source that delivers continents and shipment costs.
80    """
81    def getValues(self):
82        sorted_items = sorted(DESTINATION_COST.items(),
83                              key=lambda element: element[1][2])
84        return [item[0] for item in sorted_items]
85
86    def getToken(self, value):
87        return value
88
89    def getTitle(self, value):
90        return u"%s (₦ %s)" % (
91            DESTINATION_COST[value][0],
92            DESTINATION_COST[value][1])
93
94class OrderSource(BasicSourceFactory):
95    """
96    """
97    def getValues(self):
98        return ['o', 'c']
99
100    def getToken(self, value):
101        return value
102
103    def getTitle(self, value):
104        if value == 'o':
105            return _('Original')
106        if value == 'c':
107            return _('Certified True Copy')
108
109class TranscriptCertificateSource(CertificateSource):
110    """Include Department and Faculty in Title.
111    """
112    def getValues(self, context):
113        catalog = getUtility(ICatalog, name='certificates_catalog')
114        resultset = catalog.searchResults(code=(None, None))
115        resultlist = sorted(resultset, key=lambda
116            value: value.__parent__.__parent__.__parent__.code +
117            value.__parent__.__parent__.code +
118            value.code)
119        return resultlist
120
121    def getTitle(self, context, value):
122        """
123        """
124        try: title = "%s / %s / %s (%s)" % (
125            value.__parent__.__parent__.__parent__.title,
126            value.__parent__.__parent__.title,
127            value.title, value.code)
128        except AttributeError:
129            title = "NA / %s (%s)" % (value.title, value.code)
130        return title
131
132class ICustomUGApplicant(INigeriaUGApplicant):
133    """An undergraduate applicant.
134    """
135
136    disabilities = schema.Choice(
137        title = _(u'Disability'),
138        source = DisabilitiesSource(),
139        required = False,
140        )
141    nationality = schema.Choice(
142        source = nats_vocab,
143        title = _(u'Nationality'),
144        required = False,
145        )
146    lga = schema.Choice(
147        source = LGASource(),
148        title = _(u'State/LGA (Nigerians only)'),
149        required = True,
150        )
151    perm_address = schema.Text(
152        title = _(u'Permanent Address'),
153        required = False,
154        )
155
156    next_kin_name = schema.TextLine(
157        title = _(u'Next of Kin Name'),
158        required = False,
159        readonly = False,
160        )
161
162    next_kin_relation = schema.TextLine(
163        title = _(u'Next of Kin Relationship'),
164        required = False,
165        readonly = False,
166        )
167
168    next_kin_address = schema.Text(
169        title = _(u'Next of Kin Address'),
170        required = False,
171        readonly = False,
172        )
173
174    next_kin_phone = PhoneNumber(
175        title = _(u'Next of Kin Phone'),
176        required = False,
177        readonly = False,
178        )
179
180    course1 = schema.Choice(
181        title = _(u'1st Choice Course of Study'),
182        source = AppCatCertificateSource(),
183        required = True,
184        )
185    course2 = schema.Choice(
186        title = _(u'2nd Choice Course of Study'),
187        source = AppCatCertificateSource(),
188        required = False,
189        )
190
191    fst_sit_fname = schema.TextLine(
192        title = _(u'Full Name'),
193        required = False,
194        readonly = False,
195        )
196
197    fst_sit_no = schema.TextLine(
198        title = _(u'Exam Number'),
199        required = False,
200        readonly = False,
201        )
202
203    fst_sit_date = FormattedDate(
204        title = _(u'Exam Date'),
205        required = False,
206        readonly = False,
207        show_year = True,
208        )
209
210    fst_sit_type = schema.Choice(
211        title = _(u'Exam Type'),
212        required = False,
213        readonly = False,
214        vocabulary = exam_types,
215        )
216
217    fst_sit_results = schema.List(
218        title = _(u'Exam Results'),
219        value_type = ResultEntryField(),
220        required = False,
221        readonly = False,
222        defaultFactory=list,
223        )
224
225    scd_sit_fname = schema.TextLine(
226        title = _(u'Full Name'),
227        required = False,
228        readonly = False,
229        )
230
231    scd_sit_no = schema.TextLine(
232        title = _(u'Exam Number'),
233        required = False,
234        readonly = False,
235        )
236
237    scd_sit_date = FormattedDate(
238        title = _(u'Exam Date'),
239        required = False,
240        readonly = False,
241        show_year = True,
242        )
243
244    scd_sit_type = schema.Choice(
245        title = _(u'Exam Type'),
246        required = False,
247        readonly = False,
248        vocabulary = exam_types,
249        )
250
251    scd_sit_results = schema.List(
252        title = _(u'Exam Results'),
253        value_type = ResultEntryField(),
254        required = False,
255        readonly = False,
256        defaultFactory=list,
257        )
258
259    programme_type = schema.Choice(
260        title = _(u'Programme Type'),
261        vocabulary = programme_types_vocab,
262        required = False,
263        )
264
265    hq_type = schema.Choice(
266        title = _(u'Qualification Obtained'),
267        required = False,
268        readonly = False,
269        vocabulary = high_qual,
270        )
271    hq_matric_no = schema.TextLine(
272        title = _(u'Former Matric Number'),
273        required = False,
274        readonly = False,
275        )
276    hq_degree = schema.Choice(
277        title = _(u'Class of Degree'),
278        required = False,
279        readonly = False,
280        vocabulary = high_grade,
281        )
282    hq_school = schema.TextLine(
283        title = _(u'Institution Attended'),
284        required = False,
285        readonly = False,
286        )
287    hq_session = schema.TextLine(
288        title = _(u'Years Attended'),
289        required = False,
290        readonly = False,
291        )
292    hq_disc = schema.TextLine(
293        title = _(u'Discipline'),
294        required = False,
295        readonly = False,
296        )
297    jamb_subjects = schema.Text(
298        title = _(u'Subjects and Scores'),
299        required = False,
300        )
301    jamb_subjects_list = schema.List(
302        title = _(u'JAMB Subjects'),
303        required = False,
304        defaultFactory=list,
305        value_type = schema.Choice(
306            vocabulary = jambsubjects
307            #source = JAMBSubjectSource(),
308            ),
309        )
310    jamb_score = schema.Int(
311        title = _(u'Total JAMB Score'),
312        required = False,
313        )
314    #jamb_age = schema.Int(
315    #    title = _(u'Age (provided by JAMB)'),
316    #    required = False,
317    #    )
318    jamb_reg_number = schema.TextLine(
319        title = _(u'JAMB Registration Number'),
320        required = False,
321        constraint=validate_jamb_reg_number,
322        )
323    cbt_score = schema.Int(
324        title = _(u'CBT Score'),
325        required = False,
326        )
327    cbt_venue = schema.TextLine(
328        title = _(u'CBT Venue'),
329        required = False,
330        )
331    cbt_date = FormattedDate(
332        title = _(u'CBT Date'),
333        required = False,
334        )
335    notice = schema.Text(
336        title = _(u'Notice'),
337        required = False,
338        )
339    screening_venue = schema.TextLine(
340        title = _(u'Screening Venue'),
341        required = False,
342        )
343    screening_date = schema.TextLine(
344        title = _(u'Screening Date'),
345        required = False,
346        )
347    screening_score = schema.Int(
348        title = _(u'Screening Score (%)'),
349        required = False,
350        )
351    aggregate = schema.Int(
352        title = _(u'Aggregate Score (%)'),
353        description = _(u'(average of relative JAMB and PUTME scores)'),
354        required = False,
355        )
356    result_uploaded = schema.Bool(
357        title = _(u'Result uploaded'),
358        default = False,
359        required = False,
360        )
361    student_id = schema.TextLine(
362        title = _(u'Student Id'),
363        required = False,
364        readonly = False,
365        )
366    course_admitted = schema.Choice(
367        title = _(u'Admitted Course of Study'),
368        source = CertificateSource(),
369        required = False,
370        )
371    locked = schema.Bool(
372        title = _(u'Form locked'),
373        default = False,
374        required = False,
375        )
376
377class ICustomPGApplicant(INigeriaPGApplicant):
378    """A postgraduate applicant.
379
380    This interface defines the least common multiple of all fields
381    in pg application forms. In customized forms, fields can be excluded by
382    adding them to the PG_OMIT* tuples.
383    """
384
385class ITranscriptApplicant(IKofaObject):
386    """A transcript applicant.
387    """
388
389    suspended = schema.Bool(
390        title = _(u'Account suspended'),
391        default = False,
392        required = False,
393        )
394
395    locked = schema.Bool(
396        title = _(u'Form locked'),
397        default = False,
398        required = False,
399        )
400
401    applicant_id = schema.TextLine(
402        title = _(u'Transcript Application Id'),
403        required = False,
404        readonly = False,
405        )
406
407    student_id = schema.TextLine(
408        title = _(u'Kofa Student Id'),
409        required = False,
410        readonly = False,
411        )
412
413    matric_number = schema.TextLine(
414        title = _(u'Matriculation Number'),
415        readonly = False,
416        required = True,
417        )
418
419    firstname = schema.TextLine(
420        title = _(u'First Name in School'),
421        required = True,
422        )
423
424    middlename = schema.TextLine(
425        title = _(u'Middle Name in School'),
426        required = False,
427        )
428
429    lastname = schema.TextLine(
430        title = _(u'Surname in School'),
431        required = True,
432        )
433
434    date_of_birth = FormattedDate(
435        title = _(u'Date of Birth'),
436        required = False,
437        #date_format = u'%d/%m/%Y', # Use grok-instance-wide default
438        show_year = True,
439        )
440
441    sex = schema.Choice(
442        title = _(u'Gender'),
443        source = GenderSource(),
444        required = True,
445        )
446
447    #nationality = schema.Choice(
448    #    vocabulary = nats_vocab,
449    #    title = _(u'Nationality'),
450    #    required = False,
451    #    )
452
453    email = schema.ASCIILine(
454        title = _(u'Email Address'),
455        required = True,
456        constraint=validate_email,
457        )
458
459    phone = PhoneNumber(
460        title = _(u'Phone'),
461        description = u'',
462        required = False,
463        )
464
465    #perm_address = schema.Text(
466    #    title = _(u'Current Local Address'),
467    #    required = False,
468    #    readonly = False,
469    #    )
470
471    collected = schema.Bool(
472        title = _(u'Have you collected transcript before?'),
473        default = False,
474        required = False,
475        )
476
477    entry_session = schema.Choice(
478        title = _(u'Academic Session of Entry'),
479        source = academic_sessions_vocab,
480        required = False,
481        readonly = False,
482        )
483
484    end_session = schema.Choice(
485        title = _(u'Academic Session of Graduation'),
486        source = academic_sessions_vocab,
487        required = False,
488        readonly = False,
489        )
490
491    entry_mode = schema.Choice(
492        title = _(u'Mode of Entry'),
493        source = StudyModeSource(),
494        required = False,
495        readonly = False,
496        )
497
498    course_studied = schema.Choice(
499        title = _(u'Course of Study'),
500        source = TranscriptCertificateSource(),
501        description = u'Faculty / Department / Course',
502        required = True,
503        readonly = False,
504        )
505
506    #course_changed = schema.Choice(
507    #    title = _(u'Change of Study Course / Transfer'),
508    #    description = u'If yes, select previous course of study.',
509    #    source = TranscriptCertificateSource(),
510    #    readonly = False,
511    #    required = False,
512    #    )
513
514    spillover_level = schema.Choice(
515        title = _(u'Spill-over'),
516        description = u'Any spill-over? If yes, select session of spill-over.',
517        source = academic_sessions_vocab,
518        required = False,
519        readonly = False,
520        )
521
522    purpose = schema.TextLine(
523        title = _(u'Transcript Purpose'),
524        required = False,
525        )
526
527    order = schema.Choice(
528        source = OrderSource(),
529        title = _(u'Type of Order'),
530        required = True,
531        )
532
533    dispatch_address = schema.Text(
534        title = _(u'Recipient Body'),
535        description = u'Addresses (including email address and phone number) '
536                       'to which transcripts should be posted. '
537                       'All addresses must involve same courier charges.',
538        required = True,
539        readonly = False,
540        )
541
542    charge = schema.Choice(
543        title = _(u'Transcript Charge'),
544        source = DestinationCostSource(),
545        required = True,
546        readonly = False,
547        )
548       
549    curriculum = schema.Bool(
550        title = _(u'Including curriculum'),
551        description = u'₦ 5000 will be added to transcript charge.',
552        default = False,
553        required = False,
554        )
555
556    no_copies = schema.Choice(
557        title = _(u'Number of Copies'),
558        description = u'Must correspond with the number of dispatch addresses above.',
559        values=[1, 2, 3, 4],
560        required = False,
561        readonly = False,
562        default = 1,
563        )
564
565    courier_tno = schema.TextLine(
566        title = _(u'Courier Tracking Number'),
567        required = False,
568        )
569
570    proc_date = FormattedDate(
571        title = _(u'Processing Date'),
572        required = False,
573        #date_format = u'%d/%m/%Y', # Use grok-instance-wide default
574        show_year = True,
575        )
576
577    @invariant
578    def type_of_order(applicant):
579        if not applicant.collected and applicant.order != 'o':
580            raise Invalid(_("If you haven't collected transcript before, type of order must be 'original'."))
581        if applicant.order == 'o' and applicant.charge.startswith('cert_'):
582            raise Invalid(_("You've selected the wrong transcript charge."))
583        if applicant.order == 'c' and not applicant.charge.startswith('cert_'):
584            raise Invalid(_("You've selected the wrong transcript charge."))
585
586
587class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant,
588                       ITranscriptApplicant):
589    """An interface for both types of applicants.
590
591    Attention: The ICustomPGApplicant field seetings will be overwritten
592    by ICustomPGApplicant field settings. If a field is defined
593    in both interfaces zope.schema validates only against the
594    constraints in ICustomUGApplicant. This does not affect the forms
595    since they are build on either ICustomUGApplicant or ICustomPGApplicant.
596    """
597
598    def writeLogMessage(view, comment):
599        """Adds an INFO message to the log file
600        """
601
602    def createStudent():
603        """Create a student object from applicant data
604        and copy applicant object.
605        """
606
607class ICustomUGApplicantEdit(ICustomUGApplicant):
608    """An undergraduate applicant interface for edit forms.
609
610    Here we can repeat the fields from base data and set the
611    `required` and `readonly` attributes to True to further restrict
612    the data access. Or we can allow only certain certificates to be
613    selected by choosing the appropriate source.
614
615    We cannot omit fields here. This has to be done in the
616    respective form page.
617    """
618
619class ICustomPGApplicantEdit(INigeriaPGApplicantEdit):
620    """A postgraduate applicant interface for editing.
621
622    Here we can repeat the fields from base data and set the
623    `required` and `readonly` attributes to True to further restrict
624    the data access. Or we can allow only certain certificates to be
625    selected by choosing the appropriate source.
626
627    We cannot omit fields here. This has to be done in the
628    respective form page.
629    """
630
631class ICustomApplicantOnlinePayment(INigeriaApplicantOnlinePayment):
632    """An applicant payment via payment gateways.
633
634    """
635
636class IPUTMEApplicantEdit(IPUTMEApplicantEdit):
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
648class ICustomApplicantUpdateByRegNo(INigeriaApplicantUpdateByRegNo):
649    """Representation of an applicant.
650
651    Skip regular reg_number validation if reg_number is used for finding
652    the applicant object.
653    """
Note: See TracBrowser for help on using the repository browser.