source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/browser.py @ 17233

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

... hide all buttons.

  • Property svn:keywords set to Id
File size: 16.6 KB
RevLine 
[9781]1## $Id: browser.py 16881 2022-03-15 08:47:50Z henrik $
2##
3## Copyright (C) 2012 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
[12973]19from datetime import datetime, timedelta
[11630]20from zope.component import getUtility
[13578]21from zope.security import checkPermission
[11630]22from waeup.kofa.interfaces import IKofaUtils
23from waeup.kofa.utils.helpers import to_timezone
[16484]24from waeup.kofa.browser.layout import UtilityView, KofaPage, KofaFormPage, action
[9781]25from waeup.kofa.browser.viewlets import ManageActionButton
[11642]26from waeup.kofa.students.interfaces import IStudentsUtils
[9781]27from waeup.kofa.students.browser import OnlinePaymentDisplayFormPage as OPDPStudent
28from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
29from kofacustom.nigeria.interswitch.helpers import (
[16484]30    query_interswitch, write_payments_log, fetch_booking_details)
[9781]31from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
32from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
33from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
[16484]34from kofacustom.nigeria.interswitch.tests import PAYDIRECT_URL, PAYDIRECT_HOST, MERCHANT_ID
[9781]35from kofacustom.nigeria.interfaces import MessageFactory as _
36
[15755]37GATEWAY_AMT = 300.0
38
[13581]39# Buttons
40
[15770]41def module_activated(session, payment):
42    if payment.r_company and payment.r_company != 'interswitch':
43        return False
[14755]44    try:
45        return getattr(grok.getSite()['configuration'][str(session)],
46            'interswitch_enabled', True)
47    except KeyError:
[16246]48        session = datetime.now().year
49        try:
50            return getattr(grok.getSite()['configuration'][str(session)],
51                'interswitch_enabled', True)
52        except KeyError:
53            return False
[14755]54
[9781]55class InterswitchActionButtonStudent(ManageActionButton):
56    grok.order(1)
57    grok.context(INigeriaOnlinePayment)
58    grok.view(OPDPStudent)
59    grok.require('waeup.payStudent')
60    icon = 'actionicon_pay.png'
[16484]61    text = _('Pay via Interswitch CollegePAY')
[9781]62    target = 'goto_interswitch'
63
64    @property
65    def target_url(self):
[15770]66        if not module_activated(
67            self.context.student.current_session, self.context):
[14755]68            return ''
[9781]69        if self.context.p_state != 'unpaid':
70            return ''
[16880]71        if self.context.amount_auth == 0:
72            return ''
[9781]73        return self.view.url(self.view.context, self.target)
74
75class InterswitchActionButtonApplicant(InterswitchActionButtonStudent):
76    grok.view(OPDPApplicant)
77    grok.require('waeup.payApplicant')
78
[14755]79    @property
80    def target_url(self):
[15770]81        if not module_activated(
82            self.context.__parent__.__parent__.year, self.context):
[14755]83            return ''
84        if self.context.p_state != 'unpaid':
85            return ''
[16880]86        if self.context.amount_auth == 0:
87            return ''
[14755]88        return self.view.url(self.view.context, self.target)
89
[9781]90class InterswitchRequestWebserviceActionButtonStudent(ManageActionButton):
91    grok.order(2)
92    grok.context(INigeriaOnlinePayment)
93    grok.view(OPDPStudent)
94    grok.require('waeup.payStudent')
95    icon = 'actionicon_call.png'
[16484]96    text = _('Requery CollegePAY History')
[9781]97    target = 'request_webservice'
98
99    @property
100    def target_url(self):
[15770]101        if not module_activated(
102            self.context.student.current_session, self.context):
[14755]103            return ''
[16881]104        if self.context.amount_auth == 0:
105            return ''
[15842]106        if self.context.p_state in ('paid', 'waived', 'scholarship'):
[9781]107            return ''
108        return self.view.url(self.view.context, self.target)
109
110class InterswitchRequestWebserviceActionButtonApplicant(
111    InterswitchRequestWebserviceActionButtonStudent):
112    grok.view(OPDPApplicant)
113    grok.require('waeup.payApplicant')
114
[14755]115    @property
116    def target_url(self):
[15770]117        if not module_activated(
118            self.context.__parent__.__parent__.year, self.context):
[14755]119            return ''
[16881]120        if self.context.amount_auth == 0:
121            return ''
[15842]122        if self.context.p_state in ('paid', 'waived', 'scholarship'):
[14755]123            return ''
124        return self.view.url(self.view.context, self.target)
125
[13581]126class InterswitchVerifyWebserviceActionButtonStudent(ManageActionButton):
127    grok.order(3)
128    grok.context(INigeriaOnlinePayment)
129    grok.view(OPDPStudent)
130    grok.require('waeup.manageStudent')
131    icon = 'actionicon_call.png'
132    text = _('Verify Payment')
133    target = 'verify_payment'
134
135    @property
136    def target_url(self):
[15770]137        if not module_activated(
138            self.context.student.current_session, self.context):
[14755]139            return ''
[13585]140        if self.context.p_state != 'paid' \
141            or self.context.r_company != u'interswitch':
[13581]142            return ''
143        return self.view.url(self.view.context, self.target)
144
145class InterswitchVerifyWebserviceActionButtonApplicant(
146    InterswitchVerifyWebserviceActionButtonStudent):
147    grok.view(OPDPApplicant)
148    grok.require('waeup.manageApplication')
149
[14755]150    @property
151    def target_url(self):
[15770]152        if not module_activated(
153            self.context.__parent__.__parent__.year, self.context):
[14755]154            return ''
155        if self.context.p_state != 'paid' \
156            or self.context.r_company != u'interswitch':
157            return ''
158        return self.view.url(self.view.context, self.target)
[13581]159
160# Webservice request views
161
[9781]162class InterswitchPaymentRequestWebservicePageStudent(UtilityView, grok.View):
163    """ Request webservice view for the CollegePAY gateway
164    """
165    grok.context(INigeriaStudentOnlinePayment)
166    grok.name('request_webservice')
167    grok.require('waeup.payStudent')
168
169    product_id = None
170    gateway_host = None
171    gateway_url = None
[13044]172    https = True
[13387]173    mac = None
[9781]174
175    def update(self):
[15770]176        if not module_activated(
177            self.context.student.current_session, self.context):
[14755]178            return
[15842]179        if self.context.p_state in ('paid', 'waived', 'scholarship'):
[13579]180            self.flash(_('This ticket has already been paid.'), type='danger')
[9781]181            return
182        student = self.context.student
183        success, msg, log = query_interswitch(
[11915]184            self.context, self.product_id,
185            self.gateway_host, self.gateway_url,
[13584]186            self.https, self.mac, False)
[9781]187        student.writeLogMessage(self, log)
188        if not success:
[11579]189            self.flash(msg, type='danger')
[9781]190            return
191        write_payments_log(student.student_id, self.context)
[11581]192        flashtype, msg, log = self.context.doAfterStudentPayment()
[9781]193        if log is not None:
194            student.writeLogMessage(self, log)
[11581]195        self.flash(msg, type=flashtype)
[9781]196        return
197
198    def render(self):
199        self.redirect(self.url(self.context, '@@index'))
200        return
201
202class InterswitchPaymentRequestWebservicePageApplicant(UtilityView, grok.View):
203    """ Request webservice view for the CollegePAY gateway
204    """
205    grok.context(INigeriaApplicantOnlinePayment)
206    grok.name('request_webservice')
207    grok.require('waeup.payApplicant')
208
209    product_id = None
210    gateway_host = None
211    gateway_url = None
[13044]212    https = True
[13387]213    mac = None
[9781]214
215    def update(self):
[15770]216        if not module_activated(
217            self.context.__parent__.__parent__.year, self.context):
[14755]218            return
[13580]219        if self.context.p_state == 'paid':
[11642]220            self.flash(_('This ticket has already been paid.'), type='danger')
[9781]221            return
222        applicant = self.context.__parent__
223        success, msg, log = query_interswitch(
[11915]224            self.context, self.product_id,
225            self.gateway_host, self.gateway_url,
[13584]226            self.https, self.mac, False)
[9781]227        applicant.writeLogMessage(self, log)
228        if not success:
[11579]229            self.flash(msg, type='danger')
[9781]230            return
231        write_payments_log(applicant.applicant_id, self.context)
[11581]232        flashtype, msg, log = self.context.doAfterApplicantPayment()
[9781]233        if log is not None:
234            applicant.writeLogMessage(self, log)
[11581]235        self.flash(msg, type=flashtype)
[9781]236        return
237
238    def render(self):
[15529]239        self.redirect(self.url(self.context.__parent__, 'edit'))
[9781]240        return
[11630]241
[13581]242class InterswitchPaymentVerifyWebservicePageStudent(UtilityView, grok.View):
243    """ Verify payment view for the CollegePAY gateway
244    """
245    grok.context(INigeriaStudentOnlinePayment)
246    grok.name('verify_payment')
247    grok.require('waeup.manageStudent')
248
249    product_id = None
250    gateway_host = None
251    gateway_url = None
252    https = True
253    mac = None
254
255    def update(self):
[15770]256        if not module_activated(
257            self.context.student.current_session, self.context):
[14755]258            return
[13585]259        if self.context.p_state  != 'paid' \
260            or self.context.r_company != u'interswitch':
[13581]261            self.flash(_('This ticket has not been paid.'), type='danger')
262            return
263        student = self.context.student
264        success, msg, log = query_interswitch(
265            self.context, self.product_id,
266            self.gateway_host, self.gateway_url,
[13584]267            self.https, self.mac, True)
[13581]268        student.writeLogMessage(self, log)
269        if not success:
270            self.flash(msg, type='danger')
271            return
272        self.flash(msg)
273        return
274
275    def render(self):
276        self.redirect(self.url(self.context, '@@index'))
277        return
278
279class InterswitchPaymentVerifyWebservicePageApplicant(UtilityView, grok.View):
280    """ Verify payment view for the CollegePAY gateway
281    """
282    grok.context(INigeriaApplicantOnlinePayment)
283    grok.name('verify_payment')
284    grok.require('waeup.manageApplication')
285
286    product_id = None
287    gateway_host = None
288    gateway_url = None
289    https = True
290    mac = None
291
292    def update(self):
[15770]293        if not module_activated(
294            self.context.__parent__.__parent__.year, self.context):
[14755]295            return
[13585]296        if self.context.p_state != 'paid' \
297            or self.context.r_company != u'interswitch':
[13581]298            self.flash(_('This ticket has not been paid.'), type='danger')
299            return
300        applicant = self.context.__parent__
301        success, msg, log = query_interswitch(
302            self.context, self.product_id,
303            self.gateway_host, self.gateway_url,
[13584]304            self.https, self.mac, True)
[13581]305        applicant.writeLogMessage(self, log)
306        if not success:
307            self.flash(msg, type='danger')
308            return
309        self.flash(msg)
310        return
311
312    def render(self):
313        self.redirect(self.url(self.context, '@@index'))
314        return
315
316# Forwarding pages
317
[11630]318class InterswitchPageStudent(KofaPage):
319    """ View which sends a POST request to the Interswitch
320    CollegePAY payment gateway.
321    """
322    grok.context(INigeriaOnlinePayment)
323    grok.name('goto_interswitch')
324    grok.template('student_goto_interswitch')
325    grok.require('waeup.payStudent')
[16484]326    label = _('Submit data to CollegePAY')
[11630]327    submit_button = _('Submit')
328
[11639]329    action = None
330    site_name = None
331    currency = None
332    pay_item_id = None
333    product_id = None
334    xml_data = None
[12477]335    hashvalue = None
[15755]336    gateway_amt = GATEWAY_AMT
[11639]337
[11642]338    def init_update(self):
[11630]339        if self.context.p_state == 'paid':
[11642]340            return _("Payment ticket can't be re-sent to CollegePAY.")
[13478]341        now = datetime.utcnow()
342        if self.context.creation_date.tzinfo is not None:
343            # That's bad. Please store timezone-naive datetimes only!
344            now = self.context.creation_date.tzinfo.localize(now)
345        time_delta = now - self.context.creation_date
[13015]346        if time_delta.days > 7:
[12973]347            return _("This payment ticket is too old. Please create a new ticket.")
[15755]348        if self.context.r_company and self.context.r_company != 'interswitch':
349            return _("Payment ticket has been used for another payment gateway.")
[11642]350        student = self.context.student
[11630]351        certificate = getattr(student['studycourse'],'certificate',None)
352        if certificate is None:
[11642]353            return _("Study course data are incomplete.")
[11639]354        kofa_utils = getUtility(IKofaUtils)
[11642]355        student_utils = getUtility(IStudentsUtils)
356        if student_utils.samePaymentMade(student, self.context.p_category,
357            self.context.p_item, self.context.p_session):
358            return _("This type of payment has already been made.")
[11630]359        xmldict = {}
360        if certificate is not None:
361            xmldict['department'] = certificate.__parent__.__parent__.code
362            xmldict['faculty'] = certificate.__parent__.__parent__.__parent__.code
363        else:
364            xmldict['department'] = None
365            xmldict['faculty'] = None
[12509]366        self.category = self.context.category
[11639]367        tz = kofa_utils.tzinfo
[11630]368        self.local_date_time = to_timezone(
369            self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z")
370        self.site_redirect_url = self.url(self.context, 'request_webservice')
[11642]371        self.student = student
372        self.xmldict = xmldict
373        return
[11630]374
[11642]375    def update(self):
[15770]376        if not module_activated(
377            self.context.student.current_session, self.context):
[15974]378            self.flash(_('Forbidden'), type='danger')
379            self.redirect(self.url(self.context, '@@index'))
[14755]380            return
[11642]381        error = self.init_update()
382        if error:
383            self.flash(error, type='danger')
384            self.redirect(self.url(self.context, '@@index'))
[15755]385        # Already now it becomes an Interswitch payment. We set the net amount
386        # and add the gateway amount.
387        if not self.context.r_company:
388            self.context.net_amt = self.context.amount_auth
389            self.context.amount_auth += self.gateway_amt
390            self.context.gateway_amt = self.gateway_amt
391            self.context.r_company = u'interswitch'
392        self.amount_auth = int(100 * self.context.amount_auth)
[11642]393        return
394
[11630]395class InterswitchPageApplicant(KofaPage):
396    """ View which sends a POST request to the Interswitch
397    CollegePAY payment gateway.
398    """
399    grok.context(INigeriaApplicantOnlinePayment)
400    grok.require('waeup.payApplicant')
401    grok.template('applicant_goto_interswitch')
402    grok.name('goto_interswitch')
[16484]403    label = _('Submit data to CollegePAY')
[11630]404    submit_button = _('Submit')
405
[11639]406    action = None
407    site_name = None
408    currency = None
409    pay_item_id = None
410    product_id = None
411    xml_data = None
[15755]412    hashvalue = None
413    gateway_amt = GATEWAY_AMT
[11639]414
[11642]415    def init_update(self):
[11630]416        if self.context.p_state != 'unpaid':
[11642]417            return _("Payment ticket can't be re-sent to CollegePAY.")
[11630]418        if self.context.__parent__.__parent__.expired \
419            and self.context.__parent__.__parent__.strict_deadline:
[16247]420            return _("Payment ticket can't be sent to CollegePAY. "
[11642]421                     "Application period has expired.")
[15755]422        if self.context.r_company and self.context.r_company != 'interswitch':
423            return _("Payment ticket has been used for another payment gateway.")
[12973]424        tz = getUtility(IKofaUtils).tzinfo
425        time_delta = datetime.utcnow() - self.context.creation_date
[13015]426        if time_delta.days > 7:
[12973]427            return _("This payment ticket is too old. Please create a new ticket.")
[11630]428        self.applicant = self.context.__parent__
[12509]429        self.category = self.context.category
[11630]430        tz = getUtility(IKofaUtils).tzinfo
431        self.local_date_time = to_timezone(
432            self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z")
433        self.site_redirect_url = self.url(self.context, 'request_webservice')
[11642]434        return
435
436    def update(self):
[15770]437        if not module_activated(
438            self.context.__parent__.__parent__.year, self.context):
[15974]439            self.flash(_('Forbidden'), type='danger')
440            self.redirect(self.url(self.context, '@@index'))
[14755]441            return
[11642]442        error = self.init_update()
443        if error:
444            self.flash(error, type='danger')
445            self.redirect(self.url(self.context, '@@index'))
[15755]446        # Already now it becomes an Interswitch payment. We set the net amount
447        # and add the gateway amount.
448        if not self.context.r_company:
449            self.context.net_amt = self.context.amount_auth
450            self.context.amount_auth += self.gateway_amt
451            self.context.gateway_amt = self.gateway_amt
452            self.context.r_company = u'interswitch'
453        self.amount_auth = int(100 * self.context.amount_auth)
[13478]454        return
[16484]455
Note: See TracBrowser for help on using the repository browser.