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

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

Fetch hostel maintenance fee from hostel object.

  • Property svn:keywords set to Id
File size: 11.9 KB
Line 
1## $Id: utils.py 13418 2015-11-09 11:53:23Z 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
19from time import time
20from zope.component import createObject
21from waeup.kofa.interfaces import (
22    ADMITTED, CLEARED, RETURNING, PAID, academic_sessions_vocab)
23from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
24from waeup.kofa.accesscodes import create_accesscode
25from waeup.kofa.students.utils import trans
26from waeup.aaue.interswitch.browser import gateway_net_amt
27from waeup.aaue.interfaces import MessageFactory as _
28
29class CustomStudentsUtils(NigeriaStudentsUtils):
30    """A collection of customized methods.
31
32    """
33
34    PORTRAIT_CHANGE_STATES = (ADMITTED, RETURNING)
35
36    gpa_boundaries = ((1, 'FRNS'),
37                      (1.5, 'Pass'),
38                      (2.4, '3rd Class Honours'),
39                      (3.5, '2nd Class Honours Lower Division'),
40                      (4.5, '2nd Class Honours Upper Division'),
41                      (5, '1st Class Honours'))
42
43    def increaseMatricInteger(self, student):
44        """Increase counter for matric numbers.
45        This counter can be a centrally stored attribute or an attribute of
46        faculties, departments or certificates. In the base package the counter
47        is as an attribute of the site configuration container.
48        """
49        if student.current_mode in ('ug_pt', 'de_pt'):
50            grok.getSite()['configuration'].next_matric_integer += 1
51            return
52        grok.getSite()['configuration'].next_matric_integer_2 += 1
53        return
54
55    def constructMatricNumber(self, student):
56        faccode = student.faccode
57        depcode = student.depcode
58        year = unicode(student.entry_session)[2:]
59        if not student.state in (PAID, ) or not student.is_fresh or \
60            student.current_mode == 'found':
61            return _('Matriculation number cannot be set.'), None
62        if student.current_mode in ('ug_pt', 'de_pt'):
63            next_integer = grok.getSite()['configuration'].next_matric_integer
64            if next_integer == 0:
65                return _('Matriculation number cannot be set.'), None
66            return None, "PTP/%s/%s/%s/%05d" % (
67                faccode, depcode, year, next_integer)
68        next_integer = grok.getSite()['configuration'].next_matric_integer_2
69        if next_integer == 0:
70            return _('Matriculation number cannot be set.'), None
71        if student.faccode in ('FBM', 'FCS'):
72            return None, "CMS/%s/%s/%s/%05d" % (
73                faccode, depcode, year, next_integer)
74        return None, "%s/%s/%s/%05d" % (faccode, depcode, year, next_integer)
75
76    def getReturningData(self, student):
77        """ This method defines what happens after school fee payment
78        of returning students depending on the student's senate verdict.
79        """
80        prev_level = student['studycourse'].current_level
81        cur_verdict = student['studycourse'].current_verdict
82        if cur_verdict in ('A','B','L','M','N','Z',):
83            # Successful student
84            new_level = divmod(int(prev_level),100)[0]*100 + 100
85        elif cur_verdict == 'C':
86            # Student on probation
87            new_level = int(prev_level) + 10
88        else:
89            # Student is somehow in an undefined state.
90            # Level has to be set manually.
91            new_level = prev_level
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 == 'transcript':
117            amount = academic_session.transcript_fee
118        elif category == 'bed_allocation':
119            amount = academic_session.booking_fee
120        elif category == 'hostel_maintenance':
121            amount = 0.0
122            bedticket = student['accommodation'].get(
123                str(student.current_session), None)
124            if bedticket:
125                p_item = bedticket.bed_coordinates
126                if bedticket.bed.__parent__.maint_fee > 0:
127                    amount = bedticket.bed.__parent__.maint_fee
128                else:
129                    # fallback
130                    amount = academic_session.maint_fee
131            else:
132                # Should not happen because this is already checked
133                # in the browser module, but anyway ...
134                portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
135                p_item = trans(_('no bed allocated'), portal_language)
136        elif category == 'welfare':
137            amount = academic_session.welfare_fee
138        elif category == 'union':
139            amount = academic_session.union_fee
140        elif category == 'lapel':
141            amount = academic_session.lapel_fee
142        elif category == 'matric_gown':
143            amount = academic_session.matric_gown_fee
144        elif category == 'concessional':
145            amount = academic_session.concession_fee
146        elif category.startswith('clearance'):
147            if student.faccode == 'FP':
148                amount = academic_session.clearance_fee_fp
149            elif student.current_mode.endswith('_pt'):
150                amount = academic_session.clearance_fee_pt
151            elif student.faccode in ('FBM', 'FCS'):
152                amount = academic_session.clearance_fee_med
153            else:
154                amount = academic_session.clearance_fee
155            p_item = student['studycourse'].certificate.code
156            # Add Matric Gown Fee and Lapel Fee
157            if category.endswith('_incl'):
158                if amount is None:
159                    # Otherwise we can't add somtehing
160                    amount = 0.0
161                amount += gateway_net_amt(academic_session.matric_gown_fee) + \
162                    gateway_net_amt(academic_session.lapel_fee)
163        elif category == 'late_registration':
164            amount = academic_session.late_registration_fee
165        elif category.startswith('schoolfee'):
166            try:
167                certificate = student['studycourse'].certificate
168                p_item = certificate.code
169            except (AttributeError, TypeError):
170                return _('Study course data are incomplete.'), None
171            if student.state == CLEARED:
172                if student.is_foreigner:
173                    amount = getattr(certificate, 'school_fee_3', 0.0)
174                else:
175                    amount = getattr(certificate, 'school_fee_1', 0.0)
176            elif student.state == RETURNING:
177                # In case of returning school fee payment the payment session
178                # and level contain the values of the session the student
179                # has paid for.
180                p_session, p_level = self.getReturningData(student)
181                try:
182                    academic_session = grok.getSite()[
183                        'configuration'][str(p_session)]
184                except KeyError:
185                    return _(u'Session configuration object is not available.'), None
186                if student.is_foreigner:
187                    amount = getattr(certificate, 'school_fee_4', 0.0)
188                else:
189                    amount = getattr(certificate, 'school_fee_2', 0.0)
190            else:
191                return _('Wrong state.'), None
192            if amount in (0.0, None):
193                return _(u'Amount could not be determined.'), None
194            # Add Student Union Fee and Welfare Assurance
195            if category == 'schoolfee_incl':
196                amount += gateway_net_amt(academic_session.welfare_fee) + \
197                    gateway_net_amt(academic_session.union_fee)
198        if amount in (0.0, None):
199            return _(u'Amount could not be determined.'), None
200        # Add session specific penalty fee.
201        if category.startswith('schoolfee') and student.is_postgrad:
202            amount += academic_session.penalty_pg
203        elif category.startswith('schoolfee'):
204            amount += academic_session.penalty_ug
205        # Create ticket.
206        for key in student['payments'].keys():
207            ticket = student['payments'][key]
208            if ticket.p_state == 'paid' and\
209               ticket.p_category == category and \
210               ticket.p_item == p_item and \
211               ticket.p_session == p_session:
212                  return _('This type of payment has already been made.'), None
213        if self._isPaymentDisabled(p_session, category, student):
214            return _('Payment temporarily disabled.'), None
215        payment = createObject(u'waeup.StudentOnlinePayment')
216        timestamp = ("%d" % int(time()*10000))[1:]
217        payment.p_id = "p%s" % timestamp
218        payment.p_category = category
219        payment.p_item = p_item
220        payment.p_session = p_session
221        payment.p_level = p_level
222        payment.p_current = p_current
223        payment.amount_auth = amount
224        return None, payment
225
226    def _admissionText(self, student, portal_language):
227        inst_name = grok.getSite()['configuration'].name
228        entry_session = student['studycourse'].entry_session
229        entry_session = academic_sessions_vocab.getTerm(entry_session).title
230        text = trans(_(
231            'This is to inform you that you have been offered provisional'
232            ' admission into ${a} for the ${b} academic session as follows:',
233            mapping = {'a': inst_name, 'b': entry_session}),
234            portal_language)
235        return text
236
237    def maxCredits(self, studylevel):
238        """Return maximum credits.
239
240        """
241        return 48
242
243    def getBedCoordinates(self, bedticket):
244        """Return descriptive bed coordinates.
245        This method can be used to customize the `display_coordinates`
246        property method in order to  display a
247        customary description of the bed space.
248        """
249        bc = bedticket.bed_coordinates.split(',')
250        if len(bc) == 4:
251            return bc[0]
252        return bedticket.bed_coordinates
253
254    def getAccommodationDetails(self, student):
255        """Determine the accommodation data of a student.
256        """
257        d = {}
258        d['error'] = u''
259        hostels = grok.getSite()['hostels']
260        d['booking_session'] = hostels.accommodation_session
261        d['allowed_states'] = hostels.accommodation_states
262        d['startdate'] = hostels.startdate
263        d['enddate'] = hostels.enddate
264        d['expired'] = hostels.expired
265        # Determine bed type
266        bt = 'all'
267        if student.sex == 'f':
268            sex = 'female'
269        else:
270            sex = 'male'
271        special_handling = 'regular'
272        d['bt'] = u'%s_%s_%s' % (special_handling,sex,bt)
273        return d
274
275    # AAUE prefix
276    STUDENT_ID_PREFIX = u'E'
Note: See TracBrowser for help on using the repository browser.