source: main/kofacustom.coewarri/trunk/src/kofacustom/coewarri/students/utils.py @ 16161

Last change on this file since 16161 was 16002, checked in by Henrik Bettermann, 5 years ago

Change 300 level school fees.

  • Property svn:keywords set to Id
File size: 8.8 KB
Line 
1## $Id: utils.py 16002 2020-02-13 13:57:47Z 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##
18from time import time
19from zope.component import createObject, getUtility
20from waeup.kofa.fees import FeeTable
21from waeup.kofa.interfaces import (IKofaUtils,
22    ADMITTED, CLEARED, RETURNING, PAID, REGISTERED, VALIDATED)
23from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
24from kofacustom.coewarri.interfaces import MessageFactory as _
25from kofacustom.coewarri.interswitch.browser import GATEWAY_AMT
26
27
28def local_nonlocal(student):
29    lga = getattr(student, 'lga')
30    if lga and lga.startswith('delta'):
31        return 'local'
32    else:
33        return 'non-local'
34
35PAYMENT_LEVELS = (100, 110, 200, 210, 300, 310, 400, 410, 500, 999)
36
37FEES_PARAMS = (
38        ('local', 'non-local'),
39        ('nce_ft', 'nce_pt', 'ug_ft', 'nce_we_pt'),
40        PAYMENT_LEVELS
41    )
42
43FEES_VALUES = (
44     ( # 100      110      200      210      300      310      400      410     500  999
45       (43200.0, 43200.0, 42700.0, 42700.0, 37200.0, 37200.0, 0.0, 0.0, 0.0, 0.0), # nce_ft
46       (55200.0, 55200.0, 49200.0, 49200.0, 53200.0, 53200.0, 49200.0, 49200.0, 0.0, 0.0), # nce_pt
47       (70200.0, 70200.0, 63700.0, 63700.0, 67700.0, 67700.0, 61700.0, 61700.0, 0.0, 0.0), # ug_ft
48       (33200.0, 33200.0, 28000.0, 28000.0, 32000.0, 32000.0, 28000.0, 28000.0, 0.0, 0.0), # nce_we_pt
49     ), # local
50     ( #
51       (55800.0, 55800.0, 54800.0, 54800.0, 49800.0, 49800.0, 0.0, 0.0, 0.0, 0.0), # nce_ft
52       (55200.0, 55200.0, 49200.0, 49200.0, 53200.0, 53200.0, 49200.0, 49200.0, 0.0, 0.0), # nce_pt
53       (80200.0, 80200.0, 73700.0, 73700.0, 77700.0, 77700.0, 71700.0, 71700.0, 0.0, 0.0), # ug_ft
54       (33200.0, 33200.0, 28000.0, 28000.0, 32000.0, 32000.0, 28000.0, 28000.0, 0.0, 0.0), # nce_we_pt
55     ), # non-local
56   )
57
58SCHOOL_FEES = FeeTable(FEES_PARAMS, FEES_VALUES)
59
60class CustomStudentsUtils(NigeriaStudentsUtils):
61    """A collection of customized methods.
62
63    """
64
65    def warnCreditsOOR(self, studylevel, course=None):
66        """Return message if credits are out of range.
67        """
68        if studylevel.student.current_mode == 'nce_ft':
69            limit = 56
70        elif studylevel.student.current_mode == 'ug_ft':
71            limit = 48
72            if studylevel.level == 400:
73                limit = 51
74        else:
75            limit = 50
76        if course and studylevel.total_credits + course.credits > limit:
77            return _('Maximum credits exceeded.')
78        elif studylevel.total_credits > limit:
79            return _('Maximum credits exceeded.')
80        return
81
82    def _isPaymentDisabled(self, p_session, category, student):
83        academic_session = self._getSessionConfiguration(p_session)
84        if category.startswith('schoolfee'):
85            if 'sf_all' in academic_session.payment_disabled:
86                return True
87            if student.current_mode == 'ug_ft' and \
88                'degree' in academic_session.payment_disabled:
89                return True
90        return False
91
92    def setPaymentDetails(self, category, student,
93            previous_session=None, previous_level=None, combi=[]):
94        """Create a payment ticket and set the payment data of a
95        student for the payment category specified.
96        """
97        p_item = u''
98        amount = 0.0
99        if previous_session:
100            if previous_session < student['studycourse'].entry_session:
101                return _('The previous session must not fall below '
102                         'your entry session.'), None
103            if category == 'schoolfee':
104                # School fee is always paid for the following session
105                if previous_session > student['studycourse'].current_session:
106                    return _('This is not a previous session.'), None
107            else:
108                if previous_session > student['studycourse'].current_session - 1:
109                    return _('This is not a previous session.'), None
110            p_session = previous_session
111            p_level = previous_level
112            p_current = False
113        else:
114            p_session = student['studycourse'].current_session
115            p_level = student['studycourse'].current_level
116            p_current = True
117        academic_session = self._getSessionConfiguration(p_session)
118        if academic_session == None:
119            return _(u'Session configuration object is not available.'), None
120        # Determine fee.
121        if category.startswith('schoolfee'):
122            try:
123                certificate = student['studycourse'].certificate
124                p_item = certificate.code
125            except (AttributeError, TypeError):
126                return _('Study course data are incomplete.'), None
127            if student.state == RETURNING:
128                # Override p_session and p_level
129                p_session, p_level = self.getReturningData(student)
130                academic_session = self._getSessionConfiguration(p_session)
131                if academic_session == None:
132                    return _(u'Session configuration object '
133                              'is not available.'), None
134            if p_level in PAYMENT_LEVELS:
135                amount = SCHOOL_FEES.get_fee(
136                    (
137                     local_nonlocal(student),
138                     student.current_mode,
139                     p_level)
140                    )
141                if student.entry_mode == 'de_ft' and p_level == 200 \
142                    and student['studycourse'].entry_session >= 2019:
143                    amount += 10500
144            if amount and category in ('schoolfee_1', 'schoolfee_2'):
145                amount /= 2
146            if amount:
147                amount += GATEWAY_AMT
148        elif category == 'clearance':
149            try:
150                p_item = student['studycourse'].certificate.code
151            except (AttributeError, TypeError):
152                return _('Study course data are incomplete.'), None
153            if student.entry_mode in ('nce_we_pt', 'nce_pt'):
154                amount = academic_session.clearance_fee_3
155            elif student.entry_mode in ('ug_ft', 'de_ft'):
156                amount = academic_session.clearance_fee_2
157            else:
158                amount = academic_session.clearance_fee_1
159            if local_nonlocal(student) == 'non-local'  \
160                and student.entry_mode not in ('nce_we_pt', 'nce_pt'):
161                amount += 5000.0
162        elif category == 'bed_allocation':
163            p_item = self.getAccommodationDetails(student)['bt']
164            amount = academic_session.booking_fee
165        elif category == 'hostel_maintenance':
166            amount = 0.0
167            bedticket = student['accommodation'].get(
168                str(student.current_session), None)
169            if bedticket is not None and bedticket.bed is not None:
170                p_item = bedticket.bed_coordinates
171                if bedticket.bed.__parent__.maint_fee > 0:
172                    amount = bedticket.bed.__parent__.maint_fee
173                else:
174                    # fallback
175                    amount = academic_session.maint_fee
176            else:
177                return _(u'No bed allocated.'), None
178        elif category == 'transcript':
179            amount = academic_session.transcript_fee
180        elif category == 'transfer':
181            amount = academic_session.transfer_fee
182        elif category == 'late_registration':
183            amount = academic_session.late_registration_fee
184        if amount in (0.0, None):
185            return _('Amount could not be determined.'), None
186        if self.samePaymentMade(student, category, p_item, p_session):
187            return _('This type of payment has already been made.'), None
188        if self._isPaymentDisabled(p_session, category, student):
189            return _('This category of payments has been disabled.'), None
190        payment = createObject(u'waeup.StudentOnlinePayment')
191        timestamp = ("%d" % int(time()*10000))[1:]
192        payment.p_id = "p%s" % timestamp
193        payment.p_category = category
194        payment.p_item = p_item
195        payment.p_session = p_session
196        payment.p_level = p_level
197        payment.p_current = p_current
198        payment.amount_auth = amount
199        return None, payment
200
201    # prefix
202    STUDENT_ID_PREFIX = u'R'
203
204    PORTRAIT_CHANGE_STATES = ()
Note: See TracBrowser for help on using the repository browser.