source: main/waeup.uniben/trunk/src/waeup/uniben/interswitch/tests.py @ 13778

Last change on this file since 13778 was 13771, checked in by Henrik Bettermann, 9 years ago

Implement TSA settlement through First Bank.

  • Property svn:keywords set to Id
File size: 23.6 KB
Line 
1## $Id: tests.py 13771 2016-03-09 10:05:00Z 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 os
19from datetime import datetime, date, timedelta
20from zope.component import createObject, getUtility
21from zope.catalog.interfaces import ICatalog
22from hurry.workflow.interfaces import IWorkflowState
23from waeup.kofa.students.tests.test_browser import StudentsFullSetup
24from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup
25from waeup.uniben.configuration import CustomSessionConfiguration
26from waeup.uniben.testing import FunctionalLayer
27
28# Also run tests that send requests to external servers?
29#   If you enable this, please make sure the external services
30#   do exist really and are not bothered by being spammed by a test programme.
31EXTERNAL_TESTS = False
32
33SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
34
35def external_test(func):
36    if not EXTERNAL_TESTS:
37        myself = __file__
38        if myself.endswith('.pyc'):
39            myself = myself[:-2]
40        print "WARNING: external tests are skipped!"
41        print "WARNING: edit %s to enable them." % myself
42        return
43    return func
44
45
46class InterswitchTestsStudents(StudentsFullSetup):
47    """Tests for the Interswitch payment gateway.
48    """
49
50    layer = FunctionalLayer
51
52    def setUp(self):
53        super(InterswitchTestsStudents, self).setUp()
54        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
55        self.browser.open(self.payments_path)
56        IWorkflowState(self.student).setState('cleared')
57        self.student.nationality = u'NG'
58        self.browser.open(self.payments_path + '/addop')
59        self.browser.getControl(name="form.p_category").value = ['schoolfee']
60        self.browser.getControl("Create ticket").click()
61        self.assertMatches('...ticket created...',
62                           self.browser.contents)
63        ctrl = self.browser.getControl(name='val_id')
64        self.value = ctrl.options[0]
65        self.browser.getLink(self.value).click()
66        self.assertMatches('...Amount Authorized...',
67                           self.browser.contents)
68        self.assertTrue(
69            '<span>40000.0</span>' in self.browser.contents)
70        self.payment_url = self.browser.url
71
72#    def callback_url(self, payment_url, resp, apprAmt):
73#        return payment_url + (
74#            '/isw_callback?echo=' +
75#            '&resp=%s' +
76#            '&desc=Something went wrong' +
77#            '&txnRef=p1331792385335' +
78#            '&payRef=' + '&retRef=' +
79#            '&cardNum=0' +
80#            '&apprAmt=%s' +
81#            '&url=http://xyz') % (resp, apprAmt)
82
83    def test_interswitch_form(self):
84        # Manager can access InterswitchForm
85        self.browser.getLink("CollegePAY", index=0).click()
86        # The total amount to be processed by Interswitch
87        # has been reduced by the Interswitch fee of 150 Nairas
88        self.assertTrue('<input type="hidden" name="pay_item_id" value="5700" />'
89                           in self.browser.contents)
90        self.assertTrue('Total Amount Authorized:'
91                           in self.browser.contents)
92        self.assertEqual(self.student.current_mode, 'ug_ft')
93        self.assertTrue(
94            '<input type="hidden" name="amount" value="4000000" />'
95            in self.browser.contents)
96        self.assertTrue(
97            'item_name="School Fee" item_amt="3835000" bank_id="8" acct_num="2017506430"'
98            in self.browser.contents)
99        self.assertTrue(
100            'item_name="BT Education" item_amt="150000" bank_id="117" acct_num="1010764827"'
101            in self.browser.contents)
102
103        # Create school fee ticket for returning students. Payment is made
104        # for next session.
105        current_payment_key = self.student['payments'].keys()[0]
106        self.certificate.study_mode = u'ug_pt'
107        IWorkflowState(self.student).setState('returning')
108        configuration = createObject('waeup.SessionConfiguration')
109        configuration.academic_session = 2005
110        self.app['configuration'].addSessionConfiguration(configuration)
111        self.browser.open(self.payments_path + '/addop')
112        self.browser.getControl(name="form.p_category").value = ['schoolfee']
113        self.browser.getControl("Create ticket").click()
114
115        ## Next session payment can't be made ...
116        #self.assertMatches(
117        #    '...You have not yet paid your current/active session...',
118        #    self.browser.contents)
119        ## current session payment must be approved first.
120        #self.student['payments'][current_payment_key].approve()
121        #self.browser.open(self.payments_path + '/addop')
122        #self.browser.getControl(name="form.p_category").value = ['schoolfee']
123        #self.browser.getControl("Create ticket").click()
124
125        ctrl = self.browser.getControl(name='val_id')
126        value = ctrl.options[1]
127        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
128        self.assertEqual(self.student['payments'][value].gateway_amt, 0.0)
129        self.browser.getLink(value).click()
130        self.browser.getLink("CollegePAY", index=0).click()
131        # Split amounts have been set.
132        self.assertEqual(self.student['payments'][value].provider_amt, 1500.0)
133        self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
134        self.assertTrue('<input type="hidden" name="pay_item_id" value="5701" />'
135                           in self.browser.contents)
136        self.assertTrue(
137            '<input type="hidden" name="amount" value="2000000" />'
138            in self.browser.contents)
139        self.assertTrue(
140            'item_name="School Fee" item_amt="1835000" bank_id="8" acct_num="2017506430"'
141            in self.browser.contents)
142        self.assertTrue(
143            'item_name="BT Education" item_amt="150000" bank_id="117" acct_num="1010764827"'
144            in self.browser.contents)
145
146        # Create clearance fee ticket
147        #self.browser.open(self.payments_path + '/addop')
148        #self.browser.getControl(name="form.p_category").value = ['clearance']
149        #self.browser.getControl("Create ticket").click()
150        #ctrl = self.browser.getControl(name='val_id')
151        #value = ctrl.options[2]
152        #self.browser.getLink(value).click()
153        #self.assertMatches(
154        #    '...<span>45000.0</span>...',
155        #    self.browser.contents)
156        ## Manager can access InterswitchForm
157        #self.browser.getLink("CollegePAY", index=0).click()
158        #self.assertEqual(self.student['payments'][value].provider_amt, 1500.0)
159        #self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
160        #self.assertMatches('...<input type="hidden" name="pay_item_id" value="5702" />...',
161        #                   self.browser.contents)
162        #self.assertMatches('...Total Amount Authorized:...',
163        #                   self.browser.contents)
164        #self.assertMatches(
165        #    '...<input type="hidden" name="amount" value="4500000.0" />...',
166        #    self.browser.contents)
167        #self.assertMatches(
168        #    '...item_name="Acceptance Fee" item_amt="4335000" bank_id="7" acct_num="1003475516"...',
169        #    self.browser.contents)
170        #self.assertMatches(
171        #    '...item_name="BT Education" item_amt="150000" bank_id="117" acct_num="1010764827"...',
172        #    self.browser.contents)
173
174        # Create gown fee ticket
175        configuration.maint_fee = 987.0
176        self.app['configuration']['2004'].gown_fee = 234.0
177        self.browser.open(self.payments_path + '/addop')
178        self.browser.getControl(name="form.p_category").value = ['gown']
179        self.browser.getControl("Create ticket").click()
180        ctrl = self.browser.getControl(name='val_id')
181        value = ctrl.options[2]
182        self.browser.getLink(value).click()
183        self.assertTrue(
184            '<span>234.0</span>',
185            self.browser.contents)
186        # Manager can access InterswitchForm
187        self.browser.getLink("CollegePAY", index=0).click()
188        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
189        self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
190        self.assertTrue('<input type="hidden" name="pay_item_id" value="5704" />'
191                           in self.browser.contents)
192        self.assertTrue('Total Amount Authorized:'
193                           in self.browser.contents)
194        self.assertTrue(
195            '<input type="hidden" name="amount" value="23400" />'
196            in self.browser.contents)
197        self.assertTrue(
198            '<item_detail item_id="1" item_name="Gown Hire Fee" item_amt="8400" bank_id="8" acct_num="2017506430" />'
199            in self.browser.contents)
200        self.assertFalse(
201            'item_name="BT Education"' in self.browser.contents)
202
203        # Create hostel application ticket
204        #self.browser.open(self.payments_path + '/addop')
205        #self.browser.getControl(name="form.p_category").value = ['hostel_application']
206        #self.browser.getControl("Create ticket").click()
207        #ctrl = self.browser.getControl(name='val_id')
208        #value = ctrl.options[3]
209        #self.browser.getLink(value).click()
210        #self.assertTrue(
211        #    '<span>1000.0</span>' in self.browser.contents)
212        #self.student['payments'][value].approve()
213
214        # Create temp maint fee ticket
215        #self.browser.open(self.payments_path + '/addop')
216        #self.browser.getControl(name="form.p_category").value = ['tempmaint_1']
217        #self.browser.getControl("Create ticket").click()
218        #ctrl = self.browser.getControl(name='val_id')
219        #value = ctrl.options[4]
220        #self.browser.getLink(value).click()
221        #self.assertTrue(
222        #    '<span>8150.0</span>' in self.browser.contents)
223        # Manager can access InterswitchForm
224        #self.browser.getLink("CollegePAY", index=0).click()
225        #self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
226        #self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
227        #self.assertTrue('<input type="hidden" name="pay_item_id" value="5705" />'
228        #                 in self.browser.contents)
229        #self.assertMatches('...Total Amount Authorized:...',
230        #                   self.browser.contents)
231        #self.assertTrue(
232        #    '<input type="hidden" name="amount" value="815000" />'
233        #    in self.browser.contents)
234        #self.assertTrue(
235        #    '<item_detail item_id="1" item_name="Hostel Maintenance Fee" item_amt="800000" bank_id="129" acct_num="0014419432" />'
236        #    in self.browser.contents)
237        #self.assertFalse(
238        #    'item_name="BT Education"' in self.browser.contents)
239
240        # Create previous session fee ticket
241        configuration = createObject('waeup.SessionConfiguration')
242        configuration.academic_session = 2003
243        configuration.clearance_fee = 3456.0
244        self.app['configuration'].addSessionConfiguration(configuration)
245        self.student['studycourse'].entry_session = 2002
246        #self.browser.open(self.payments_path + '/addpp')
247        #self.browser.getControl(name="form.p_category").value = ['clearance']
248        #self.browser.getControl(name="form.p_session").value = ['2003']
249        #self.browser.getControl(name="form.p_level").value = ['300']
250        #self.browser.getControl("Create ticket").click()
251        #ctrl = self.browser.getControl(name='val_id')
252        #value = ctrl.options[5]
253        #self.browser.getLink(value).click()
254        #self.assertMatches(
255        #    '...<span>45000.0</span>...',
256        #    self.browser.contents)
257        ## Manager can access InterswitchForm
258        #self.browser.getLink("CollegePAY", index=0).click()
259        #self.assertEqual(self.student['payments'][value].provider_amt, 1500.0)
260        #self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
261        #self.assertMatches('...<input type="hidden" name="pay_item_id" value="5702" />...',
262        #                   self.browser.contents)
263        #self.assertMatches('...Total Amount Authorized:...',
264        #                   self.browser.contents)
265        ##self.assertMatches(
266        #    '...<input type="hidden" name="amount" value="4500000.0" />...',
267        #    self.browser.contents)
268        #self.assertMatches(
269        #    '...<item_detail item_id="1" item_name="Acceptance Fee" item_amt="4335000" bank_id="7" acct_num="1003475516" />...',
270        #    self.browser.contents)
271
272        # Create balance payment ticket
273        self.browser.open(self.payments_path + '/addbp')
274        self.browser.getControl(name="form.p_category").value = ['schoolfee']
275        self.browser.getControl(name="form.balance_session").value = ['2003']
276        self.browser.getControl(name="form.balance_level").value = ['300']
277        self.browser.getControl(name="form.balance_amount").value = '200'
278        self.browser.getControl("Create ticket").click()
279        ctrl = self.browser.getControl(name='val_id')
280        value = ctrl.options[3]
281        self.browser.getLink(value).click()
282        self.assertTrue(
283            '<span>200.0</span>' in self.browser.contents)
284        # Manager can access InterswitchForm
285        self.browser.getLink("CollegePAY", index=0).click()
286        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
287        self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)
288        self.assertTrue('<input type="hidden" name="pay_item_id" value="5701" />'
289                           in self.browser.contents)
290        self.assertTrue(
291            '<input type="hidden" name="amount" value="20000" />'
292            in self.browser.contents)
293        self.assertTrue(
294            'item_name="School Fee" item_amt="5000" bank_id="8" acct_num="2017506430"'
295            in self.browser.contents)
296        self.assertFalse(
297            'item_name="BT Education"' in self.browser.contents)
298
299#    @external_test
300#    def test_callback(self):
301
302        # Manager can call callback manually
303#        self.browser.open(self.callback_url(self.payment_url, 'XX', '300'))
304#        self.assertMatches('...Unsuccessful callback: Something went wrong...',
305#                          self.browser.contents)
306#        self.assertMatches('...Failed...',
307#                           self.browser.contents)
308#        self.browser.open(self.payment_url + '/isw_callback')
309#        self.assertMatches('...Unsuccessful callback: Incomplete query string...',
310#                          self.browser.contents)
311#        self.assertMatches('...Failed...',
312#                           self.browser.contents)
313#        self.browser.open(self.callback_url(self.payment_url, '00', '300000'))
314#        self.assertMatches('...Wrong amount...',
315#                          self.browser.contents)
316#        self.browser.open(self.callback_url(self.payment_url, '00', '4000000'))
317#        self.assertMatches('...Valid callback received...',
318#                          self.browser.contents)
319
320    def test_interswitch_form_ticket_expired(self):
321        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
322        acc_payment = createObject('waeup.StudentOnlinePayment')
323        acc_payment.p_state = 'unpaid'
324        acc_payment.p_category = 'clearance'
325        acc_payment.p_id = 'xyz'
326        acc_payment.pay_item_id = '123'
327        acc_payment.amount_auth = 876.0
328        self.student['payments']['xyz'] = acc_payment
329        self.browser.open(self.payments_path + '/xyz')
330        self.browser.getLink("CollegePAY", index=0).click()
331        self.assertTrue('<input type="hidden" name="pay_item_id" value="5702" />'
332                           in self.browser.contents)
333        self.assertTrue('Total Amount Authorized:'
334                           in self.browser.contents)
335        self.assertEqual(self.student.current_mode, 'ug_ft')
336        self.assertTrue(
337            '<input type="hidden" name="amount" value="87600" />'
338            in self.browser.contents)
339        delta = timedelta(days=8)
340        acc_payment.creation_date -= delta
341        self.browser.open(self.payments_path + '/xyz')
342        self.browser.getLink("CollegePAY", index=0).click()
343        self.assertMatches(
344            '...This payment ticket is too old. Please create a new ticket...',
345            self.browser.contents)
346        delta = timedelta(days=2)
347        acc_payment.creation_date += delta
348        self.browser.open(self.payments_path + '/xyz')
349        self.browser.getLink("CollegePAY", index=0).click()
350        self.assertMatches('...Total Amount Authorized:...',
351                           self.browser.contents)
352
353    def test_pay_twice(self):
354        # Create second ticket
355        self.browser.open(self.payments_path + '/addop')
356        self.browser.getControl(name="form.p_category").value = ['schoolfee']
357        self.browser.getControl("Create ticket").click()
358        # Pay first ticket
359        self.student['payments'][self.value].approve()
360        # Try to pay second ticket
361        self.browser.open(self.payments_path)
362        ctrl = self.browser.getControl(name='val_id')
363        value = ctrl.options[1]
364        self.browser.getLink(value).click()
365        self.browser.getLink("CollegePAY", index=0).click()
366        self.assertMatches(
367            '...alert alert-danger">This type of payment has already been made...',
368            self.browser.contents)
369
370    @external_test
371    def test_webservice(self):
372        # First we have open InterswitchPageStudent to set provider_amt
373        # and gateway_amt
374        self.browser.open(self.payment_url + '/goto_interswitch')
375        # Now we can call the webservice
376        self.browser.open(self.payment_url + '/request_webservice')
377        self.assertMatches('...Unsuccessful callback...',
378                          self.browser.contents)
379        # The payment is now in state failed ...
380        self.assertMatches('...<span>Failed</span>...',
381                          self.browser.contents)
382        # ... and the catalog has been updated
383        cat = getUtility(ICatalog, name='payments_catalog')
384        results = list(
385            cat.searchResults(p_state=('failed', 'failed')))
386        self.assertEqual(len(results), 1)
387        self.assertEqual(results[0].p_state, 'failed')
388
389        # Let's replace the p_id with a valid p_id of the Uniben
390        # live system. This is definitely not an appropriate
391        # solution for testing, but we have no choice since
392        # Interswitch doesn't provide any interface
393        # for testing.
394        payment = self.student['payments'][self.value]
395        payment.p_id = 'p3547789850240'
396        self.browser.open(self.payment_url + '/request_webservice')
397        self.assertMatches('...Callback amount does not match...',
398                          self.browser.contents)
399        # The payment is now in state failed ...
400        self.assertMatches('...<span>Failed</span>...',
401                          self.browser.contents)
402        # Let's replace the amount autorized with the amount of the
403        # live system payment
404        payment.amount_auth = payment.r_amount_approved
405        self.browser.open(self.payment_url + '/request_webservice')
406        self.assertMatches('...Successful payment...',
407                          self.browser.contents)
408        # The payment is now in state paid ...
409        self.assertMatches('...<span>Paid</span>...',
410                          self.browser.contents)
411        # ... and the catalog has been updated
412        cat = getUtility(ICatalog, name='payments_catalog')
413        results = list(
414            cat.searchResults(p_state=('paid', 'paid')))
415        self.assertEqual(len(results), 1)
416        self.assertEqual(results[0].p_state, 'paid')
417        # Approval is logged in students.log ...
418        logfile = os.path.join(
419            self.app['datacenter'].storage, 'logs', 'students.log')
420        logcontent = open(logfile).read()
421        self.assertTrue(
422            'zope.mgr - '
423            'waeup.uniben.interswitch.browser.CustomInterswitchPaymentRequestWebservicePageStudent - '
424            'B1000000 - successful schoolfee payment: p3547789850240\n'
425            in logcontent)
426        # ... and in payments.log
427        logfile = os.path.join(
428            self.app['datacenter'].storage, 'logs', 'payments.log')
429        logcontent = open(logfile).read()
430        self.assertTrue(
431            '"zope.mgr",B1000000,p3547789850240,schoolfee,'
432            '12000.0,00,1500.0,150.0,0.0,,,\n'
433            in logcontent)
434
435
436class InterswitchTestsApplicants(ApplicantsFullSetup):
437    """Tests for the Interswitch payment gateway.
438    """
439
440    layer = FunctionalLayer
441
442    def setUp(self):
443        super(InterswitchTestsApplicants, self).setUp()
444        configuration = CustomSessionConfiguration()
445        configuration.academic_session = datetime.now().year - 2
446        self.app['configuration'].addSessionConfiguration(configuration)
447        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
448        self.browser.open(self.manage_path)
449        #IWorkflowState(self.student).setState('started')
450        self.applicantscontainer.application_fee = 1000.0
451        super(InterswitchTestsApplicants, self).fill_correct_values()
452        self.browser.getControl("Add online").click()
453        self.assertMatches('...passport photo before making payment...',
454                           self.browser.contents)
455        self.browser.open(self.manage_path)
456        super(InterswitchTestsApplicants, self).fill_correct_values()
457        #self.browser.getControl(name="form.nationality").value = ['NG']
458        #self.browser.getControl(name="transition").value = ['start']
459        image = open(SAMPLE_IMAGE, 'rb')
460        ctrl = self.browser.getControl(name='form.passport')
461        file_ctrl = ctrl.mech_control
462        file_ctrl.add_file(image, filename='myphoto.jpg')
463        self.browser.getControl("Save").click()
464        self.browser.getControl("Add online").click()
465        self.assertMatches('...ticket created...',
466                           self.browser.contents)
467        #ctrl = self.browser.getControl(name='val_id')
468        #value = ctrl.options[0]
469        #self.browser.getLink(value).click()
470        self.payment_url = self.browser.url
471
472    def test_interswitch_form(self):
473        self.assertMatches('...Amount Authorized...',
474                           self.browser.contents)
475        self.assertTrue(
476            '<span>1000.0</span>' in self.browser.contents)
477        # Manager can access InterswitchForm
478        self.browser.getLink("CollegePAY", index=0).click()
479        self.assertMatches('...Total Amount Authorized:...',
480                           self.browser.contents)
481        self.assertTrue(
482            '<input type="hidden" name="amount" value="100000" />'
483            in self.browser.contents)
484        delta = timedelta(days=8)
485        self.applicant.values()[0].creation_date -= delta
486        self.browser.open(self.payment_url)
487        self.browser.getLink("CollegePAY", index=0).click()
488        self.assertMatches(
489            '...This payment ticket is too old. Please create a new ticket...',
490            self.browser.contents)
491
492    @external_test
493    def test_webservice(self):
494
495        self.browser.open(self.payment_url + '/request_webservice')
496        self.assertMatches('...Unsuccessful callback...',
497                          self.browser.contents)
498        # The payment is now in state failed
499        self.assertMatches('...<span>Failed</span>...',
500                          self.browser.contents)
Note: See TracBrowser for help on using the repository browser.