source: main/waeup.aaue/trunk/src/waeup/aaue/students/utils.py @ 13586

Last change on this file since 13586 was 13571, checked in by Henrik Bettermann, 9 years ago

Disable postgrad matric number generation.

  • Property svn:keywords set to Id
File size: 13.1 KB
RevLine 
[7419]1## $Id: utils.py 13571 2016-01-08 12:58:27Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
[7151]18import grok
[8600]19from time import time
20from zope.component import createObject
[10922]21from waeup.kofa.interfaces import (
[13348]22    ADMITTED, CLEARED, RETURNING, PAID, academic_sessions_vocab)
[8823]23from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
[8247]24from waeup.kofa.accesscodes import create_accesscode
[10922]25from waeup.kofa.students.utils import trans
[13414]26from waeup.aaue.interswitch.browser import gateway_net_amt
[8444]27from waeup.aaue.interfaces import MessageFactory as _
[6902]28
[8823]29class CustomStudentsUtils(NigeriaStudentsUtils):
[7151]30    """A collection of customized methods.
31
32    """
33
[13348]34    PORTRAIT_CHANGE_STATES = (ADMITTED, RETURNING)
35
[10641]36    gpa_boundaries = ((1, 'FRNS'),
37                      (1.5, 'Pass'),
38                      (2.4, '3rd Class Honours'),
39                      (3.5, '2nd Class Honours Lower Division'),
40                      (4.5, '2nd Class Honours Upper Division'),
41                      (5, '1st Class Honours'))
42
[13359]43    def increaseMatricInteger(self, student):
44        """Increase counter for matric numbers.
45        This counter can be a centrally stored attribute or an attribute of
46        faculties, departments or certificates. In the base package the counter
47        is as an attribute of the site configuration container.
48        """
49        if student.current_mode in ('ug_pt', 'de_pt'):
50            grok.getSite()['configuration'].next_matric_integer += 1
51            return
52        grok.getSite()['configuration'].next_matric_integer_2 += 1
53        return
54
[11596]55    def constructMatricNumber(self, student):
[11593]56        faccode = student.faccode
57        depcode = student.depcode
58        year = unicode(student.entry_session)[2:]
[13359]59        if not student.state in (PAID, ) or not student.is_fresh or \
60            student.current_mode == 'found':
61            return _('Matriculation number cannot be set.'), None
[13571]62        if student.is_postgrad:
63            return _('Matriculation number cannot be set.'), None
[13359]64        if student.current_mode in ('ug_pt', 'de_pt'):
65            next_integer = grok.getSite()['configuration'].next_matric_integer
66            if next_integer == 0:
67                return _('Matriculation number cannot be set.'), None
[12975]68            return None, "PTP/%s/%s/%s/%05d" % (
69                faccode, depcode, year, next_integer)
[13359]70        next_integer = grok.getSite()['configuration'].next_matric_integer_2
71        if next_integer == 0:
72            return _('Matriculation number cannot be set.'), None
73        if student.faccode in ('FBM', 'FCS'):
74            return None, "CMS/%s/%s/%s/%05d" % (
75                faccode, depcode, year, next_integer)
76        return None, "%s/%s/%s/%05d" % (faccode, depcode, year, next_integer)
[12975]77
[8270]78    def getReturningData(self, student):
79        """ This method defines what happens after school fee payment
[8319]80        of returning students depending on the student's senate verdict.
[8270]81        """
[8319]82        prev_level = student['studycourse'].current_level
83        cur_verdict = student['studycourse'].current_verdict
84        if cur_verdict in ('A','B','L','M','N','Z',):
85            # Successful student
86            new_level = divmod(int(prev_level),100)[0]*100 + 100
87        elif cur_verdict == 'C':
88            # Student on probation
89            new_level = int(prev_level) + 10
90        else:
91            # Student is somehow in an undefined state.
92            # Level has to be set manually.
93            new_level = prev_level
[8270]94        new_session = student['studycourse'].current_session + 1
95        return new_session, new_level
96
[13454]97    def _isPaymentDisabled(self, p_session, category, student):
98        academic_session = self._getSessionConfiguration(p_session)
99        if category == 'schoolfee' and \
100            'sf_all' in academic_session.payment_disabled:
101            return True
102        if category == 'hostel_maintenance' and \
103            'maint_all' in academic_session.payment_disabled:
104            return True
105        return False
106
[9154]107    def setPaymentDetails(self, category, student,
108            previous_session=None, previous_level=None):
[8600]109        """Create Payment object and set the payment data of a student for
110        the payment category specified.
111
112        """
[8306]113        details = {}
[8600]114        p_item = u''
115        amount = 0.0
116        error = u''
[9154]117        if previous_session:
118            return _('Previous session payment not yet implemented.'), None
[8600]119        p_session = student['studycourse'].current_session
120        p_level = student['studycourse'].current_level
[9154]121        p_current = True
[9527]122        academic_session = self._getSessionConfiguration(p_session)
123        if academic_session == None:
[8600]124            return _(u'Session configuration object is not available.'), None
[8677]125        # Determine fee.
[7151]126        if category == 'transfer':
[8600]127            amount = academic_session.transfer_fee
[10467]128        elif category == 'transcript':
129            amount = academic_session.transcript_fee
[7151]130        elif category == 'bed_allocation':
[8600]131            amount = academic_session.booking_fee
[7151]132        elif category == 'hostel_maintenance':
[13418]133            amount = 0.0
134            bedticket = student['accommodation'].get(
135                str(student.current_session), None)
[13502]136            if bedticket is not None and bedticket.bed is not None:
[13474]137                p_item = bedticket.display_coordinates
[13418]138                if bedticket.bed.__parent__.maint_fee > 0:
139                    amount = bedticket.bed.__parent__.maint_fee
140                else:
141                    # fallback
142                    amount = academic_session.maint_fee
143            else:
[13506]144                return _(u'No bed allocated.'), None
[13374]145        elif category == 'welfare':
146            amount = academic_session.welfare_fee
147        elif category == 'union':
148            amount = academic_session.union_fee
149        elif category == 'lapel':
150            amount = academic_session.lapel_fee
151        elif category == 'matric_gown':
152            amount = academic_session.matric_gown_fee
153        elif category == 'concessional':
[13464]154            amount = academic_session.concessional_fee
[13400]155        elif category.startswith('clearance'):
[11653]156            if student.faccode == 'FP':
157                amount = academic_session.clearance_fee_fp
[13377]158            elif student.current_mode.endswith('_pt'):
159                amount = academic_session.clearance_fee_pt
[13466]160            elif student.faccode == 'FCS':
161                # Students in clinical medical sciences pay the medical
162                # acceptance fee
[13377]163                amount = academic_session.clearance_fee_med
[13526]164            elif student.is_postgrad:
165                amount = academic_session.clearance_fee_pg
[11653]166            else:
167                amount = academic_session.clearance_fee
[8753]168            p_item = student['studycourse'].certificate.code
[13400]169            # Add Matric Gown Fee and Lapel Fee
[13410]170            if category.endswith('_incl'):
[13400]171                if amount is None:
172                    # Otherwise we can't add somtehing
173                    amount = 0.0
[13414]174                amount += gateway_net_amt(academic_session.matric_gown_fee) + \
175                    gateway_net_amt(academic_session.lapel_fee)
[11004]176        elif category == 'late_registration':
[13035]177            amount = academic_session.late_registration_fee
[13400]178        elif category.startswith('schoolfee'):
[8600]179            try:
[8753]180                certificate = student['studycourse'].certificate
181                p_item = certificate.code
[8600]182            except (AttributeError, TypeError):
183                return _('Study course data are incomplete.'), None
[13512]184            if student.state == CLEARED or category == 'schoolfee_2':
[13374]185                if student.is_foreigner:
186                    amount = getattr(certificate, 'school_fee_3', 0.0)
[10930]187                else:
[13374]188                    amount = getattr(certificate, 'school_fee_1', 0.0)
[13512]189                # Cut school fee by 50%
190                if category in ('schoolfee_1', 'schoolfee_2'):
191                    amount = amount / 2
192            elif category == 'schoolfee_1':
193                return _("Wrong state. Only students in state 'cleared' "
194                         "are allowed to pay by instalments."), None
[13374]195            elif student.state == RETURNING:
[13526]196                if student.is_postgrad and category == 'schoolfee_incl':
197                    return _("No additional fees required."), None
[13482]198                if not student.father_name:
199                    return _("Personal data form is not properly filled."), None
[13374]200                # In case of returning school fee payment the payment session
201                # and level contain the values of the session the student
202                # has paid for.
203                p_session, p_level = self.getReturningData(student)
[8961]204                try:
205                    academic_session = grok.getSite()[
206                        'configuration'][str(p_session)]
207                except KeyError:
208                    return _(u'Session configuration object is not available.'), None
[13374]209                if student.is_foreigner:
210                    amount = getattr(certificate, 'school_fee_4', 0.0)
211                else:
212                    amount = getattr(certificate, 'school_fee_2', 0.0)
[8600]213            else:
[8753]214                return _('Wrong state.'), None
[13417]215            if amount in (0.0, None):
216                return _(u'Amount could not be determined.'), None
[13400]217            # Add Student Union Fee and Welfare Assurance
[13512]218            if category in ('schoolfee_incl', 'schoolfee_1'):
[13414]219                amount += gateway_net_amt(academic_session.welfare_fee) + \
220                    gateway_net_amt(academic_session.union_fee)
[13534]221            # Add non-indigenous fee and session specific penalty fees
222            if student.is_postgrad:
223                amount += academic_session.penalty_pg
224                if not student.lga.startswith('edo'):
225                    amount += 20000.0
226            else:
227                amount += academic_session.penalty_ug
[8600]228        if amount in (0.0, None):
229            return _(u'Amount could not be determined.'), None
[13534]230
[8677]231        # Create ticket.
[8600]232        for key in student['payments'].keys():
233            ticket = student['payments'][key]
234            if ticket.p_state == 'paid' and\
235               ticket.p_category == category and \
236               ticket.p_item == p_item and \
237               ticket.p_session == p_session:
238                  return _('This type of payment has already been made.'), None
[11455]239        if self._isPaymentDisabled(p_session, category, student):
240            return _('Payment temporarily disabled.'), None
[8712]241        payment = createObject(u'waeup.StudentOnlinePayment')
[8954]242        timestamp = ("%d" % int(time()*10000))[1:]
[8600]243        payment.p_id = "p%s" % timestamp
244        payment.p_category = category
245        payment.p_item = p_item
246        payment.p_session = p_session
247        payment.p_level = p_level
[9154]248        payment.p_current = p_current
[8600]249        payment.amount_auth = amount
250        return None, payment
[7621]251
[10922]252    def _admissionText(self, student, portal_language):
253        inst_name = grok.getSite()['configuration'].name
254        entry_session = student['studycourse'].entry_session
255        entry_session = academic_sessions_vocab.getTerm(entry_session).title
256        text = trans(_(
[10953]257            'This is to inform you that you have been offered provisional'
258            ' admission into ${a} for the ${b} academic session as follows:',
[10922]259            mapping = {'a': inst_name, 'b': entry_session}),
260            portal_language)
261        return text
262
[10051]263    def maxCredits(self, studylevel):
264        """Return maximum credits.
265
266        """
267        return 48
268
[13353]269    def getBedCoordinates(self, bedticket):
270        """Return descriptive bed coordinates.
271        This method can be used to customize the `display_coordinates`
272        property method in order to  display a
273        customary description of the bed space.
274        """
275        bc = bedticket.bed_coordinates.split(',')
276        if len(bc) == 4:
277            return bc[0]
278        return bedticket.bed_coordinates
279
[13415]280    def getAccommodationDetails(self, student):
281        """Determine the accommodation data of a student.
282        """
283        d = {}
284        d['error'] = u''
285        hostels = grok.getSite()['hostels']
286        d['booking_session'] = hostels.accommodation_session
287        d['allowed_states'] = hostels.accommodation_states
288        d['startdate'] = hostels.startdate
289        d['enddate'] = hostels.enddate
290        d['expired'] = hostels.expired
291        # Determine bed type
[13416]292        bt = 'all'
[13415]293        if student.sex == 'f':
294            sex = 'female'
295        else:
296            sex = 'male'
297        special_handling = 'regular'
298        d['bt'] = u'%s_%s_%s' % (special_handling,sex,bt)
299        return d
300
[8444]301    # AAUE prefix
302    STUDENT_ID_PREFIX = u'E'
Note: See TracBrowser for help on using the repository browser.