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

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

Parttime and fulltime postgrad students pay different acceptance fees.

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