source: main/waeup.fceokene/trunk/src/waeup/fceokene/students/utils.py @ 11915

Last change on this file since 11915 was 11913, checked in by Henrik Bettermann, 10 years ago

Add payment category 'NCE Third Semester Fee' which can be set in session configuration objects. Remove unused payment categories.

  • Property svn:keywords set to Id
File size: 16.0 KB
Line 
1## $Id: utils.py 11913 2014-10-29 21:23:53Z 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##
18import grok
19import random
20from time import time
21from zope.component import createObject, getUtility
22from waeup.kofa.interfaces import CLEARED, RETURNING, PAID
23from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
24from waeup.kofa.accesscodes import create_accesscode
25from waeup.kofa.interfaces import CLEARED, RETURNING
26from waeup.fceokene.interfaces import MessageFactory as _
27from waeup.kofa.browser.interfaces import IPDFCreator
28from waeup.kofa.students.utils import trans
29from waeup.fceokene.interswitch.browser import GATEWAY_AMT
30
31class CustomStudentsUtils(NigeriaStudentsUtils):
32    """A collection of customized methods.
33
34    """
35
36    VERDICTS_DICT = {
37        '0': 'not yet',
38        'A': 'Successful student',
39        'B': 'Student with carryover courses',
40        'C': 'Student on probation',
41        'D': 'Withdrawn from the faculty',
42        #'E': 'Student who were previously on probation',
43        #'F': 'Medical case',
44        'G': 'Absent from examination',
45        #'H': 'Withheld results',
46        'I': 'Expelled/rusticated/suspended student',
47        'J': 'Temporary withdrawn from the university',
48        #'K': 'Unregistered student',
49        'L': 'Referred student',
50        'M': 'Reinstatement',
51        #'N': 'Student on transfer',
52        'O': 'NCE-III repeater',
53        #'Y': 'No previous verdict',
54        #'X': 'New 300 level student (Uniben)',
55        #'Z': 'Successful student (provisional)',
56        'A1': 'First Class',
57        'A2': 'Second Class Upper',
58        'A3': 'Second Class Lower',
59        'A4': 'Third Class',
60        'A5': 'Pass',
61        'A6': 'Distinction',
62        'A7': 'Credit',
63        'A8': 'Merit',
64        'OPDE': 'PDE repeater',
65        }
66
67    def selectBed(self, available_beds):
68        """Randomly select a bed from a list of available beds.
69
70        """
71        return random.choice(available_beds)
72
73    def getReturningData(self, student):
74        """ This method defines what happens after school fee payment
75        of returning students depending on the student's senate verdict.
76        """
77        prev_level = student['studycourse'].current_level
78        cur_verdict = student['studycourse'].current_verdict
79        if cur_verdict in ('A','B','L','M','N','Z',):
80            # Successful student
81            new_level = divmod(int(prev_level),100)[0]*100 + 100
82        elif cur_verdict in ('C','O'):
83            # Student on probation
84            new_level = int(prev_level) + 10
85        else:
86            # Student is somehow in an undefined state.
87            # Level has to be set manually.
88            new_level = prev_level
89        if cur_verdict == 'O':
90            new_session = student['studycourse'].current_session
91        else:
92            new_session = student['studycourse'].current_session + 1
93        return new_session, new_level
94
95    def setPaymentDetails(self, category, student,
96            previous_session=None, previous_level=None):
97        """Create Payment object and set the payment data of a student for
98        the payment category specified.
99
100        """
101        details = {}
102        p_item = u''
103        amount = 0.0
104        error = u''
105        if previous_session:
106            return _('Previous session payment not yet implemented.'), None
107        p_session = student['studycourse'].current_session
108        p_level = student['studycourse'].current_level
109        p_current = True
110        academic_session = self._getSessionConfiguration(p_session)
111        if academic_session == None:
112            return _(u'Session configuration object is not available.'), None
113        # Determine fee.
114        if category == 'transfer':
115            amount = academic_session.transfer_fee
116        elif category == 'gown':
117            amount = academic_session.gown_fee
118        elif category == 'bed_allocation':
119            amount = academic_session.booking_fee
120        elif category == 'hostel_maintenance':
121            current_session = student['studycourse'].current_session
122            bedticket = student['accommodation'].get(str(current_session), None)
123            if bedticket is not None and bedticket.bed is not None:
124                p_item = bedticket.bed_coordinates
125            else:
126                return _(u'You have not yet booked accommodation.'), None
127            acc_details = self.getAccommodationDetails(student)
128            if current_session != acc_details['booking_session']:
129                return _(u'Current session does not match accommodation session.'), None
130            if student.current_mode.endswith('_sw') or student.current_mode == 'pd_ft':
131                amount = 2500.0 #removed interswitch fee
132            else:
133                amount = 4000.0 #removed interswitch fee
134        elif category == 'clearance':
135            amount = academic_session.clearance_fee
136            try:
137                p_item = student['studycourse'].certificate.code
138            except (AttributeError, TypeError):
139                return _('Study course data are incomplete.'), None
140        elif category == 'third_semester' and student.current_mode == 'nce_ft':
141            amount = academic_session.third_semester_fee
142        elif category == 'schoolfee':
143            try:
144                certificate = student['studycourse'].certificate
145                p_item = certificate.code
146            except (AttributeError, TypeError):
147                return _('Study course data are incomplete.'), None
148
149            # Very special school fee configuration, should be moved to
150            # a seperate file.
151
152            ARTS = ('CRS','ISS','HIS','MUS','ECO','GEO','POL','SOS','CCA','ECU',
153                    'THA','GED','GSE','PES','SPC','ENG','FRE','ARB','HAU','IGB',
154                    'YOR','NCRS','NISS','NHIS','NMUS','NECO','NGEO','NPOL',
155                    'NCCA','NECU','NTHA','NGED','NGSE','NPES','NSPC','NENG',
156                    'NFRE','NARB','NHAU','NIGB','NYOR','NSOS')
157
158            if student.state not in (CLEARED, RETURNING):
159                return _('Wrong state.'), None
160
161            # PDE repeater
162            if student.current_verdict == 'OPDE':
163                amount = 23000
164            # PDE
165            elif student.current_mode == 'pd_ft':
166                amount = 35300
167            # UG
168            elif student.current_mode == 'ug_ft':
169            # Introducing returning students fee for 'ug_ft' for 1st time
170            # on 07/01/2014
171                if student.state == CLEARED:
172                    amount = 65650
173                else:
174                    amount = 56150
175            # NCE
176            elif not student.current_mode.endswith('_sw'):
177                # PRENCE
178                if student.current_level == 10 and student.state == CLEARED:
179                    if student.depcode in ARTS:
180                        amount = 15500
181                    else:
182                        amount = 16000
183                # NCE I fresh
184                elif student.current_level == 100 and student.state == CLEARED:
185                    if student.depcode in ARTS:
186                        amount = 12620
187                    else:
188                        amount = 13095
189                # NCE II
190                elif student.current_level in (100, 110, 120) and \
191                    student.state == RETURNING:
192                    if student.depcode in ARTS:
193                        amount = 12100
194                    else:
195                        amount = 12575
196                # NCE III
197                elif student.current_level in (200, 210, 220):
198                    if student.depcode in ARTS:
199                        amount = 12100
200                    else:
201                        amount = 12575
202                # NCE III repeater
203                elif student.current_level in (300, 310, 320) and \
204                    student.current_verdict == 'O':
205                    if student.depcode in ARTS:
206                        amount = 10200
207                    else:
208                        amount = 10675
209                # NCE III spillover
210                elif student.current_level in (300, 310, 320) and \
211                    student.current_verdict == 'B':
212                    if student.depcode in ARTS:
213                        amount = 9170
214                    else:
215                        amount = 9645
216                # NCE III second spillover
217                elif student.current_level in (400, 410, 420) and \
218                    student.current_verdict == 'B':
219                    if student.depcode in ARTS:
220                        amount = 9170
221                    else:
222                        amount = 9645
223            else:
224                if student.current_level == 100 and student.state == CLEARED:
225                    if student.depcode in ARTS:
226                        amount = 22500
227                    else:
228                        amount = 23000
229                # NCE II sw
230                elif student.current_level in (100, 110, 120) and \
231                    student.state == RETURNING:
232                    if student.depcode in ARTS:
233                        amount = 19000
234                    else:
235                        amount = 19500
236                # NCE III sw
237                elif student.current_level in (200, 210, 220):
238                    if student.depcode in ARTS:
239                        amount = 21000
240                    else:
241                        amount = 21000
242                # NCE IV sw
243                elif student.current_level in (300, 310, 320):
244                    if student.depcode in ARTS:
245                        amount = 19000
246                    else:
247                        amount = 19500
248                # NCE V sw
249                elif student.current_level in (400, 410, 420):
250                    if student.depcode in ARTS:
251                        amount = 19000
252                    else:
253                        amount = 19500
254                # NCE V spillover sw
255                elif student.current_level in (500, 510, 520) and \
256                    student.current_verdict == 'B':
257                    if student.depcode in ARTS:
258                        amount = 17500
259                    else:
260                        amount = 18000
261                # NCE V second spillover sw
262                elif student.current_level in (600, 610, 620) and \
263                    student.current_verdict == 'B':
264                    if student.depcode in ARTS:
265                        amount = 17500
266                    else:
267                        amount = 18000
268            # NCE student payment can be disabled by
269            # setting the base school fee to -1
270            if academic_session.school_fee_base == -1 and \
271                student.current_mode.startswith('nce'):
272                return _(u'School fee payment is disabled.'), None
273            if student.state == RETURNING:
274                # Override p_session and p_level
275                p_session, p_level = self.getReturningData(student)
276                academic_session = self._getSessionConfiguration(p_session)
277                if academic_session == None:
278                    return _(u'Session configuration object is not available.'), None
279
280        if amount in (0.0, None):
281            return _(u'Amount could not be determined.'), None
282        if self.samePaymentMade(student, category, p_item, p_session):
283            return _('This type of payment has already been made.'), None
284        if self._isPaymentDisabled(p_session, category, student):
285            return _('Payment temporarily disabled.'), None
286        payment = createObject(u'waeup.StudentOnlinePayment')
287        timestamp = ("%d" % int(time()*10000))[1:]
288        payment.p_id = "p%s" % timestamp
289        payment.p_category = category
290        payment.p_item = p_item
291        payment.p_session = p_session
292        payment.p_level = p_level
293        payment.p_current = p_current
294        # On June 26, 2013 FCEOkene realized that the Interswitch fee
295        # is deducted from their amount. Therefore, we add this fee here.
296        payment.amount_auth = float(amount) + GATEWAY_AMT
297        return None, payment
298
299    def getAccommodationDetails(self, student):
300        """Determine the accommodation data of a student.
301        """
302        d = {}
303        d['error'] = u''
304        hostels = grok.getSite()['hostels']
305        d['booking_session'] = hostels.accommodation_session
306        d['allowed_states'] = hostels.accommodation_states
307        d['startdate'] = hostels.startdate
308        d['enddate'] = hostels.enddate
309        d['expired'] = hostels.expired
310        # Determine bed type
311        studycourse = student['studycourse']
312        certificate = getattr(studycourse,'certificate',None)
313        current_level = studycourse.current_level
314        if None in (current_level, certificate):
315            return d
316        end_level = certificate.end_level
317        if current_level == 10:
318            bt = 'pr'
319        elif current_level == 100:
320            bt = 'fr'
321        elif current_level >= 300:
322            bt = 'fi'
323        else:
324            bt = 're'
325        if student.sex == 'f':
326            sex = 'female'
327        else:
328            sex = 'male'
329        special_handling = 'regular'
330        d['bt'] = u'%s_%s_%s' % (special_handling,sex,bt)
331        return d
332
333    def maxCredits(self, studylevel):
334        """Return maximum credits.
335
336        """
337        return 58
338
339    def getPDFCreator(self, context):
340        """Get a pdf creator suitable for `context`.
341
342        The default implementation always returns the default creator.
343        """
344        mode = getattr(context, 'current_mode', None)
345        if mode and mode.startswith('ug'):
346            return getUtility(IPDFCreator, name='ibadan_pdfcreator')
347        return getUtility(IPDFCreator)
348
349    def _admissionText(self, student, portal_language):
350        mode = getattr(student, 'current_mode', None)
351        if mode and mode.startswith('ug'):
352            text = trans(_(
353                'With reference to your application for admission into Bachelor Degree '
354                'Programme of the University of Ibadan, this is to inform you that you have '
355                'been provisionally admitted to pursue a full-time Bachelor of Arts in '
356                'Education Degree Programme as follows:'),
357                portal_language)
358        else:
359            inst_name = grok.getSite()['configuration'].name
360            text = trans(_(
361                'This is to inform you that you have been provisionally'
362                ' admitted into ${a} as follows:', mapping = {'a': inst_name}),
363                portal_language)
364        return text
365
366    def getBedCoordinates(self, bedticket):
367        """Return bed coordinates.
368
369        Bed coordinates are invisible in FCEOkene.
370        """
371        return _('(see payment slip)')
372
373    SEPARATORS_DICT = {
374        'form.fst_sit_fname': _(u'First Sitting Record'),
375        'form.scd_sit_fname': _(u'Second Sitting Record'),
376        #'form.alr_fname': _(u'Advanced Level Record'),
377        'form.hq_type': _(u'Advanced Level Record'),
378        'form.hq2_type': _(u'Second Higher Education Record'),
379        'form.nysc_year': _(u'NYSC Information'),
380        'form.employer': _(u'Employment History'),
381        'form.former_matric': _(u'Former Student'),
382        }
383
384    SKIP_UPLOAD_VIEWLETS = (
385        'higherqualificationresultupload',
386        'secondHigherqualificationresultupload',
387        'certificateupload',
388        'secondcertificateupload',
389        'thirdcertificateupload',
390        'resultstatementupload',
391        'secondrefereeletterupload',
392        'thirdrefereeletterupload',)
393
394    # FCEOkene prefix
395    STUDENT_ID_PREFIX = u'K'
Note: See TracBrowser for help on using the repository browser.