source: main/kofacustom.iuokada/trunk/src/kofacustom/iuokada/students/utils.py @ 15883

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

Also cleared students may get a matric number.

  • Property svn:keywords set to Id
File size: 9.2 KB
Line 
1## $Id: utils.py 15810 2019-11-15 07:31:06Z 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, getUtility
21from waeup.kofa.interfaces import (IKofaUtils,
22    ADMITTED, CLEARANCE, CLEARED, RETURNING, PAID, REGISTERED, VALIDATED)
23from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
24from kofacustom.iuokada.interfaces import MessageFactory as _
25
26class CustomStudentsUtils(NigeriaStudentsUtils):
27    """A collection of customized methods.
28
29    """
30
31    # refix
32    STUDENT_ID_PREFIX = u'I'
33
34    SKIP_UPLOAD_VIEWLETS = (
35        'acceptanceletterupload', 'certificateupload'
36        )
37    # Maximum size of upload files in kB
38    MAX_KB = 500
39
40    #: A tuple containing the names of registration states in which changing of
41    #: passport pictures is allowed.
42    PORTRAIT_CHANGE_STATES = (ADMITTED, CLEARANCE,)
43
44    def warnCreditsOOR(self, studylevel, course=None):
45        """Return message if credits are out of range. In the base
46        package only maximum credits is set.
47        """
48        if course and studylevel.total_credits + course.credits > 60:
49            return _('Maximum credits exceeded.')
50        elif studylevel.total_credits > 60:
51            return _('Maximum credits exceeded.')
52        return
53
54    def setPaymentDetails(self, category, student,
55            previous_session, previous_level, combi=[]):
56        """Create a payment ticket and set the payment data of a
57        student for the payment category specified.
58        """
59        p_item = u''
60        amount = 0.0
61        if previous_session:
62            if previous_session < student['studycourse'].entry_session:
63                return _('The previous session must not fall below '
64                         'your entry session.'), None
65            if category == 'schoolfee':
66                # School fee is always paid for the following session
67                if previous_session > student['studycourse'].current_session:
68                    return _('This is not a previous session.'), None
69            else:
70                if previous_session > student['studycourse'].current_session - 1:
71                    return _('This is not a previous session.'), None
72            p_session = previous_session
73            p_level = previous_level
74            p_current = False
75        else:
76            p_session = student['studycourse'].current_session
77            p_level = student['studycourse'].current_level
78            p_current = True
79        academic_session = self._getSessionConfiguration(p_session)
80        if academic_session == None:
81            return _(u'Session configuration object is not available.'), None
82        # Determine fee.
83        if category in ('schoolfee', 'schoolfee40',
84                        'secondinstal'):
85            try:
86                certificate = student['studycourse'].certificate
87                p_item = certificate.code
88            except (AttributeError, TypeError):
89                return _('Study course data are incomplete.'), None
90            if previous_session:
91                # Students can pay for previous sessions in all
92                # workflow states.  Fresh students are excluded by the
93                # update method of the PreviousPaymentAddFormPage.
94                if previous_level == 100:
95                    amount = getattr(certificate, 'school_fee_1', 0.0)
96                else:
97                    amount = getattr(certificate, 'school_fee_2', 0.0)
98                if category == 'schoolfee40':
99                    amount = 0.4*amount
100                elif category == 'secondinstal':
101                    amount = 0.6*amount
102            else:
103                if category == 'secondinstal':
104                    if student.is_fresh:
105                        amount = 0.6 * getattr(certificate, 'school_fee_1', 0.0)
106                    else:
107                        amount = 0.6 * getattr(certificate, 'school_fee_2', 0.0)
108                else:
109                    if student.state == CLEARED:
110                        amount = getattr(certificate, 'school_fee_1', 0.0)
111                    elif student.state == RETURNING:
112                        # In case of returning school fee payment the
113                        # payment session and level contain the values of
114                        # the session the student has paid for. Payment
115                        # session is always next session.
116                        p_session, p_level = self.getReturningData(student)
117                        academic_session = self._getSessionConfiguration(p_session)
118                        if academic_session == None:
119                            return _(
120                                u'Session configuration object is not available.'
121                                ), None
122                        amount = getattr(certificate, 'school_fee_2', 0.0)
123                    elif student.is_postgrad and student.state == PAID:
124                        # Returning postgraduate students also pay for the
125                        # next session but their level always remains the
126                        # same.
127                        p_session += 1
128                        academic_session = self._getSessionConfiguration(p_session)
129                        if academic_session == None:
130                            return _(
131                                u'Session configuration object is not available.'
132                                ), None
133                        amount = getattr(certificate, 'school_fee_2', 0.0)
134                    if amount and category == 'schoolfee40':
135                        amount = 0.4*amount
136        elif category == 'clearance':
137            try:
138                p_item = student['studycourse'].certificate.code
139            except (AttributeError, TypeError):
140                return _('Study course data are incomplete.'), None
141            amount = academic_session.clearance_fee
142        #elif category == 'bed_allocation':
143        #    p_item = self.getAccommodationDetails(student)['bt']
144        #    amount = academic_session.booking_fee
145        #elif category == 'hostel_maintenance':
146        #    amount = 0.0
147        #    bedticket = student['accommodation'].get(
148        #        str(student.current_session), None)
149        #    if bedticket is not None and bedticket.bed is not None:
150        #        p_item = bedticket.bed_coordinates
151        #        if bedticket.bed.__parent__.maint_fee > 0:
152        #            amount = bedticket.bed.__parent__.maint_fee
153        #        else:
154        #            # fallback
155        #            amount = academic_session.maint_fee
156        #    else:
157        #        return _(u'No bed allocated.'), None
158        elif category == 'combi' and combi:
159            categories = getUtility(IKofaUtils).COMBI_PAYMENT_CATEGORIES
160            for cat in combi:
161                fee_name = cat + '_fee'
162                cat_amount = getattr(academic_session, fee_name, 0.0)
163                if not cat_amount:
164                    return _('%s undefined.' % categories[cat]), None
165                amount += cat_amount
166                p_item += u'%s + ' % categories[cat]
167            p_item = p_item.strip(' + ')
168        else:
169            fee_name = category + '_fee'
170            amount = getattr(academic_session, fee_name, 0.0)
171        if amount in (0.0, None):
172            return _('Amount could not be determined.'), None
173        if self.samePaymentMade(student, category, p_item, p_session):
174            return _('This type of payment has already been made.'), None
175        if self._isPaymentDisabled(p_session, category, student):
176            return _('This category of payments has been disabled.'), None
177        payment = createObject(u'waeup.StudentOnlinePayment')
178        timestamp = ("%d" % int(time()*10000))[1:]
179        payment.p_id = "p%s" % timestamp
180        payment.p_category = category
181        payment.p_item = p_item
182        payment.p_session = p_session
183        payment.p_level = p_level
184        payment.p_current = p_current
185        payment.amount_auth = amount
186        payment.p_combi = combi
187        return None, payment
188
189    def constructMatricNumber(self, student):
190        """Fetch the matric number counter which fits the student and
191        construct the new matric number of the student.
192        """
193        next_integer = grok.getSite()['configuration'].next_matric_integer
194        if next_integer == 0:
195            return _('Matriculation number cannot be set.'), None
196        if not student.state in (
197            RETURNING, CLEARED, PAID, REGISTERED, VALIDATED):
198            return _('Matriculation number cannot be set.'), None
199        year = unicode(student.entry_session)[2:]
200        return None, "%s/%06d" % (year, next_integer)
Note: See TracBrowser for help on using the repository browser.