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
Line 
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
19from datetime import datetime, timedelta
20from zope.component import getUtility
21from zope.security import checkPermission
22from waeup.kofa.interfaces import IKofaUtils
23from waeup.kofa.utils.helpers import to_timezone
24from waeup.kofa.browser.layout import UtilityView, KofaPage, KofaFormPage, action
25from waeup.kofa.browser.viewlets import ManageActionButton
26from waeup.kofa.students.interfaces import IStudentsUtils
27from waeup.kofa.students.browser import OnlinePaymentDisplayFormPage as OPDPStudent
28from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
29from kofacustom.nigeria.interswitch.helpers import (
30    query_interswitch, write_payments_log, fetch_booking_details)
31from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
32from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
33from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
34from kofacustom.nigeria.interswitch.tests import PAYDIRECT_URL, PAYDIRECT_HOST, MERCHANT_ID
35from kofacustom.nigeria.interfaces import MessageFactory as _
36
37GATEWAY_AMT = 300.0
38
39# Buttons
40
41def module_activated(session, payment):
42    if payment.r_company and payment.r_company != 'interswitch':
43        return False
44    try:
45        return getattr(grok.getSite()['configuration'][str(session)],
46            'interswitch_enabled', True)
47    except KeyError:
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
54
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'
61    text = _('Pay via Interswitch CollegePAY')
62    target = 'goto_interswitch'
63
64    @property
65    def target_url(self):
66        if not module_activated(
67            self.context.student.current_session, self.context):
68            return ''
69        if self.context.p_state != 'unpaid':
70            return ''
71        if self.context.amount_auth == 0:
72            return ''
73        return self.view.url(self.view.context, self.target)
74
75class InterswitchActionButtonApplicant(InterswitchActionButtonStudent):
76    grok.view(OPDPApplicant)
77    grok.require('waeup.payApplicant')
78
79    @property
80    def target_url(self):
81        if not module_activated(
82            self.context.__parent__.__parent__.year, self.context):
83            return ''
84        if self.context.p_state != 'unpaid':
85            return ''
86        if self.context.amount_auth == 0:
87            return ''
88        return self.view.url(self.view.context, self.target)
89
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'
96    text = _('Requery CollegePAY History')
97    target = 'request_webservice'
98
99    @property
100    def target_url(self):
101        if not module_activated(
102            self.context.student.current_session, self.context):
103            return ''
104        if self.context.amount_auth == 0:
105            return ''
106        if self.context.p_state in ('paid', 'waived', 'scholarship'):
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
115    @property
116    def target_url(self):
117        if not module_activated(
118            self.context.__parent__.__parent__.year, self.context):
119            return ''
120        if self.context.amount_auth == 0:
121            return ''
122        if self.context.p_state in ('paid', 'waived', 'scholarship'):
123            return ''
124        return self.view.url(self.view.context, self.target)
125
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):
137        if not module_activated(
138            self.context.student.current_session, self.context):
139            return ''
140        if self.context.p_state != 'paid' \
141            or self.context.r_company != u'interswitch':
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
150    @property
151    def target_url(self):
152        if not module_activated(
153            self.context.__parent__.__parent__.year, self.context):
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)
159
160# Webservice request views
161
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
172    https = True
173    mac = None
174
175    def update(self):
176        if not module_activated(
177            self.context.student.current_session, self.context):
178            return
179        if self.context.p_state in ('paid', 'waived', 'scholarship'):
180            self.flash(_('This ticket has already been paid.'), type='danger')
181            return
182        student = self.context.student
183        success, msg, log = query_interswitch(
184            self.context, self.product_id,
185            self.gateway_host, self.gateway_url,
186            self.https, self.mac, False)
187        student.writeLogMessage(self, log)
188        if not success:
189            self.flash(msg, type='danger')
190            return
191        write_payments_log(student.student_id, self.context)
192        flashtype, msg, log = self.context.doAfterStudentPayment()
193        if log is not None:
194            student.writeLogMessage(self, log)
195        self.flash(msg, type=flashtype)
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
212    https = True
213    mac = None
214
215    def update(self):
216        if not module_activated(
217            self.context.__parent__.__parent__.year, self.context):
218            return
219        if self.context.p_state == 'paid':
220            self.flash(_('This ticket has already been paid.'), type='danger')
221            return
222        applicant = self.context.__parent__
223        success, msg, log = query_interswitch(
224            self.context, self.product_id,
225            self.gateway_host, self.gateway_url,
226            self.https, self.mac, False)
227        applicant.writeLogMessage(self, log)
228        if not success:
229            self.flash(msg, type='danger')
230            return
231        write_payments_log(applicant.applicant_id, self.context)
232        flashtype, msg, log = self.context.doAfterApplicantPayment()
233        if log is not None:
234            applicant.writeLogMessage(self, log)
235        self.flash(msg, type=flashtype)
236        return
237
238    def render(self):
239        self.redirect(self.url(self.context.__parent__, 'edit'))
240        return
241
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):
256        if not module_activated(
257            self.context.student.current_session, self.context):
258            return
259        if self.context.p_state  != 'paid' \
260            or self.context.r_company != u'interswitch':
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,
267            self.https, self.mac, True)
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):
293        if not module_activated(
294            self.context.__parent__.__parent__.year, self.context):
295            return
296        if self.context.p_state != 'paid' \
297            or self.context.r_company != u'interswitch':
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,
304            self.https, self.mac, True)
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
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')
326    label = _('Submit data to CollegePAY')
327    submit_button = _('Submit')
328
329    action = None
330    site_name = None
331    currency = None
332    pay_item_id = None
333    product_id = None
334    xml_data = None
335    hashvalue = None
336    gateway_amt = GATEWAY_AMT
337
338    def init_update(self):
339        if self.context.p_state == 'paid':
340            return _("Payment ticket can't be re-sent to CollegePAY.")
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
346        if time_delta.days > 7:
347            return _("This payment ticket is too old. Please create a new ticket.")
348        if self.context.r_company and self.context.r_company != 'interswitch':
349            return _("Payment ticket has been used for another payment gateway.")
350        student = self.context.student
351        certificate = getattr(student['studycourse'],'certificate',None)
352        if certificate is None:
353            return _("Study course data are incomplete.")
354        kofa_utils = getUtility(IKofaUtils)
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.")
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
366        self.category = self.context.category
367        tz = kofa_utils.tzinfo
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')
371        self.student = student
372        self.xmldict = xmldict
373        return
374
375    def update(self):
376        if not module_activated(
377            self.context.student.current_session, self.context):
378            self.flash(_('Forbidden'), type='danger')
379            self.redirect(self.url(self.context, '@@index'))
380            return
381        error = self.init_update()
382        if error:
383            self.flash(error, type='danger')
384            self.redirect(self.url(self.context, '@@index'))
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)
393        return
394
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')
403    label = _('Submit data to CollegePAY')
404    submit_button = _('Submit')
405
406    action = None
407    site_name = None
408    currency = None
409    pay_item_id = None
410    product_id = None
411    xml_data = None
412    hashvalue = None
413    gateway_amt = GATEWAY_AMT
414
415    def init_update(self):
416        if self.context.p_state != 'unpaid':
417            return _("Payment ticket can't be re-sent to CollegePAY.")
418        if self.context.__parent__.__parent__.expired \
419            and self.context.__parent__.__parent__.strict_deadline:
420            return _("Payment ticket can't be sent to CollegePAY. "
421                     "Application period has expired.")
422        if self.context.r_company and self.context.r_company != 'interswitch':
423            return _("Payment ticket has been used for another payment gateway.")
424        tz = getUtility(IKofaUtils).tzinfo
425        time_delta = datetime.utcnow() - self.context.creation_date
426        if time_delta.days > 7:
427            return _("This payment ticket is too old. Please create a new ticket.")
428        self.applicant = self.context.__parent__
429        self.category = self.context.category
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')
434        return
435
436    def update(self):
437        if not module_activated(
438            self.context.__parent__.__parent__.year, self.context):
439            self.flash(_('Forbidden'), type='danger')
440            self.redirect(self.url(self.context, '@@index'))
441            return
442        error = self.init_update()
443        if error:
444            self.flash(error, type='danger')
445            self.redirect(self.url(self.context, '@@index'))
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)
454        return
455
Note: See TracBrowser for help on using the repository browser.