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

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

Allow foundation programme students only to pay 'schoolfee', 'clearance', 'late_registration' fees.

  • Property svn:keywords set to Id
File size: 13.8 KB
RevLine 
[7419]1## $Id: utils.py 13636 2016-01-19 08:45:25Z 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
[13636]164        elif student.current_mode == 'found' and category not in (
165            'schoolfee', 'clearance', 'late_registration'):
166            return _('Not allowed.'), None
[13400]167        elif category.startswith('clearance'):
[13594]168            if student.state not in (ADMITTED, CLEARANCE, REQUESTED, CLEARED):
169                return _(u'Acceptance Fee payments not allowed.'), None
[11653]170            if student.faccode == 'FP':
171                amount = academic_session.clearance_fee_fp
[13377]172            elif student.current_mode.endswith('_pt'):
173                amount = academic_session.clearance_fee_pt
[13466]174            elif student.faccode == 'FCS':
175                # Students in clinical medical sciences pay the medical
176                # acceptance fee
[13377]177                amount = academic_session.clearance_fee_med
[13526]178            elif student.is_postgrad:
179                amount = academic_session.clearance_fee_pg
[11653]180            else:
181                amount = academic_session.clearance_fee
[8753]182            p_item = student['studycourse'].certificate.code
[13400]183            # Add Matric Gown Fee and Lapel Fee
[13410]184            if category.endswith('_incl'):
[13400]185                if amount is None:
186                    # Otherwise we can't add somtehing
187                    amount = 0.0
[13414]188                amount += gateway_net_amt(academic_session.matric_gown_fee) + \
189                    gateway_net_amt(academic_session.lapel_fee)
[11004]190        elif category == 'late_registration':
[13035]191            amount = academic_session.late_registration_fee
[13400]192        elif category.startswith('schoolfee'):
[8600]193            try:
[8753]194                certificate = student['studycourse'].certificate
195                p_item = certificate.code
[8600]196            except (AttributeError, TypeError):
197                return _('Study course data are incomplete.'), None
[13512]198            if student.state == CLEARED or category == 'schoolfee_2':
[13374]199                if student.is_foreigner:
200                    amount = getattr(certificate, 'school_fee_3', 0.0)
[10930]201                else:
[13374]202                    amount = getattr(certificate, 'school_fee_1', 0.0)
[13512]203                # Cut school fee by 50%
204                if category in ('schoolfee_1', 'schoolfee_2'):
205                    amount = amount / 2
206            elif category == 'schoolfee_1':
207                return _("Wrong state. Only students in state 'cleared' "
208                         "are allowed to pay by instalments."), None
[13374]209            elif student.state == RETURNING:
[13526]210                if student.is_postgrad and category == 'schoolfee_incl':
211                    return _("No additional fees required."), None
[13482]212                if not student.father_name:
213                    return _("Personal data form is not properly filled."), None
[13374]214                # In case of returning school fee payment the payment session
215                # and level contain the values of the session the student
216                # has paid for.
217                p_session, p_level = self.getReturningData(student)
[8961]218                try:
219                    academic_session = grok.getSite()[
220                        'configuration'][str(p_session)]
221                except KeyError:
222                    return _(u'Session configuration object is not available.'), None
[13374]223                if student.is_foreigner:
224                    amount = getattr(certificate, 'school_fee_4', 0.0)
225                else:
226                    amount = getattr(certificate, 'school_fee_2', 0.0)
[8600]227            else:
[8753]228                return _('Wrong state.'), None
[13417]229            if amount in (0.0, None):
230                return _(u'Amount could not be determined.'), None
[13400]231            # Add Student Union Fee and Welfare Assurance
[13512]232            if category in ('schoolfee_incl', 'schoolfee_1'):
[13414]233                amount += gateway_net_amt(academic_session.welfare_fee) + \
234                    gateway_net_amt(academic_session.union_fee)
[13534]235            # Add non-indigenous fee and session specific penalty fees
236            if student.is_postgrad:
237                amount += academic_session.penalty_pg
238                if not student.lga.startswith('edo'):
239                    amount += 20000.0
240            else:
241                amount += academic_session.penalty_ug
[8600]242        if amount in (0.0, None):
243            return _(u'Amount could not be determined.'), None
[13534]244
[8677]245        # Create ticket.
[8600]246        for key in student['payments'].keys():
247            ticket = student['payments'][key]
248            if ticket.p_state == 'paid' and\
249               ticket.p_category == category and \
250               ticket.p_item == p_item and \
251               ticket.p_session == p_session:
252                  return _('This type of payment has already been made.'), None
[11455]253        if self._isPaymentDisabled(p_session, category, student):
254            return _('Payment temporarily disabled.'), None
[8712]255        payment = createObject(u'waeup.StudentOnlinePayment')
[8954]256        timestamp = ("%d" % int(time()*10000))[1:]
[8600]257        payment.p_id = "p%s" % timestamp
258        payment.p_category = category
259        payment.p_item = p_item
260        payment.p_session = p_session
261        payment.p_level = p_level
[9154]262        payment.p_current = p_current
[8600]263        payment.amount_auth = amount
264        return None, payment
[7621]265
[10922]266    def _admissionText(self, student, portal_language):
267        inst_name = grok.getSite()['configuration'].name
268        entry_session = student['studycourse'].entry_session
269        entry_session = academic_sessions_vocab.getTerm(entry_session).title
270        text = trans(_(
[10953]271            'This is to inform you that you have been offered provisional'
272            ' admission into ${a} for the ${b} academic session as follows:',
[10922]273            mapping = {'a': inst_name, 'b': entry_session}),
274            portal_language)
275        return text
276
[10051]277    def maxCredits(self, studylevel):
278        """Return maximum credits.
279
280        """
281        return 48
282
[13353]283    def getBedCoordinates(self, bedticket):
284        """Return descriptive bed coordinates.
285        This method can be used to customize the `display_coordinates`
286        property method in order to  display a
287        customary description of the bed space.
288        """
289        bc = bedticket.bed_coordinates.split(',')
290        if len(bc) == 4:
291            return bc[0]
292        return bedticket.bed_coordinates
293
[13415]294    def getAccommodationDetails(self, student):
295        """Determine the accommodation data of a student.
296        """
297        d = {}
298        d['error'] = u''
299        hostels = grok.getSite()['hostels']
300        d['booking_session'] = hostels.accommodation_session
301        d['allowed_states'] = hostels.accommodation_states
302        d['startdate'] = hostels.startdate
303        d['enddate'] = hostels.enddate
304        d['expired'] = hostels.expired
305        # Determine bed type
[13416]306        bt = 'all'
[13415]307        if student.sex == 'f':
308            sex = 'female'
309        else:
310            sex = 'male'
311        special_handling = 'regular'
312        d['bt'] = u'%s_%s_%s' % (special_handling,sex,bt)
313        return d
314
[8444]315    # AAUE prefix
316    STUDENT_ID_PREFIX = u'E'
Note: See TracBrowser for help on using the repository browser.