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
RevLine 
[7419]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##
[7151]18import grok
[9190]19import random
[8599]20from time import time
[9950]21from zope.component import createObject, getUtility
[8475]22from waeup.kofa.interfaces import CLEARED, RETURNING, PAID
[8834]23from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
[8247]24from waeup.kofa.accesscodes import create_accesscode
[9143]25from waeup.kofa.interfaces import CLEARED, RETURNING
[8460]26from waeup.fceokene.interfaces import MessageFactory as _
[9950]27from waeup.kofa.browser.interfaces import IPDFCreator
[9982]28from waeup.kofa.students.utils import trans
[10388]29from waeup.fceokene.interswitch.browser import GATEWAY_AMT
[6902]30
[8834]31class CustomStudentsUtils(NigeriaStudentsUtils):
[7151]32    """A collection of customized methods.
33
34    """
35
[10661]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
[9190]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
[8270]73    def getReturningData(self, student):
74        """ This method defines what happens after school fee payment
[8319]75        of returning students depending on the student's senate verdict.
[8270]76        """
[8319]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
[9923]82        elif cur_verdict in ('C','O'):
[8319]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
[9923]89        if cur_verdict == 'O':
90            new_session = student['studycourse'].current_session
91        else:
92            new_session = student['studycourse'].current_session + 1
[8270]93        return new_session, new_level
94
[9153]95    def setPaymentDetails(self, category, student,
96            previous_session=None, previous_level=None):
[8599]97        """Create Payment object and set the payment data of a student for
98        the payment category specified.
99
100        """
[8306]101        details = {}
[8599]102        p_item = u''
103        amount = 0.0
104        error = u''
[9153]105        if previous_session:
106            return _('Previous session payment not yet implemented.'), None
[8599]107        p_session = student['studycourse'].current_session
108        p_level = student['studycourse'].current_level
[9153]109        p_current = True
[9525]110        academic_session = self._getSessionConfiguration(p_session)
111        if academic_session == None:
[8599]112            return _(u'Session configuration object is not available.'), None
[9525]113        # Determine fee.
[7151]114        if category == 'transfer':
[8599]115            amount = academic_session.transfer_fee
[7151]116        elif category == 'gown':
[8599]117            amount = academic_session.gown_fee
[7151]118        elif category == 'bed_allocation':
[8599]119            amount = academic_session.booking_fee
[7151]120        elif category == 'hostel_maintenance':
[9611]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
[9612]130            if student.current_mode.endswith('_sw') or student.current_mode == 'pd_ft':
[10520]131                amount = 2500.0 #removed interswitch fee
[9612]132            else:
[10520]133                amount = 4000.0 #removed interswitch fee
[7151]134        elif category == 'clearance':
[9143]135            amount = academic_session.clearance_fee
[8599]136            try:
137                p_item = student['studycourse'].certificate.code
138            except (AttributeError, TypeError):
139                return _('Study course data are incomplete.'), None
[11913]140        elif category == 'third_semester' and student.current_mode == 'nce_ft':
141            amount = academic_session.third_semester_fee
[7151]142        elif category == 'schoolfee':
[8599]143            try:
144                certificate = student['studycourse'].certificate
145                p_item = certificate.code
146            except (AttributeError, TypeError):
147                return _('Study course data are incomplete.'), None
[9143]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
[10012]158            if student.state not in (CLEARED, RETURNING):
159                return _('Wrong state.'), None
160
[10661]161            # PDE repeater
162            if student.current_verdict == 'OPDE':
[11850]163                amount = 23000
[10660]164            # PDE
165            elif student.current_mode == 'pd_ft':
[11850]166                amount = 35300
[10012]167            # UG
168            elif student.current_mode == 'ug_ft':
[10876]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
[10012]175            # NCE
[9143]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:
[10663]180                        amount = 15500
[9143]181                    else:
[10663]182                        amount = 16000
[10012]183                # NCE I fresh
[9143]184                elif student.current_level == 100 and student.state == CLEARED:
185                    if student.depcode in ARTS:
[10663]186                        amount = 12620
[9143]187                    else:
[10665]188                        amount = 13095
[10012]189                # NCE II
[9143]190                elif student.current_level in (100, 110, 120) and \
191                    student.state == RETURNING:
192                    if student.depcode in ARTS:
[10829]193                        amount = 12100
[9143]194                    else:
[10829]195                        amount = 12575
[10012]196                # NCE III
[9143]197                elif student.current_level in (200, 210, 220):
198                    if student.depcode in ARTS:
[10829]199                        amount = 12100
[9143]200                    else:
[10829]201                        amount = 12575
[10012]202                # NCE III repeater
[9143]203                elif student.current_level in (300, 310, 320) and \
204                    student.current_verdict == 'O':
205                    if student.depcode in ARTS:
[10829]206                        amount = 10200
[9143]207                    else:
[10829]208                        amount = 10675
[10012]209                # NCE III spillover
[9143]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
[10012]216                # NCE III second spillover
[9143]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:
[11850]226                        amount = 22500
[9143]227                    else:
[11850]228                        amount = 23000
[10012]229                # NCE II sw
[9143]230                elif student.current_level in (100, 110, 120) and \
231                    student.state == RETURNING:
232                    if student.depcode in ARTS:
[11850]233                        amount = 19000
[9143]234                    else:
[11882]235                        amount = 19500
[10012]236                # NCE III sw
[9143]237                elif student.current_level in (200, 210, 220):
238                    if student.depcode in ARTS:
[11850]239                        amount = 21000
[9143]240                    else:
[11850]241                        amount = 21000
[10012]242                # NCE IV sw
[9143]243                elif student.current_level in (300, 310, 320):
244                    if student.depcode in ARTS:
[11850]245                        amount = 19000
[9143]246                    else:
[11850]247                        amount = 19500
[10012]248                # NCE V sw
[9143]249                elif student.current_level in (400, 410, 420):
250                    if student.depcode in ARTS:
[11850]251                        amount = 19000
[9143]252                    else:
[11850]253                        amount = 19500
[10012]254                # NCE V spillover sw
[9143]255                elif student.current_level in (500, 510, 520) and \
256                    student.current_verdict == 'B':
257                    if student.depcode in ARTS:
[11850]258                        amount = 17500
[9143]259                    else:
[11850]260                        amount = 18000
[10012]261                # NCE V second spillover sw
[9143]262                elif student.current_level in (600, 610, 620) and \
263                    student.current_verdict == 'B':
264                    if student.depcode in ARTS:
[11850]265                        amount = 17500
[9143]266                    else:
[11850]267                        amount = 18000
[10009]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'):
[10010]272                return _(u'School fee payment is disabled.'), None
[9297]273            if student.state == RETURNING:
[9525]274                # Override p_session and p_level
[9297]275                p_session, p_level = self.getReturningData(student)
[9525]276                academic_session = self._getSessionConfiguration(p_session)
277                if academic_session == None:
278                    return _(u'Session configuration object is not available.'), None
[9143]279
[8599]280        if amount in (0.0, None):
281            return _(u'Amount could not be determined.'), None
[11649]282        if self.samePaymentMade(student, category, p_item, p_session):
283            return _('This type of payment has already been made.'), None
[11457]284        if self._isPaymentDisabled(p_session, category, student):
285            return _('Payment temporarily disabled.'), None
[8713]286        payment = createObject(u'waeup.StudentOnlinePayment')
[8953]287        timestamp = ("%d" % int(time()*10000))[1:]
[8599]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
[9153]293        payment.p_current = p_current
[10388]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
[8599]297        return None, payment
[7621]298
[9207]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
[9903]333    def maxCredits(self, studylevel):
334        """Return maximum credits.
335
336        """
337        return 58
338
[9950]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
[9982]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
[9989]366    def getBedCoordinates(self, bedticket):
367        """Return bed coordinates.
368
369        Bed coordinates are invisible in FCEOkene.
370        """
371        return _('(see payment slip)')
372
[10019]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
[10023]384    SKIP_UPLOAD_VIEWLETS = (
385        'higherqualificationresultupload',
386        'secondHigherqualificationresultupload',
387        'certificateupload',
388        'secondcertificateupload',
389        'thirdcertificateupload',
390        'resultstatementupload',
391        'secondrefereeletterupload',
392        'thirdrefereeletterupload',)
393
[8460]394    # FCEOkene prefix
[10520]395    STUDENT_ID_PREFIX = u'K'
Note: See TracBrowser for help on using the repository browser.