## $Id: studentsbrowser.py 15599 2019-09-20 13:24:59Z henrik $ ## ## Copyright (C) 2017 Uli Fouquet & Henrik Bettermann ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## import grok import hashlib from datetime import datetime, timedelta from zope.component import getUtility from zope.security import checkPermission from waeup.kofa.interfaces import IKofaUtils from waeup.kofa.utils.helpers import to_timezone from waeup.kofa.browser.layout import UtilityView, KofaPage, KofaEditFormPage, action, NullValidator from waeup.kofa.browser.viewlets import ManageActionButton from kofacustom.nigeria.etranzact.helpers import ( write_payments_log, initiate_payment, query_credo_payment) from kofacustom.nigeria.students.browser import NigeriaOnlinePaymentDisplayFormPage as NOPDPStudent from kofacustom.nigeria.applicants.browser import NigeriaOnlinePaymentDisplayFormPage as NOPDPApplicant from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment from kofacustom.nigeria.interfaces import MessageFactory as _ from kofacustom.nigeria.etranzact.tests import ( TERMINAL_ID, CREDO_HOST, HTTPS, SECRET_API_KEY, API_PUBLIC_KEY, LOGO_URL, GATEWAY_AMT) grok.templatedir('browser_templates') def credo_module_activated(session, payment): if payment.p_currency != 'NGN': return False if payment.r_company and payment.r_company != 'etranzact': return False try: return getattr(grok.getSite()['configuration'][str(session)], 'etranzact_credo_enabled', False) except KeyError: session = datetime.now().year try: return getattr(grok.getSite()['configuration'][str(session)], 'etranzact_credo_enabled', False) except KeyError: return False class CredoActionButtonStudent(ManageActionButton): grok.order(8) grok.context(INigeriaOnlinePayment) grok.view(NOPDPStudent) grok.require('waeup.payStudent') icon = 'actionicon_pay.png' text = _('Pay via Etranzact Credo') target = 'goto_credo' @property def target_url(self): if not credo_module_activated( self.context.student.current_session, self.context): return '' if self.context.p_state != 'unpaid': return '' return self.view.url(self.view.context, self.target) class CredoActionButtonApplicant(CredoActionButtonStudent): grok.context(INigeriaOnlinePayment) grok.require('waeup.payApplicant') grok.view(NOPDPApplicant) @property def target_url(self): if not credo_module_activated( self.context.__parent__.__parent__.year, self.context): return '' if self.context.p_state != 'unpaid': return '' return self.view.url(self.view.context, self.target) class CredoVerifyActionButtonStudent(ManageActionButton): grok.order(9) grok.context(INigeriaOnlinePayment) grok.view(NOPDPStudent) grok.require('waeup.payStudent') icon = 'actionicon_call.png' text = _('Requery Etranzact Credo') target = 'requery_credo' @property def target_url(self): if not credo_module_activated( self.context.student.current_session, self.context): return '' if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'): return '' return self.view.url(self.view.context, self.target) class CredoVerifyActionButtonApplicant(CredoVerifyActionButtonStudent): grok.view(NOPDPApplicant) grok.require('waeup.payApplicant') icon = 'actionicon_call.png' text = _('Requery Etranzact Credo') target = 'requery_credo' @property def target_url(self): if not credo_module_activated( self.context.__parent__.__parent__.year, self.context): return '' if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'): return '' return self.view.url(self.view.context, self.target) class CredoPageStudent(KofaEditFormPage): """ View which sends a POST request to the Credo payment gateway. """ grok.context(INigeriaStudentOnlinePayment) grok.name('goto_credo') grok.template('goto_credo') grok.require('waeup.payStudent') label = _('Pay via Credo') submit_button = _('Pay now') host = CREDO_HOST api_public_key = API_PUBLIC_KEY gateway_amt = 0.0 # is being added by Etranzact serviceCode = None def init_update(self): if self.context.p_state == 'paid': return _("Payment ticket can't be re-sent to Etranzact.") now = datetime.utcnow() if self.context.creation_date.tzinfo is not None: # That's bad. Please store timezone-naive datetimes only! now = self.context.creation_date.tzinfo.localize(now) time_delta = now - self.context.creation_date if time_delta.days > 7: return _("This payment ticket is too old. Please create a new ticket.") self.callbackUrl = self.url(self.context, 'requery_credo') return def update(self): if not credo_module_activated( self.context.student.current_session, self.context): self.flash(_('Forbidden'), type='danger') self.redirect(self.url(self.context, '@@index')) return # Already now it becomes an Etranzact payment. We set the net amount # and add the gateway amount. if not self.context.r_company: self.context.net_amt = self.context.amount_auth #self.context.amount_auth += self.gateway_amt #self.context.gateway_amt = self.gateway_amt self.context.r_company = u'etranzact' #self.amount = "%.1f" % (100.0 * self.context.amount_auth) error = self.init_update() self.customer = self.context.student if error: self.flash(error, type='danger') self.redirect(self.url(self.context, '@@index')) return return @action(_('Pay now'), validator=NullValidator, style='primary') def pay(self, **data): if not self.serviceCode: self.flash('Payment via Credo not possible.', type='danger') self.redirect(self.url(self.context, '@@index')) return success, url_or_message = initiate_payment( self.context, self.host, self.callbackUrl, self.api_public_key, self.serviceCode) if success: self.redirect(url_or_message, trusted=True) else: self.flash(url_or_message, type='danger') self.redirect(self.url(self.context, '@@index')) return class CredoPageApplicant(CredoPageStudent): """ View which sends a POST request to the Credo payment gateway. """ grok.require('waeup.payApplicant') grok.context(INigeriaApplicantOnlinePayment) def update(self): if not credo_module_activated( self.context.__parent__.__parent__.year, self.context): self.flash(_('Forbidden'), type='danger') self.redirect(self.url(self.context, '@@index')) return # Already now it becomes an Etranzact payment. We set the net amount # and add the gateway amount. if not self.context.r_company: self.context.net_amt = self.context.amount_auth #self.context.amount_auth += self.gateway_amt #self.context.gateway_amt = self.gateway_amt self.context.r_company = u'etranzact' #self.amount = "%.1f" % (100.0 * self.context.amount_auth) error = self.init_update() self.customer = self.context.__parent__ if error: self.flash(error, type='danger') self.redirect(self.url(self.context, '@@index')) return return class CredoVerifyPaymentStatusPageStudent(UtilityView, grok.View): """ Request webservice view for the Etranzact Credo gateway. """ grok.context(INigeriaStudentOnlinePayment) grok.name('requery_credo') grok.require('waeup.payStudent') host = CREDO_HOST secret_api_key = SECRET_API_KEY def update(self): if not credo_module_activated( self.context.student.current_session, self.context): self.flash(_('Forbidden'), type='danger') self.redirect(self.url(self.context, '@@index')) return if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'): self.flash(_('This ticket has already been processed.'), type='danger') return student = self.context.student #verify = False success, msg, log = query_credo_payment(self.context, self.host, self.secret_api_key) student.writeLogMessage(self, log) if not success: self.flash(msg, type='danger') return write_payments_log(student.student_id, self.context) flashtype, msg, log = self.context.doAfterStudentPayment() if log is not None: student.writeLogMessage(self, log) self.flash(msg, type=flashtype) return def render(self): self.redirect(self.url(self.context)) return class CredoVerifyPaymentStatusPageApplicant(CredoVerifyPaymentStatusPageStudent): """ Request webservice view for the Etranzact Credo gateway. """ grok.context(INigeriaApplicantOnlinePayment) grok.name('requery_credo') grok.require('waeup.payApplicant') def update(self): if not credo_module_activated( self.context.__parent__.__parent__.year, self.context): self.flash(_('Forbidden'), type='danger') self.redirect(self.url(self.context, '@@index')) return if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'): self.flash(_('This ticket has already been processed.'), type='danger') return applicant = self.context.__parent__ #verify = False success, msg, log = query_credo_payment(self.context, self.host, self.secret_api_key) applicant.writeLogMessage(self, log) if not success: self.flash(msg, type='danger') return write_payments_log(applicant.applicant_id, self.context) flashtype, msg, log = self.context.doAfterApplicantPayment() if log is not None: applicant.writeLogMessage(self, log) self.flash(msg, type=flashtype) return