Changeset 17370


Ignore:
Timestamp:
29 Mar 2023, 13:15:45 (21 months ago)
Author:
Henrik Bettermann
Message:

Implement transcript application.

Location:
main/kofacustom.edopoly/trunk/src/kofacustom/edopoly/applicants
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • main/kofacustom.edopoly/trunk/src/kofacustom/edopoly/applicants/applicant.py

    r15218 r17370  
    2727from kofacustom.edopoly.applicants.interfaces import(
    2828    ICustomApplicant, ICustomUGApplicantEdit, ICustomPGApplicantEdit,
    29     IPUTMEApplicantEdit, ICustomSpecialApplicant)
     29    IPUTMEApplicantEdit, ICustomSpecialApplicant, ITranscriptApplicant)
    3030
    3131class CustomApplicant(NigeriaApplicant):
    3232
    3333    grok.implements(ICustomApplicant, ICustomUGApplicantEdit,
    34         ICustomPGApplicantEdit, IPUTMEApplicantEdit, ICustomSpecialApplicant)
     34        ICustomPGApplicantEdit, IPUTMEApplicantEdit, ICustomSpecialApplicant,
     35        ITranscriptApplicant)
    3536    grok.provides(ICustomApplicant)
    3637
  • main/kofacustom.edopoly/trunk/src/kofacustom/edopoly/applicants/browser.py

    r15319 r17370  
    5151    ICustomUGApplicantEdit, ICustomUGApplicant,
    5252    ICustomPGApplicantEdit, ICustomPGApplicant,
    53     ICustomApplicant, ICustomSpecialApplicant,)
     53    ICustomApplicant, ICustomSpecialApplicant, ITranscriptApplicant)
    5454
    5555from kofacustom.edopoly.interfaces import MessageFactory as _
     
    8181    'aggregate')
    8282
     83TRANS_OMIT_FIELDS = ('suspended',)
     84
     85TRANS_SHORT_OMIT_FIELDS = TRANS_OMIT_FIELDS
     86
     87TRANS_OMIT_EDIT_FIELDS = TRANS_OMIT_FIELDS + ('applicant_id', )
     88
     89TRANS_SHORT_OMIT_EDIT_FIELDS = TRANS_SHORT_OMIT_FIELDS + ('applicant_id', )
     90
     91TRANS_OMIT_PDF_FIELDS = TRANS_OMIT_FIELDS + ('locked', )
     92
     93TRANS_SHORT_OMIT_PDF_FIELDS = TRANS_SHORT_OMIT_FIELDS + ('locked', )
     94
    8395class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
    8496    """A display view for applicant data.
     
    89101    def form_fields(self):
    90102        target = getattr(self.context.__parent__, 'prefix', None)
     103        if target is not None and target == 'tscf':
     104            form_fields = grok.AutoFields(ITranscriptApplicant)
     105            for field in TRANS_OMIT_FIELDS:
     106                form_fields = form_fields.omit(field)
     107            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
     108            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
     109            return form_fields
     110        if target is not None and target == 'tscs':
     111            form_fields = grok.AutoFields(ITranscriptApplicant)
     112            for field in TRANS_SHORT_OMIT_FIELDS:
     113                form_fields = form_fields.omit(field)
     114            form_fields['dispatch_address'].custom_widget = BytesDisplayWidget
     115            #form_fields['perm_address'].custom_widget = BytesDisplayWidget
     116            return form_fields
    91117        if self.context.special:
    92118            return grok.AutoFields(ICustomSpecialApplicant)
     
    223249    @property
    224250    def form_fields(self):
     251        target = getattr(self.context.__parent__, 'prefix', None)
     252        if target is not None and target == 'tscf':
     253            form_fields = grok.AutoFields(ITranscriptApplicant)
     254            for field in TRANS_OMIT_EDIT_FIELDS:
     255                form_fields = form_fields.omit(field)
     256            return form_fields
     257        if target is not None and target == 'tscs':
     258            form_fields = grok.AutoFields(ITranscriptApplicant)
     259            for field in TRANS_SHORT_OMIT_EDIT_FIELDS:
     260                form_fields = form_fields.omit(field)
     261            return form_fields
    225262        if self.context.special:
    226263            form_fields = grok.AutoFields(ICustomSpecialApplicant)
    227264            form_fields['applicant_id'].for_display = True
    228265            return form_fields
    229         target = getattr(self.context.__parent__, 'prefix', None)
    230266        form_fields = grok.AutoFields(ICustomUGApplicant)
    231267        for field in UG_OMIT_MANAGE_FIELDS:
     
    241277    @property
    242278    def form_fields(self):
     279        target = getattr(self.context.__parent__, 'prefix', None)
     280        state = IWorkflowState(self.context).getState()
     281        if target is not None and target == 'tscf':
     282            form_fields = grok.AutoFields(ITranscriptApplicant)
     283            form_fields['courier_tno'].for_display = True
     284            form_fields['proc_date'].for_display = True
     285            for field in TRANS_OMIT_EDIT_FIELDS:
     286                form_fields = form_fields.omit(field)
     287            if state == PAID:
     288                form_fields['order'].for_display = True
     289            form_fields = form_fields.omit('locked')
     290            return form_fields
     291        if target is not None and target == 'tscs':
     292            form_fields = grok.AutoFields(ITranscriptApplicant)
     293            form_fields['courier_tno'].for_display = True
     294            form_fields['proc_date'].for_display = True
     295            for field in TRANS_SHORT_OMIT_EDIT_FIELDS:
     296                form_fields = form_fields.omit(field)
     297            form_fields = form_fields.omit('locked')
     298            if state == PAID:
     299                form_fields['order'].for_display = True
     300            return form_fields
    243301        if self.context.special:
    244302            form_fields = grok.AutoFields(ICustomSpecialApplicant).omit(
     
    246304            form_fields['applicant_id'].for_display = True
    247305            return form_fields
    248         target = getattr(self.context.__parent__, 'prefix', None)
    249306        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
    250307        for field in UG_OMIT_EDIT_FIELDS:
  • main/kofacustom.edopoly/trunk/src/kofacustom/edopoly/applicants/interfaces.py

    r15218 r17370  
     1# -*- coding: utf-8 -*-
    12## $Id$
    23##
     
    2021
    2122from 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
    2227from waeup.kofa.applicants.interfaces import (
    2328    IApplicantBaseData,
     
    2530from waeup.kofa.schoolgrades import ResultEntryField
    2631from waeup.kofa.interfaces import (
    27     SimpleKofaVocabulary, academic_sessions_vocab, validate_email)
    28 from waeup.kofa.schema import FormattedDate, TextLineChoice
     32    SimpleKofaVocabulary, IKofaObject,
     33    academic_sessions_vocab, validate_email)
     34from waeup.kofa.university.vocabularies import StudyModeSource
     35from waeup.kofa.schema import FormattedDate, TextLineChoice, PhoneNumber
    2936from waeup.kofa.students.vocabularies import nats_vocab, GenderSource
    3037from waeup.kofa.applicants.interfaces import (
     
    4148from kofacustom.edopoly.payments.interfaces import ICustomOnlinePayment
    4249
     50class TranscriptCertificateSource(CertificateSource):
     51    """Include Department and Faculty in Title.
     52    """
     53    def getValues(self, context):
     54        catalog = getUtility(ICatalog, name='certificates_catalog')
     55        resultset = catalog.searchResults(code=(None, None))
     56        resultlist = sorted(resultset, key=lambda
     57            value: value.__parent__.__parent__.__parent__.code +
     58            value.__parent__.__parent__.code +
     59            value.code)
     60        return resultlist
     61
     62    def getTitle(self, context, value):
     63        """
     64        """
     65        try: title = "%s / %s / %s (%s)" % (
     66            value.__parent__.__parent__.__parent__.title,
     67            value.__parent__.__parent__.title,
     68            value.title, value.code)
     69        except AttributeError:
     70            title = "NA / %s (%s)" % (value.title, value.code)
     71        return title
     72
     73DESTINATION_COST = {
     74    #'none': ('To the moon', 1000000000.0, 1),
     75    'nigeria': ('Within Nigeria', 20000.0, 1),
     76    'africa': ('Within Africa ', 30000.0, 2),
     77    'inter': ('International', 35000.0, 3),
     78    'cert_nigeria': ('Certified Copy - Within Nigeria', 13000.0, 4),
     79    'cert_africa': ('Certified Copy - Within Africa', 23000.0, 5),
     80    'cert_inter': ('Certified Copy - International', 28000.0, 6),
     81    }
     82
     83class DestinationCostSource(BasicSourceFactory):
     84    """A source that delivers continents and shipment costs.
     85    """
     86    def getValues(self):
     87        sorted_items = sorted(DESTINATION_COST.items(),
     88                              key=lambda element: element[1][2])
     89        return [item[0] for item in sorted_items]
     90
     91    def getToken(self, value):
     92        return value
     93
     94    def getTitle(self, value):
     95        return u"%s (₦ %s)" % (
     96            DESTINATION_COST[value][0],
     97            DESTINATION_COST[value][1])
     98
     99class OrderSource(BasicSourceFactory):
     100    """
     101    """
     102    def getValues(self):
     103        return ['o', 'c']
     104
     105    def getToken(self, value):
     106        return value
     107
     108    def getTitle(self, value):
     109        if value == 'o':
     110            return _('Original')
     111        if value == 'c':
     112            return _('Certified True Copy')
     113
    43114class ICustomUGApplicant(IApplicantBaseData):
    44115    """An undergraduate applicant.
     
    218289        )
    219290
     291class ITranscriptApplicant(IKofaObject):
     292    """A transcript applicant.
     293    """
     294
     295    suspended = schema.Bool(
     296        title = _(u'Account suspended'),
     297        default = False,
     298        required = False,
     299        )
     300
     301    locked = schema.Bool(
     302        title = _(u'Form locked'),
     303        default = False,
     304        required = False,
     305        )
     306
     307    applicant_id = schema.TextLine(
     308        title = _(u'Transcript Application Id'),
     309        required = False,
     310        readonly = False,
     311        )
     312
     313    student_id = schema.TextLine(
     314        title = _(u'Kofa Student Id'),
     315        required = False,
     316        readonly = False,
     317        )
     318
     319    matric_number = schema.TextLine(
     320        title = _(u'Matriculation Number'),
     321        readonly = False,
     322        required = True,
     323        )
     324
     325    firstname = schema.TextLine(
     326        title = _(u'First Name in School'),
     327        required = True,
     328        )
     329
     330    middlename = schema.TextLine(
     331        title = _(u'Middle Name in School'),
     332        required = False,
     333        )
     334
     335    lastname = schema.TextLine(
     336        title = _(u'Surname in School'),
     337        required = True,
     338        )
     339
     340    date_of_birth = FormattedDate(
     341        title = _(u'Date of Birth'),
     342        required = False,
     343        #date_format = u'%d/%m/%Y', # Use grok-instance-wide default
     344        show_year = True,
     345        )
     346
     347    sex = schema.Choice(
     348        title = _(u'Gender'),
     349        source = GenderSource(),
     350        required = True,
     351        )
     352
     353    #nationality = schema.Choice(
     354    #    vocabulary = nats_vocab,
     355    #    title = _(u'Nationality'),
     356    #    required = False,
     357    #    )
     358
     359    email = schema.ASCIILine(
     360        title = _(u'Email Address'),
     361        required = True,
     362        constraint=validate_email,
     363        )
     364
     365    phone = PhoneNumber(
     366        title = _(u'Phone'),
     367        description = u'',
     368        required = False,
     369        )
     370
     371    #perm_address = schema.Text(
     372    #    title = _(u'Current Local Address'),
     373    #    required = False,
     374    #    readonly = False,
     375    #    )
     376
     377    collected = schema.Bool(
     378        title = _(u'Have you collected transcript before?'),
     379        default = False,
     380        required = False,
     381        )
     382
     383    entry_session = schema.Choice(
     384        title = _(u'Academic Session of Entry'),
     385        source = academic_sessions_vocab,
     386        required = False,
     387        readonly = False,
     388        )
     389
     390    end_session = schema.Choice(
     391        title = _(u'Academic Session of Graduation'),
     392        source = academic_sessions_vocab,
     393        required = False,
     394        readonly = False,
     395        )
     396
     397    entry_mode = schema.Choice(
     398        title = _(u'Mode of Entry'),
     399        source = StudyModeSource(),
     400        required = False,
     401        readonly = False,
     402        )
     403
     404    course_studied = schema.Choice(
     405        title = _(u'Course of Study'),
     406        source = TranscriptCertificateSource(),
     407        description = u'Faculty / Department / Course',
     408        required = True,
     409        readonly = False,
     410        )
     411
     412    course_changed = schema.Choice(
     413        title = _(u'Change of Study Course / Transfer'),
     414        description = u'If yes, select previous course of study.',
     415        source = TranscriptCertificateSource(),
     416        readonly = False,
     417        required = False,
     418        )
     419
     420    spillover_level = schema.Choice(
     421        title = _(u'Spill-over'),
     422        description = u'Any spill-over? If yes, select session of spill-over.',
     423        source = academic_sessions_vocab,
     424        required = False,
     425        readonly = False,
     426        )
     427
     428    purpose = schema.TextLine(
     429        title = _(u'Transcript Purpose'),
     430        required = False,
     431        )
     432
     433    order = schema.Choice(
     434        source = OrderSource(),
     435        title = _(u'Type of Order'),
     436        required = False,
     437        )
     438
     439    dispatch_address = schema.Text(
     440        title = _(u'Recipient Body'),
     441        description = u'Addresses (including email address and phone number) '
     442                       'to which transcripts should be posted. '
     443                       'All addresses must involve same courier charges.',
     444        required = True,
     445        readonly = False,
     446        )
     447
     448    charge = schema.Choice(
     449        title = _(u'Transcript Charge'),
     450        source = DestinationCostSource(),
     451        required = False,
     452        readonly = False,
     453        )
     454
     455    no_copies = schema.Choice(
     456        title = _(u'Number of Copies'),
     457        description = u'Must correspond with the number of dispatch addresses above.',
     458        values=[1, 2, 3, 4],
     459        required = False,
     460        readonly = False,
     461        default = 1,
     462        )
     463
     464    courier_tno = schema.TextLine(
     465        title = _(u'Courier Tracking Number'),
     466        required = False,
     467        )
     468
     469    proc_date = FormattedDate(
     470        title = _(u'Processing Date'),
     471        required = False,
     472        #date_format = u'%d/%m/%Y', # Use grok-instance-wide default
     473        show_year = True,
     474        )
     475
     476    @invariant
     477    def type_of_order(applicant):
     478        if not applicant.collected and applicant.order != 'o':
     479            raise Invalid(_("If you haven't collected transcript before, type of order must be 'original'."))
     480        if applicant.order == 'o' and applicant.charge.startswith('cert_'):
     481            raise Invalid(_("You've selected the wrong transcript charge."))
     482        if applicant.order == 'c' and not applicant.charge.startswith('cert_'):
     483            raise Invalid(_("You've selected the wrong transcript charge."))
     484
    220485class ICustomPGApplicant(INigeriaPGApplicant):
    221486    """A postgraduate applicant.
     
    230495    """
    231496
    232 class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant):
     497class ICustomApplicant(ICustomUGApplicant, ICustomPGApplicant,
     498    ITranscriptApplicant):
    233499    """An interface for both types of applicants.
    234500
  • main/kofacustom.edopoly/trunk/src/kofacustom/edopoly/applicants/utils.py

    r15410 r17370  
    4545        'hnde': ['HND Part-Time Evening Programmes', 'HNDE'],
    4646        'nde': ['ND Part-Time Evening Programmes', 'NDE'],
     47        'tscf': ['Transcript (without student record)', 'TRF'],
     48        'tscs': ['Transcript (with student record)', 'TRS'],
    4749        }
    4850
Note: See TracChangeset for help on using the changeset viewer.