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

Last change on this file since 16478 was 16478, checked in by Henrik Bettermann, 4 years ago

Use p_session not current_session.

  • Property svn:keywords set to Id
File size: 9.5 KB
Line 
1## $Id: utils.py 16478 2021-05-08 16:11:45Z 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, 43200.0, 43200.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       (75700.0, 75700.0, 64700.0, 64700.0, 68700.0, 68700.0, 62700.0, 62700.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, 55700.0, 55700.0, 49700.0, 49700.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       (85700.0, 85700.0, 74700.0, 74700.0, 78700.0, 78700.0, 72700.0, 72700.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 _lsfp_penalty_paymentMade(self, student, session):
93        if student.current_mode not in ('ug_ft','de_ft', 'nce_ft', 'nce_pt'):
94            return True
95        if len(student['payments']):
96            for ticket in student['payments'].values():
97                if ticket.p_state == 'paid' and \
98                    ticket.p_category == 'lsfp_penalty' and \
99                    ticket.p_session == session:
100                    return True
101        return False
102
103    def setPaymentDetails(self, category, student,
104            previous_session=None, previous_level=None, combi=[]):
105        """Create a payment ticket and set the payment data of a
106        student for the payment category specified.
107        """
108        p_item = u''
109        amount = 0.0
110        if previous_session:
111            if previous_session < student['studycourse'].entry_session:
112                return _('The previous session must not fall below '
113                         'your entry session.'), None
114            if category == 'schoolfee':
115                # School fee is always paid for the following session
116                if previous_session > student['studycourse'].current_session:
117                    return _('This is not a previous session.'), None
118            else:
119                if previous_session > student['studycourse'].current_session - 1:
120                    return _('This is not a previous session.'), None
121            p_session = previous_session
122            p_level = previous_level
123            p_current = False
124        else:
125            p_session = student['studycourse'].current_session
126            p_level = student['studycourse'].current_level
127            p_current = True
128        academic_session = self._getSessionConfiguration(p_session)
129        if academic_session == None:
130            return _(u'Session configuration object is not available.'), None
131        # Determine fee.
132        if category.startswith('schoolfee'):
133            try:
134                certificate = student['studycourse'].certificate
135                p_item = certificate.code
136            except (AttributeError, TypeError):
137                return _('Study course data are incomplete.'), None
138            if student.state == RETURNING:
139                # Override p_session and p_level
140                p_session, p_level = self.getReturningData(student)
141                academic_session = self._getSessionConfiguration(p_session)
142                if academic_session == None:
143                    return _(u'Session configuration object '
144                              'is not available.'), None
145            penalty = getattr(academic_session, 'lsfp_penalty_fee')
146            if p_session < 2020 and penalty and \
147                not self._lsfp_penalty_paymentMade(
148                student, student.current_session):
149                return _('You have to pay late school fee payment penalty first.'), None
150            if p_level in PAYMENT_LEVELS:
151                amount = SCHOOL_FEES.get_fee(
152                    (
153                     local_nonlocal(student),
154                     student.current_mode,
155                     p_level)
156                    )
157                if student.entry_mode == 'de_ft' and p_level == 200:
158                    if student['studycourse'].entry_session >= 2020:
159                        amount += 15000
160                    elif student['studycourse'].entry_session >= 2019:
161                        amount += 10500
162            if amount and category in ('schoolfee_1', 'schoolfee_2'):
163                amount /= 2
164            if amount:
165                amount += GATEWAY_AMT
166        elif category == 'clearance':
167            try:
168                p_item = student['studycourse'].certificate.code
169            except (AttributeError, TypeError):
170                return _('Study course data are incomplete.'), None
171            if student.entry_mode in ('nce_we_pt', 'nce_pt'):
172                amount = academic_session.clearance_fee_3
173            elif student.entry_mode in ('ug_ft', 'de_ft'):
174                amount = academic_session.clearance_fee_2
175            else:
176                amount = academic_session.clearance_fee_1
177            if local_nonlocal(student) == 'non-local'  \
178                and student.entry_mode not in ('nce_we_pt', 'nce_pt'):
179                amount += 5000.0
180        elif category == 'bed_allocation':
181            p_item = self.getAccommodationDetails(student)['bt']
182            amount = academic_session.booking_fee
183        elif category == 'hostel_maintenance':
184            amount = 0.0
185            bedticket = student['accommodation'].get(
186                str(student.current_session), None)
187            if bedticket is not None and bedticket.bed is not None:
188                p_item = bedticket.bed_coordinates
189                if bedticket.bed.__parent__.maint_fee > 0:
190                    amount = bedticket.bed.__parent__.maint_fee
191                else:
192                    # fallback
193                    amount = academic_session.maint_fee
194            else:
195                return _(u'No bed allocated.'), None
196        else:
197            fee_name = category + '_fee'
198            amount = getattr(academic_session, fee_name, 0.0)
199        if amount in (0.0, None):
200            return _('Amount could not be determined.'), None
201        if self.samePaymentMade(student, category, p_item, p_session):
202            return _('This type of payment has already been made.'), None
203        if self._isPaymentDisabled(p_session, category, student):
204            return _('This category of payments has been disabled.'), None
205        payment = createObject(u'waeup.StudentOnlinePayment')
206        timestamp = ("%d" % int(time()*10000))[1:]
207        payment.p_id = "p%s" % timestamp
208        payment.p_category = category
209        payment.p_item = p_item
210        payment.p_session = p_session
211        payment.p_level = p_level
212        payment.p_current = p_current
213        payment.amount_auth = amount
214        return None, payment
215
216    # prefix
217    STUDENT_ID_PREFIX = u'R'
218
219    PORTRAIT_CHANGE_STATES = ()
Note: See TracBrowser for help on using the repository browser.