source: main/waeup.kofa/trunk/src/waeup/kofa/students/payments.py @ 13012

Last change on this file since 13012 was 12889, checked in by Henrik Bettermann, 10 years ago

Bypass school fee payment activation code creation if student is allowed
to proceed to next session.

  • Property svn:keywords set to Id
File size: 7.6 KB
RevLine 
[7191]1## $Id: payments.py 12889 2015-04-27 08:14:31Z henrik $
2##
[6635]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##
18"""
[7599]19Student payment components.
[6635]20"""
21import grok
22from zope.component.interfaces import IFactory
[6875]23from zope.interface import implementedBy
[12889]24from zope.schema.interfaces import ConstraintNotSatisfied
25from hurry.workflow.interfaces import IWorkflowInfo
[8420]26from waeup.kofa.interfaces import MessageFactory as _
[7811]27from waeup.kofa.students.interfaces import (
[6877]28    IStudentPaymentsContainer, IStudentNavigation, IStudentOnlinePayment)
[12889]29from waeup.kofa.students.workflow import CLEARED, RETURNING, PAID
[7811]30from waeup.kofa.payments import PaymentsContainer, OnlinePayment
[10030]31from waeup.kofa.payments.interfaces import IPayer
[7811]32from waeup.kofa.utils.helpers import attrs_to_fields
[8420]33from waeup.kofa.accesscodes import create_accesscode
[6635]34
[6860]35class StudentPaymentsContainer(PaymentsContainer):
[6635]36    """This is a container for student payments.
37    """
[6860]38    grok.implements(IStudentPaymentsContainer, IStudentNavigation)
39    grok.provides(IStudentPaymentsContainer)
[6635]40
41    def __init__(self):
[6860]42        super(StudentPaymentsContainer, self).__init__()
[6635]43        return
44
[8736]45    @property
46    def student(self):
[6642]47        return self.__parent__
48
[8735]49    def writeLogMessage(self, view, message):
50        return self.__parent__.writeLogMessage(view, message)
51
[6875]52StudentPaymentsContainer = attrs_to_fields(StudentPaymentsContainer)
53
54class StudentOnlinePayment(OnlinePayment):
55    """This is an online payment.
56    """
[6877]57    grok.implements(IStudentOnlinePayment, IStudentNavigation)
58    grok.provides(IStudentOnlinePayment)
[6875]59
60    def __init__(self):
61        super(StudentOnlinePayment, self).__init__()
62        return
63
[8736]64    @property
65    def student(self):
[8368]66        try:
67            return self.__parent__.__parent__
68        except AttributeError:
69            return None
[6875]70
[8735]71    def writeLogMessage(self, view, message):
72        return self.__parent__.__parent__.writeLogMessage(view, message)
73
[12889]74    def _redeemTicket(self):
[8736]75        student = self.student
[8420]76        if self.p_category == 'clearance':
77            # Create CLR access code
78            pin, error = create_accesscode(
79                'CLR',0,self.amount_auth,student.student_id)
80            if error:
[8732]81                return error
[8420]82            self.ac = pin
[8732]83        elif self.p_category in ('schoolfee', 'schoolfee_1'):
[12889]84            # Bypass activation code creation if next session
85            # can be started directly.
86            if student['studycourse'].next_session_allowed:
87                try:
88                    if student.state == CLEARED:
89                        IWorkflowInfo(student).fireTransition(
90                            'pay_first_school_fee')
91                        return None
92                    elif student.state == RETURNING:
93                        IWorkflowInfo(student).fireTransition(
94                            'pay_school_fee')
95                        return None
96                    elif student.state == PAID:
97                        IWorkflowInfo(student).fireTransition(
98                            'pay_pg_fee')
99                        return None
100                except ConstraintNotSatisfied:
101                    pass
[8420]102            # Create SFE access code
103            pin, error = create_accesscode(
104                'SFE',0,self.amount_auth,student.student_id)
105            if error:
[8732]106                return error
[8420]107            self.ac = pin
108        elif self.p_category == 'bed_allocation':
109            # Create HOS access code
110            pin, error = create_accesscode(
111                'HOS',0,self.amount_auth,student.student_id)
112            if error:
[8732]113                return error
[8420]114            self.ac = pin
[10449]115        elif self.p_category == 'transcript':
116            # Create TSC access code
117            pin, error = create_accesscode(
118                'TSC',0,self.amount_auth,student.student_id)
119            if error:
120                return error
121            self.ac = pin
[8732]122        return None
123
124    def doAfterStudentPayment(self):
125        """Process student after payment was made.
126        """
[9148]127        if self.p_current:
[12889]128            error = self._redeemTicket()
[9148]129            if error is not None:
[11580]130                return 'danger', error, error
[9438]131        log = 'successful %s payment: %s' % (self.p_category, self.p_id)
[8428]132        msg = _('Successful payment')
[11580]133        flashtype = 'success'
134        return flashtype, msg, log
[8420]135
[8453]136    def doAfterStudentPaymentApproval(self):
137        """Process student after payment was approved.
138        """
[9148]139        if self.p_current:
[12889]140            error = self._redeemTicket()
[9148]141            if error is not None:
[11580]142                return 'danger', error, error
[9438]143        log = '%s payment approved: %s' % (self.p_category, self.p_id)
[11583]144        msg = _('Payment approved.')
[11580]145        flashtype = 'success'
146        return flashtype, msg, log
[8453]147
[8422]148    def approveStudentPayment(self):
149        """Approve payment and process student.
150        """
151        if self.p_state == 'paid':
[11580]152            return 'warning', _('This ticket has already been paid.'), None
[8422]153        self.approve()
[8732]154        return self.doAfterStudentPaymentApproval()
[8422]155
156
[9984]157StudentOnlinePayment = attrs_to_fields(
158    StudentOnlinePayment, omit=['display_item'])
[6875]159
[10030]160class Payer(grok.Adapter):
161    """An adapter to publish student data through a simple webservice.
[8703]162    """
163    grok.context(IStudentOnlinePayment)
[10030]164    grok.implements(IPayer)
[8703]165
166    @property
[8708]167    def display_fullname(self):
[10030]168        "Name of  payer"
[8736]169        return self.context.student.display_fullname
[8703]170
[8708]171    @property
172    def id(self):
[10030]173        "Id of payer"
[8736]174        return self.context.student.student_id
[8708]175
176    @property
[9733]177    def matric_number(self):
[10030]178        "Matric number or reg number of payer"
[9506]179        return self.context.student.matric_number
180
181    @property
[9733]182    def reg_number(self):
[10030]183        "Reg number or reg number of payer"
[9733]184        return self.context.student.reg_number
185
186    @property
[8708]187    def faculty(self):
[10030]188        "Faculty of payer"
[8736]189        return self.context.student.faccode
[8708]190
191    @property
192    def department(self):
[10030]193        "Department of payer"
[8736]194        return self.context.student.depcode
[8708]195
[10906]196    @property
197    def email(self):
198        "Email of payer"
199        return self.context.student.email
200
201    @property
202    def phone(self):
203        "Phone number of payer"
204        return self.context.student.phone
205
206    @property
207    def current_mode(self):
208        "Current study mode of payer"
209        return self.context.student.current_mode
210
211    @property
212    def current_level(self):
213        "Current level of payer"
214        return self.context.student.current_level
215
[6875]216# Student online payments must be importable. So we might need a factory.
217class StudentOnlinePaymentFactory(grok.GlobalUtility):
218    """A factory for student online payments.
219    """
220    grok.implements(IFactory)
221    grok.name(u'waeup.StudentOnlinePayment')
222    title = u"Create a new online payment.",
223    description = u"This factory instantiates new online payment instances."
224
225    def __call__(self, *args, **kw):
226        return StudentOnlinePayment()
227
228    def getInterfaces(self):
[7811]229        return implementedBy(StudentOnlinePayment)
Note: See TracBrowser for help on using the repository browser.