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

Last change on this file since 16935 was 16934, checked in by Henrik Bettermann, 3 years ago

Addm LMS + Sundry Fees to school fee.

  • Property svn:keywords set to Id
File size: 28.2 KB
Line 
1## $Id: utils.py 16934 2022-04-26 14:57:39Z 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, queryUtility
21from zope.catalog.interfaces import ICatalog
22from waeup.kofa.interfaces import (
23    ADMITTED, CLEARANCE, REQUESTED, CLEARED, RETURNING, PAID,
24    REGISTERED, VALIDATED, academic_sessions_vocab)
25from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
26from waeup.kofa.accesscodes import create_accesscode
27from waeup.kofa.students.utils import trans
28from waeup.aaue.interswitch.browser import gateway_net_amt, GATEWAY_AMT
29from waeup.aaue.interfaces import MessageFactory as _
30
31MINIMUM_UNITS_THRESHOLD = 15
32
33class CustomStudentsUtils(NigeriaStudentsUtils):
34    """A collection of customized methods.
35
36    """
37
38    # PORTRAIT_CHANGE_STATES = (ADMITTED, CLEARANCE, REQUESTED, CLEARED)
39
40    def allowPortraitChange(self, student):
41        if student.is_fresh:
42            return True
43        return False
44
45    def GPABoundaries(self, faccode=None, depcode=None,
46                            certcode=None, student=None):
47        if student and student.current_mode.startswith('dp'):
48            return ((1.5, 'IRNS / NER / NYV'),
49                    (2.4, 'Pass'),
50                    (3.5, 'Merit'),
51                    (4.5, 'Credit'),
52                    (5, 'Distinction'))
53        elif student:
54            return ((1, 'FRNS / NER / NYV'),
55                    (1.5, 'Pass'),
56                    (2.4, '3rd Class Honours'),
57                    (3.5, '2nd Class Honours Lower Division'),
58                    (4.5, '2nd Class Honours Upper Division'),
59                    (5, '1st Class Honours'))
60        # Session Results Presentations depend on certificate
61        results = None
62        if certcode:
63            cat = queryUtility(ICatalog, name='certificates_catalog')
64            results = list(
65                cat.searchResults(code=(certcode, certcode)))
66        if results and results[0].study_mode.startswith('dp'):
67            return ((1.5, 'IRNS / NER / NYV'),
68                    (2.4, 'Pass'),
69                    (3.5, 'Merit'),
70                    (4.5, 'Credit'),
71                    (5, 'Distinction'))
72        else:
73            return ((1, 'FRNS / NER / NYV'),
74                    (1.5, 'Pass'),
75                    (2.4, '3rd Class Honours'),
76                    (3.5, '2nd Class Honours Lower Division'),
77                    (4.5, '2nd Class Honours Upper Division'),
78                    (5, '1st Class Honours'))
79
80    def getClassFromCGPA(self, gpa, student):
81        gpa_boundaries = self.GPABoundaries(student=student)
82
83        try:
84            certificate = getattr(student['studycourse'],'certificate',None)
85            end_level = getattr(certificate, 'end_level', None)
86            final_level = max([studylevel.level for studylevel in student['studycourse'].values()])
87            if end_level and final_level >= end_level:
88                dummy, repeat = divmod(final_level, 100)
89                if gpa <= 5.1 and repeat == 20:
90                    # Irrespective of the CGPA of a student, if the He/She has
91                    # 3rd Extension, such student will be graduated with a "Pass".
92                    return 1, gpa_boundaries[1][1]
93        except ValueError:
94            pass
95
96        if gpa < gpa_boundaries[0][0]:
97            # FRNS / Fail
98            return 0, gpa_boundaries[0][1]
99        if student.entry_session < 2013 or \
100            student.current_mode.startswith('dp'):
101            if gpa < gpa_boundaries[1][0]:
102                # Pass
103                return 1, gpa_boundaries[1][1]
104        else:
105            if gpa < gpa_boundaries[1][0]:
106                # FRNS
107                # Pass degree has been phased out in 2013 for non-diploma
108                # students
109                return 0, gpa_boundaries[0][1]
110        if gpa < gpa_boundaries[2][0]:
111            # 3rd / Merit
112            return 2, gpa_boundaries[2][1]
113        if gpa < gpa_boundaries[3][0]:
114            # 2nd L / Credit
115            return 3, gpa_boundaries[3][1]
116        if gpa < gpa_boundaries[4][0]:
117            # 2nd U / Distinction
118            return 4, gpa_boundaries[4][1]
119        if gpa <= gpa_boundaries[5][0]:
120            # 1st
121            return 5, gpa_boundaries[5][1]
122        return
123
124    def getDegreeClassNumber(self, level_obj):
125        """Get degree class number (used for SessionResultsPresentation
126        reports).
127        """
128        certificate = getattr(level_obj.__parent__,'certificate', None)
129        end_level = getattr(certificate, 'end_level', None)
130        if level_obj.level_verdict in ('FRNS', 'NER', 'NYV'):
131            return 0
132        if end_level and level_obj.level >= end_level:
133            if level_obj.level > end_level:
134                # spill-over level
135                if level_obj.gpa_params[1] == 0:
136                    # no credits taken
137                    return 0
138            elif level_obj.gpa_params[1] < MINIMUM_UNITS_THRESHOLD:
139                # credits taken below limit
140                return 0
141            failed_courses = level_obj.passed_params[4]
142            not_taken_courses = level_obj.passed_params[5]
143            if '_m' in failed_courses:
144                return 0
145            if len(not_taken_courses) \
146                and not not_taken_courses == 'Nil':
147                return 0
148        elif level_obj.gpa_params[1] < MINIMUM_UNITS_THRESHOLD:
149            # credits taken below limit
150            return 0
151        # use gpa_boundaries above
152        return self.getClassFromCGPA(
153            level_obj.cumulative_params[0], level_obj.student)[0]
154
155    def increaseMatricInteger(self, student):
156        """Increase counter for matric numbers.
157        This counter can be a centrally stored attribute or an attribute of
158        faculties, departments or certificates. In the base package the counter
159        is as an attribute of the site configuration container.
160        """
161        if student.current_mode in ('ug_pt', 'de_pt', 'ug_dsh', 'de_dsh'):
162            grok.getSite()['configuration'].next_matric_integer += 1
163            return
164        elif student.is_postgrad:
165            grok.getSite()['configuration'].next_matric_integer_3 += 1
166            return
167        elif student.current_mode in ('dp_ft',):
168            grok.getSite()['configuration'].next_matric_integer_4 += 1
169            return
170        grok.getSite()['configuration'].next_matric_integer_2 += 1
171        return
172
173    def _concessionalPaymentMade(self, student):
174        if len(student['payments']):
175            for ticket in student['payments'].values():
176                if ticket.p_state == 'paid' and \
177                    ticket.p_category == 'concessional':
178                    return True
179        return False
180
181    def constructMatricNumber(self, student):
182        faccode = student.faccode
183        depcode = student.depcode
184        certcode = student.certcode
185        degree = getattr(
186            getattr(student.get('studycourse', None), 'certificate', None),
187                'degree', None)
188        year = unicode(student.entry_session)[2:]
189        if not student.state in (PAID, ) or not student.is_fresh or \
190            student.current_mode in ('found', 'ijmbe'):
191            return _('Matriculation number cannot be set.'), None
192        #if student.current_mode not in ('mug_ft', 'mde_ft') and \
193        #    not self._concessionalPaymentMade(student):
194        #    return _('Matriculation number cannot be set.'), None
195        if student.is_postgrad:
196            next_integer = grok.getSite()['configuration'].next_matric_integer_3
197            if not degree or next_integer == 0:
198                return _('Matriculation number cannot be set.'), None
199            if student.faccode in ('IOE'):
200                return None, "AAU/SPS/%s/%s/%s/%05d" % (
201                    faccode, year, degree, next_integer)
202            return None, "AAU/SPS/%s/%s/%s/%s/%05d" % (
203                faccode, depcode, year, degree, next_integer)
204        if student.current_mode in ('ug_dsh', 'de_dsh'):
205            next_integer = grok.getSite()['configuration'].next_matric_integer
206            if next_integer == 0:
207                return _('Matriculation number cannot be set.'), None
208            return None, "DSH/%s/%s/%s/%05d" % (
209                faccode, depcode, year, next_integer)
210        if student.current_mode in ('ug_pt', 'de_pt'):
211            next_integer = grok.getSite()['configuration'].next_matric_integer
212            if next_integer == 0:
213                return _('Matriculation number cannot be set.'), None
214            return None, "PTP/%s/%s/%s/%05d" % (
215                faccode, depcode, year, next_integer)
216        if student.current_mode in ('dp_ft',):
217            next_integer = grok.getSite()['configuration'].next_matric_integer_4
218            if next_integer == 0:
219                return _('Matriculation number cannot be set.'), None
220            return None, "IOE/DIP/%s/%05d" % (year, next_integer)
221        next_integer = grok.getSite()['configuration'].next_matric_integer_2
222        if next_integer == 0:
223            return _('Matriculation number cannot be set.'), None
224        if student.faccode in ('FBM', 'FCS', 'FMLS'):
225            return None, "CMS/%s/%s/%s/%05d" % (
226                faccode, depcode, year, next_integer)
227        return None, "%s/%s/%s/%05d" % (faccode, depcode, year, next_integer)
228
229    def getReturningData(self, student):
230        """ This method defines what happens after school fee payment
231        of returning students depending on the student's senate verdict.
232        """
233        prev_level = student['studycourse'].current_level
234        cur_verdict = student['studycourse'].current_verdict
235        if cur_verdict in ('A','B','L','M','N','Z',):
236            # Successful student
237            new_level = divmod(int(prev_level),100)[0]*100 + 100
238        elif cur_verdict == 'C':
239            # Student on probation
240            new_level = int(prev_level) + 10
241        else:
242            # Student is somehow in an undefined state.
243            # Level has to be set manually.
244            new_level = prev_level
245        new_session = student['studycourse'].current_session + 1
246        return new_session, new_level
247
248    def _isPaymentDisabled(self, p_session, category, student):
249        academic_session = self._getSessionConfiguration(p_session)
250        if category.startswith('schoolfee'):
251            if 'sf_all' in academic_session.payment_disabled:
252                return True
253            if 'sf_pg' in academic_session.payment_disabled and \
254                student.is_postgrad:
255                return True
256            if 'sf_ug_pt' in academic_session.payment_disabled and \
257                student.current_mode in ('ug_pt', 'de_pt'):
258                return True
259            if 'sf_found' in academic_session.payment_disabled and \
260                student.current_mode == 'found':
261                return True
262        if category.startswith('clearance') and \
263            'cl_regular' in academic_session.payment_disabled and \
264            student.current_mode in ('ug_ft', 'de_ft', 'mug_ft', 'mde_ft'):
265            return True
266        if category == 'hostel_maintenance' and \
267            'maint_all' in academic_session.payment_disabled:
268            return True
269        return False
270
271    def setPaymentDetails(self, category, student,
272            previous_session=None, previous_level=None, combi=[]):
273        """Create Payment object and set the payment data of a student for
274        the payment category specified.
275
276        """
277        details = {}
278        p_item = u''
279        amount = 0.0
280        error = u''
281        if previous_session:
282            if previous_session < student['studycourse'].entry_session:
283                return _('The previous session must not fall below '
284                         'your entry session.'), None
285            if category == 'schoolfee':
286                # School fee is always paid for the following session
287                if previous_session > student['studycourse'].current_session:
288                    return _('This is not a previous session.'), None
289            else:
290                if previous_session > student['studycourse'].current_session - 1:
291                    return _('This is not a previous session.'), None
292            p_session = previous_session
293            p_level = previous_level
294            p_current = False
295        else:
296            p_session = student['studycourse'].current_session
297            p_level = student['studycourse'].current_level
298            p_current = True
299        academic_session = self._getSessionConfiguration(p_session)
300        if academic_session == None:
301            return _(u'Session configuration object is not available.'), None
302        # Determine fee.
303        if category == 'transfer':
304            amount = academic_session.transfer_fee
305        elif category == 'transcript_local':
306            amount = academic_session.transcript_fee_local
307        elif category == 'transcript_inter':
308            amount = academic_session.transcript_fee_inter
309        elif category == 'bed_allocation':
310            amount = academic_session.booking_fee
311        elif category == 'restitution':
312            if student.current_session != 2016 \
313                or student.current_mode not in ('ug_ft', 'dp_ft') \
314                or student.is_fresh:
315                return _(u'Restitution fee payment not required.'), None
316            amount = academic_session.restitution_fee
317        elif category == 'hostel_maintenance':
318            amount = 0.0
319            bedticket = student['accommodation'].get(
320                str(student.current_session), None)
321            if bedticket is not None and bedticket.bed is not None:
322                p_item = bedticket.display_coordinates
323                if bedticket.bed.__parent__.maint_fee > 0:
324                    amount = bedticket.bed.__parent__.maint_fee
325                else:
326                    # fallback
327                    amount = academic_session.maint_fee
328            else:
329                return _(u'No bed allocated.'), None
330        elif student.current_mode == 'found' and category not in (
331            'schoolfee', 'clearance', 'late_registration'):
332            return _('Not allowed.'), None
333        elif category.startswith('clearance'):
334            if student.state not in (ADMITTED, CLEARANCE, REQUESTED, CLEARED):
335                return _(u'Acceptance Fee payments not allowed.'), None
336            if student.current_mode in (
337                'ug_ft', 'ug_pt', 'de_ft', 'de_pt',
338                'transfer', 'mug_ft', 'mde_ft') \
339                and category != 'clearance_incl':
340                    return _("Additional fees must be included."), None
341            if student.current_mode == 'ijmbe':
342                amount = academic_session.clearance_fee_ijmbe
343            elif student.current_mode == 'bridge':
344                amount = academic_session.clearance_fee_bridge
345            elif student.current_mode == 'dp_ft':
346                amount = academic_session.clearance_fee_dp
347            elif student.faccode == 'FP':
348                amount = academic_session.clearance_fee_fp
349            elif student.current_mode in ('ug_pt', 'de_pt', 'ug_dsh', 'de_dsh'):
350                amount = academic_session.clearance_fee_ug_pt
351            elif student.current_mode == 'special_pg_pt':
352                amount = academic_session.clearance_fee_pg_pt
353            elif student.faccode == 'FCS':
354                # Students in clinical medical sciences pay the medical
355                # acceptance fee
356                amount = academic_session.clearance_fee_med
357            elif student.current_mode == 'special_pg_ft':
358                if category != 'clearance':
359                    return _("No additional fees required."), None
360                amount = academic_session.clearance_fee_pg
361            else:
362                amount = academic_session.clearance_fee
363            p_item = student['studycourse'].certificate.code
364            if amount in (0.0, None):
365                return _(u'Amount could not be determined.'), None
366            # Add Matric Gown Fee and Lapel Fee
367            if category == 'clearance_incl':
368                amount += gateway_net_amt(academic_session.matric_gown_fee) + \
369                    gateway_net_amt(academic_session.lapel_fee)
370        elif category == 'late_registration':
371            if student.is_postgrad:
372                amount = academic_session.late_pg_registration_fee
373            else:
374                amount = academic_session.late_registration_fee
375        elif category == 'ict':
376            if student.is_fresh:
377                amount = 2200
378            else:
379                amount = 1200
380        elif category.startswith('schoolfee'):
381            try:
382                certificate = student['studycourse'].certificate
383                p_item = certificate.code
384            except (AttributeError, TypeError):
385                return _('Study course data are incomplete.'), None
386            if student.is_postgrad and category != 'schoolfee':
387                return _("No additional fees required."), None
388            if not previous_session and student.current_mode in (
389                'ug_ft', 'ug_pt', 'de_ft', 'de_pt',
390                'transfer', 'mug_ft', 'mde_ft') \
391                and not category in (
392                'schoolfee_incl', 'schoolfee_1', 'schoolfee_2'):
393                    return _("You must choose a payment which includes "
394                             "additional fees."), None
395            if category in ('schoolfee_1', 'schoolfee_2'):
396                if student.current_mode == 'ug_pt':
397                    return _("Part-time students are not allowed "
398                             "to pay by instalments."), None
399                if student.entry_session < 2015:
400                    return _("You are not allowed "
401                             "to pay by instalments."), None
402            if previous_session:
403                # Students can pay for previous sessions in all
404                # workflow states.  Fresh students are excluded by the
405                # update method of the PreviousPaymentAddFormPage.
406                if previous_level == 100:
407                    amount = getattr(certificate, 'school_fee_1', 0.0)
408                else:
409                    if student.entry_session in (2015, 2016):
410                        amount = getattr(certificate, 'school_fee_2', 0.0)
411                    else:
412                        amount = getattr(certificate, 'school_fee_3', 0.0)
413            elif student.state == CLEARED and category != 'schoolfee_2':
414                amount = getattr(certificate, 'school_fee_1', 0.0)
415                # Cut school fee by 50%
416                if category == 'schoolfee_1' and amount:
417                    amount = gateway_net_amt(amount) / 2 + GATEWAY_AMT
418            elif student.is_fresh and category == 'schoolfee_2':
419                amount = getattr(certificate, 'school_fee_1', 0.0)
420                # Cut school fee by 50%
421                if amount:
422                    amount = gateway_net_amt(amount) / 2 + GATEWAY_AMT
423            elif student.state == RETURNING and category != 'schoolfee_2':
424                if not student.father_name:
425                    return _("Personal data form is not properly filled."), None
426                # In case of returning school fee payment the payment session
427                # and level contain the values of the session the student
428                # has paid for.
429                p_session, p_level = self.getReturningData(student)
430                try:
431                    academic_session = grok.getSite()[
432                        'configuration'][str(p_session)]
433                except KeyError:
434                    return _(u'Session configuration object is not available.'), None
435                if student.entry_session >= 2015:
436                    amount = getattr(certificate, 'school_fee_2', 0.0)
437                else:
438                    amount = getattr(certificate, 'school_fee_3', 0.0)
439                # Cut school fee by 50%
440                if category == 'schoolfee_1' and amount:
441                    amount = gateway_net_amt(amount) / 2 + GATEWAY_AMT
442            elif category == 'schoolfee_2':
443                amount = getattr(certificate, 'school_fee_2', 0.0)
444                # Cut school fee by 50%
445                if amount:
446                    amount = gateway_net_amt(amount) / 2 + GATEWAY_AMT
447            else:
448                return _('Wrong state.'), None
449            if amount in (0.0, None):
450                return _(u'Amount could not be determined.'), None
451            # Add Student Union Fee, Student Id Card Fee, Sports Dev. Fee,
452            # Library Dev. Fee and Welfare Assurance
453            if category in ('schoolfee_incl', 'schoolfee_1') \
454                and student.current_mode != 'ijmbe':
455                amount += gateway_net_amt(academic_session.welfare_fee) + \
456                    gateway_net_amt(academic_session.union_fee)
457                if student.entry_session >= 2018 and student.is_fresh:
458                    amount += gateway_net_amt(academic_session.sports_fee)
459                    if student.is_postgrad:
460                        amount += gateway_net_amt(academic_session.library_pg_fee)
461                    else:
462                        amount += gateway_net_amt(academic_session.library_fee)
463                if student.entry_session >= 2021 and student.is_fresh \
464                    and student.current_mode == 'ug_ft':
465                    amount += gateway_net_amt(academic_session.lms_sund_fee)
466            # Add non-indigenous fee and session specific penalty fees
467            if student.is_postgrad:
468                amount += academic_session.penalty_pg
469                if student.lga and not student.lga.startswith('edo'):
470                    amount += 20000.0
471            else:
472                amount += academic_session.penalty_ug
473        #elif category == ('fac_dep'):
474        #    if student.faccode in ('FAT', 'FED', 'FLW', 'FMS', 'FSS'):
475        #        amount = 4200.0
476        #    elif student.faccode in ('FAG', 'FBM', 'FCS',
477        #                             'FES', 'FET', 'FLS', 'FPS'):
478        #        amount = 5200.0
479        #    elif student.faccode == 'FAG' and student.current_level == 400:
480        #        amount = 10200.0
481        #    elif student.depcode == 'VTE':
482        #        amount = 5200.0
483        #    if student.entry_session >= 2019:
484        #        amount += gateway_net_amt(academic_session.ict_fee)
485        elif category == 'sports_library': # temporarily in 2020
486            if student.is_postgrad:
487                amount = academic_session.sports_fee + gateway_net_amt(
488                    academic_session.library_pg_fee)
489            else:
490                amount = academic_session.sports_fee + gateway_net_amt(
491                    academic_session.library_fee)
492        elif not student.is_postgrad:
493            fee_name = category + '_fee'
494            amount = getattr(academic_session, fee_name, 0.0)
495        if amount in (0.0, None):
496            return _(u'Amount could not be determined.'), None
497        # Create ticket.
498        for key in student['payments'].keys():
499            ticket = student['payments'][key]
500            if ticket.p_state == 'paid' and\
501               ticket.p_category == category and \
502               not ticket.p_category.startswith('transcript') and \
503               ticket.p_item == p_item and \
504               ticket.p_session == p_session:
505                  return _('This type of payment has already been made.'), None
506            # Additional condition in AAUE
507            if category in ('schoolfee', 'schoolfee_incl', 'schoolfee_1'):
508                if ticket.p_state == 'paid' and \
509                   ticket.p_category in ('schoolfee',
510                                         'schoolfee_incl',
511                                         'schoolfee_1') and \
512                   ticket.p_item == p_item and \
513                   ticket.p_session == p_session:
514                      return _(
515                          'Another school fee payment for this '
516                          'session has already been made.'), None
517
518        if self._isPaymentDisabled(p_session, category, student):
519            return _('This category of payments has been disabled.'), None
520        payment = createObject(u'waeup.StudentOnlinePayment')
521        timestamp = ("%d" % int(time()*10000))[1:]
522        payment.p_id = "p%s" % timestamp
523        payment.p_category = category
524        payment.p_item = p_item
525        payment.p_session = p_session
526        payment.p_level = p_level
527        payment.p_current = p_current
528        payment.amount_auth = amount
529        return None, payment
530
531    def _admissionText(self, student, portal_language):
532        inst_name = grok.getSite()['configuration'].name
533        entry_session = student['studycourse'].entry_session
534        entry_session = academic_sessions_vocab.getTerm(entry_session).title
535        text = trans(_(
536            'This is to inform you that you have been offered provisional'
537            ' admission into ${a} for the ${b} academic session as follows:',
538            mapping = {'a': inst_name, 'b': entry_session}),
539            portal_language)
540        return text
541
542    def warnCreditsOOR(self, studylevel, course=None):
543        studycourse = studylevel.__parent__
544        certificate = getattr(studycourse,'certificate', None)
545        current_level = studycourse.current_level
546        if None in (current_level, certificate):
547            return
548        end_level = certificate.end_level
549        if current_level >= end_level:
550            limit = 52
551        else:
552            limit = 48
553        if course and studylevel.total_credits + course.credits > limit:
554            return  _('Maximum credits exceeded.')
555        elif studylevel.total_credits > limit:
556            return _('Maximum credits exceeded.')
557        return
558
559    def getBedCoordinates(self, bedticket):
560        """Return descriptive bed coordinates.
561        This method can be used to customize the `display_coordinates`
562        property method in order to  display a
563        customary description of the bed space.
564        """
565        bc = bedticket.bed_coordinates.split(',')
566        if len(bc) == 4:
567            return bc[0]
568        return bedticket.bed_coordinates
569
570    def getAccommodationDetails(self, student):
571        """Determine the accommodation data of a student.
572        """
573        d = {}
574        d['error'] = u''
575        hostels = grok.getSite()['hostels']
576        d['booking_session'] = hostels.accommodation_session
577        d['allowed_states'] = hostels.accommodation_states
578        d['startdate'] = hostels.startdate
579        d['enddate'] = hostels.enddate
580        d['expired'] = hostels.expired
581        # Determine bed type
582        bt = 'all'
583        if student.sex == 'f':
584            sex = 'female'
585        else:
586            sex = 'male'
587        special_handling = 'regular'
588        d['bt'] = u'%s_%s_%s' % (special_handling,sex,bt)
589        return d
590
591    def checkAccommodationRequirements(self, student, acc_details):
592        msg = super(CustomStudentsUtils, self).checkAccommodationRequirements(
593            student, acc_details)
594        if msg:
595            return msg
596        if student.current_mode not in ('ug_ft', 'de_ft', 'mug_ft', 'mde_ft'):
597            return _('You are not eligible to book accommodation.')
598        return
599
600    # AAUE prefix
601    STUDENT_ID_PREFIX = u'E'
602
603    STUDENT_EXPORTER_NAMES = (
604            'students',
605            'studentstudycourses',
606            'studentstudycourses_1',
607            'studentstudylevels',
608            #'studentstudylevels_1',
609            'coursetickets',
610            #'coursetickets_1',
611            'studentpayments',
612            'bedtickets',
613            'unpaidpayments',
614            'sfpaymentsoverview',
615            'studylevelsoverview',
616            'combocard',
617            'bursary',
618            'levelreportdata',
619            'outstandingcourses',
620            'sessionpaymentsoverview',
621            'accommodationpayments',
622            'transcriptdata',
623            'trimmedpayments',
624            'trimmed',
625            'outstandingcourses_2'
626            )
627
628    # Maximum size of upload files in kB
629    MAX_KB = 500
Note: See TracBrowser for help on using the repository browser.