source: main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py @ 9520

Last change on this file since 9520 was 9520, checked in by Henrik Bettermann, 12 years ago

Reorganize getReturningData.

Students can pay for previous sessions in all workflow states.
Fresh students are excluded by the update method of the
PreviousPaymentAddFormPage?.

Students are only allowed to pay for the next session if current session payment has really been made, i.e. payment object exists and is paid.

  • Property svn:keywords set to Id
File size: 12.8 KB
Line 
1## $Id: utils.py 9520 2012-11-04 07:48:11Z 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 reportlab.lib.styles import getSampleStyleSheet
22from reportlab.platypus import Paragraph, Image, Table, Spacer
23from waeup.kofa.interfaces import (IKofaUtils,
24    CLEARED, RETURNING, PAID, REGISTERED, VALIDATED)
25from kofacustom.nigeria.students.utils import NigeriaStudentsUtils
26from waeup.kofa.accesscodes import create_accesscode
27from waeup.uniben.interfaces import MessageFactory as _
28from waeup.kofa.students.utils import (trans, render_student_data,
29    render_table_data, get_signature_table)
30
31class CustomStudentsUtils(NigeriaStudentsUtils):
32    """A collection of customized methods.
33
34    """
35
36    def getReturningData(self, student):
37        """ This method defines what happens after school fee payment
38        of returning students depending on the student's senate verdict.
39        """
40        prev_level = student['studycourse'].current_level
41        cur_verdict = student['studycourse'].current_verdict
42        if cur_verdict in ('A','B','L','M','N','Z',):
43            # Successful student
44            new_level = divmod(int(prev_level),100)[0]*100 + 100
45        elif cur_verdict == 'C':
46            # Student on probation
47            new_level = int(prev_level) + 10
48        else:
49            # Student is somehow in an undefined state.
50            # Level has to be set manually.
51            new_level = prev_level
52        new_session = student['studycourse'].current_session + 1
53        return new_session, new_level
54
55    def _paymentMade(self, student, session):
56        if len(student['payments']):
57            for ticket in student['payments'].values():
58                if ticket.p_state == 'paid' and \
59                    ticket.p_category == 'schoolfee' and \
60                    ticket.p_session == session:
61                    return True
62        return False
63
64    def setPaymentDetails(self, category, student,
65            previous_session, previous_level):
66        """Create Payment object and set the payment data of a student for
67        the payment category specified.
68
69        """
70        p_item = u''
71        amount = 0.0
72        if previous_session:
73            if previous_session < student['studycourse'].entry_session:
74                return _('The previous session must not fall below '
75                         'your entry session.'), None
76            if category == 'schoolfee':
77                # School fee is always paid for the following session
78                if previous_session > student['studycourse'].current_session:
79                    return _('This is not a previous session.'), None
80            else:
81                if previous_session > student['studycourse'].current_session - 1:
82                    return _('This is not a previous session.'), None
83            p_session = previous_session
84            p_level = previous_level
85            p_current = False
86        else:
87            p_session = student['studycourse'].current_session
88            p_level = student['studycourse'].current_level
89            p_current = True
90        academic_session = self._getSessionConfiguration(p_session)
91        if academic_session == None:
92            return _(u'Session configuration object is not available.'), None
93        # Determine fee.
94        if category == 'transfer':
95            amount = academic_session.transfer_fee
96        elif category == 'gown':
97            amount = academic_session.gown_fee
98        elif category == 'bed_allocation':
99            amount = academic_session.booking_fee
100        elif category == 'hostel_maintenance':
101            amount = academic_session.maint_fee
102        elif category == 'clearance':
103            try:
104                p_item = student['studycourse'].certificate.code
105            except (AttributeError, TypeError):
106                return _('Study course data are incomplete.'), None
107            if p_item in ('BSCANA', 'BSCMBC', 'BMLS', 'BSCNUR', 'BSCPHS', 'BDS',
108                'MBBSMED', 'MBBSNDU'):
109                amount = 65000.0
110            elif p_item in ('BEDCET', 'BIOEDCET', 'CHMEDCET', 'ISEDCET',
111                'MTHEDCET', 'PHYEDCET', 'ITECET', 'AGREDCET', 'HEEDCET'):
112                amount = 22500.0
113            else:
114                amount = 45000.0
115        elif category == 'schoolfee':
116            try:
117                certificate = student['studycourse'].certificate
118                p_item = certificate.code
119            except (AttributeError, TypeError):
120                return _('Study course data are incomplete.'), None
121            if previous_session:
122                # Students can pay for previous sessions in all workflow states.
123                # Fresh students are excluded by the update method of the
124                # PreviousPaymentAddFormPage.
125                if previous_session == student['studycourse'].entry_session:
126                    if student.is_foreigner:
127                        amount = getattr(certificate, 'school_fee_3', 0.0)
128                    else:
129                        amount = getattr(certificate, 'school_fee_1', 0.0)
130                else:
131                    if student.is_foreigner:
132                        amount = getattr(certificate, 'school_fee_4', 0.0)
133                    else:
134                        amount = getattr(certificate, 'school_fee_2', 0.0)
135            else:
136                if student.state == CLEARED:
137                    if student.is_foreigner:
138                        amount = getattr(certificate, 'school_fee_3', 0.0)
139                    else:
140                        amount = getattr(certificate, 'school_fee_1', 0.0)
141                elif student.state in (PAID, REGISTERED, VALIDATED):
142                    p_session += 1
143                    # We don't know which level the student is paying for.
144                    p_level = None
145                    academic_session = self._getSessionConfiguration(p_session)
146                    if academic_session == None:
147                        return _(u'Session configuration object is not available.'), None
148                    # Students are only allowed to pay for the next session
149                    # if current session payment
150                    # has really been made, i.e. payment object exists.
151                    if not self._paymentMade(
152                        student, student.current_session):
153                        return _('You have not yet paid your current/active' +
154                                 ' session. Please use the previous session' +
155                                 ' payment form first.'), None
156                    if student.is_foreigner:
157                        amount = getattr(certificate, 'school_fee_4', 0.0)
158                    else:
159                        amount = getattr(certificate, 'school_fee_2', 0.0)
160                elif student.state == RETURNING:
161                    # In case of returning school fee payment the payment session
162                    # and level contain the values of the session the student
163                    # has paid for.
164                    p_session, p_level = self.getReturningData(student)
165                    academic_session = self._getSessionConfiguration(p_session)
166                    if academic_session == None:
167                        return _(u'Session configuration object is not available.'), None
168                    # Students are only allowed to pay for the next session
169                    # if current session payment has really been made,
170                    # i.e. payment object exists and is paid.
171                    if not self._paymentMade(
172                        student, student.current_session):
173                        return _('You have not yet paid your current/active' +
174                                 ' session. Please use the previous session' +
175                                 ' payment form first.'), None
176                    if student.is_foreigner:
177                        amount = getattr(certificate, 'school_fee_4', 0.0)
178                    else:
179                        amount = getattr(certificate, 'school_fee_2', 0.0)
180            # Give 50% school fee discount to staff members.
181            if student.is_staff:
182                amount /= 2
183        if amount in (0.0, None):
184            return _('Amount could not be determined.'), None
185        # Add session specific penalty fee.
186        if category == 'schoolfee' and student.is_postgrad:
187            amount += academic_session.penalty_pg
188        elif category == 'schoolfee':
189            amount += academic_session.penalty_ug
190        # Create ticket.
191        for key in student['payments'].keys():
192            ticket = student['payments'][key]
193            if ticket.p_state == 'paid' and\
194               ticket.p_category == category and \
195               ticket.p_item == p_item and \
196               ticket.p_session == p_session:
197                  return _('This type of payment has already been made.'), None
198        payment = createObject(u'waeup.StudentOnlinePayment')
199        timestamp = ("%d" % int(time()*10000))[1:]
200        payment.p_id = "p%s" % timestamp
201        payment.p_category = category
202        payment.p_item = p_item
203        payment.p_session = p_session
204        payment.p_level = p_level
205        payment.p_current = p_current
206        payment.amount_auth = amount
207        return None, payment
208
209    def renderPDF(self, view, filename='slip.pdf', student=None,
210                  studentview=None, tableheader=None, tabledata=None,
211                  note=None, signatures=None):
212        """Render pdf slips for various pages.
213        """
214        # XXX: we have to fix the import problems here.
215        from waeup.kofa.browser.interfaces import IPDFCreator
216        from waeup.kofa.browser.pdf import NORMAL_STYLE, ENTRY1_STYLE
217        style = getSampleStyleSheet()
218        creator = getUtility(IPDFCreator)
219        data = []
220        doc_title = view.label
221        author = '%s (%s)' % (view.request.principal.title,
222                              view.request.principal.id)
223        footer_text = view.label
224        if getattr(student, 'student_id', None) is not None:
225            footer_text = "%s - %s - " % (student.student_id, footer_text)
226
227        # Insert student data table
228        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
229        if student is not None:
230            bd_translation = trans(_('Base Data'), portal_language)
231            data.append(Paragraph(bd_translation, style["Heading3"]))
232            data.append(render_student_data(studentview))
233
234        # Insert widgets
235        if view.form_fields:
236            data.append(Paragraph(view.title, style["Heading3"]))
237            portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
238            separators = getattr(self, 'SEPARATORS_DICT', {})
239            table = creator.getWidgetsTable(
240                view.form_fields, view.context, None, lang=portal_language,
241                separators=separators)
242            data.append(table)
243
244        # Insert scanned docs
245        #data.extend(docs_as_flowables(view, portal_language))
246
247       # Insert content table (optionally on second page)
248        if tabledata and tableheader:
249            #data.append(PageBreak())
250            data.append(Spacer(1, 20))
251            data.append(Paragraph(view.content_title, style["Heading3"]))
252            contenttable = render_table_data(tableheader,tabledata)
253            data.append(contenttable)
254
255        # Insert signatures
256        if signatures:
257            data.append(Spacer(1, 20))
258            signaturetable = get_signature_table(signatures)
259            data.append(signaturetable)
260
261        # Insert history
262        if filename.startswith('clearance') or filename.startswith('course'):
263            data.append(Spacer(1, 20))
264            hist_translation = trans(_('Workflow History'), portal_language)
265            data.append(Paragraph(hist_translation, style["Heading3"]))
266            data.extend(creator.fromStringList(student.history.messages))
267
268        view.response.setHeader(
269            'Content-Type', 'application/pdf')
270        try:
271            pdf_stream = creator.create_pdf(
272                data, None, doc_title, author=author, footer=footer_text,
273                note=note)
274        except IOError:
275            view.flash('Error in image file.')
276            return view.redirect(view.url(view.context))
277        return pdf_stream
278
279    # Uniben prefix
280    STUDENT_ID_PREFIX = u'B'
Note: See TracBrowser for help on using the repository browser.