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

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

Implement matric number constructor for pg students.

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