source: main/waeup.kwarapoly/trunk/src/waeup/kwarapoly/interswitch/tests.py @ 10709

Last change on this file since 10709 was 10682, checked in by Henrik Bettermann, 11 years ago

Take hostel_maintenance fee from hostel objects. Store bed coordinates as payment item.

  • Property svn:keywords set to Id
File size: 20.2 KB
Line 
1## $Id: tests.py 10682 2013-11-01 09:11:10Z 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
19import grok
20from hurry.workflow.interfaces import IWorkflowState
21from zope.component import createObject, getUtility
22from zope.catalog.interfaces import ICatalog
23from zope.event import notify
24from waeup.kofa.university.faculty import Faculty
25from waeup.kofa.university.department import Department
26from waeup.kofa.students.tests.test_browser import StudentsFullSetup
27from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup
28from waeup.kofa.configuration import SessionConfiguration
29from waeup.kwarapoly.testing import FunctionalLayer
30from waeup.kwarapoly.students.payments import CustomStudentOnlinePayment
31
32# Also run tests that send requests to external servers?
33#   If you enable this, please make sure the external services
34#   do exist really and are not bothered by being spammed by a test programme.
35EXTERNAL_TESTS = False
36
37def external_test(func):
38    if not EXTERNAL_TESTS:
39        myself = __file__
40        if myself.endswith('.pyc'):
41            myself = myself[:-2]
42        print "WARNING: external tests are skipped!"
43        print "WARNING: edit %s to enable them." % myself
44        return
45    return func
46
47
48class InterswitchTestsStudents(StudentsFullSetup):
49    """Tests for the Interswitch payment gateway.
50    """
51
52    layer = FunctionalLayer
53
54    def setUp(self):
55        super(InterswitchTestsStudents, self).setUp()
56
57        # Create at least one Kwarapoly faculty
58        self.app['faculties']['CPGS'] = Faculty(code='CPGS')
59        self.app['faculties']['CPGS']['dep1'] = Department(code='dep1')
60        self.certificate2 = createObject('waeup.Certificate')
61        self.certificate2.code = u'CERT2'
62        self.certificate2.application_category = 'basic'
63        self.certificate2.study_mode = 'nd_ft'
64        self.certificate2.start_level = 100
65        self.certificate2.end_level = 300
66        self.app['faculties']['CPGS']['dep1'].certificates.addCertificate(
67            self.certificate2)
68        # Set study course attributes of test student
69        self.student['studycourse'].certificate = self.certificate2
70        self.student['studycourse'].current_session = 2004
71        self.student['studycourse'].entry_session = 2004
72        self.student['studycourse'].current_verdict = 'A'
73        self.student['studycourse'].current_level = 100
74        # Set local lga
75        self.student.lga = u'kwara_asa'
76        # Update the catalog
77        notify(grok.ObjectModifiedEvent(self.student))
78
79
80    def test_schoolfee_ticket_creation(self):
81        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
82        self.browser.open(self.payments_path)
83        IWorkflowState(self.student).setState('cleared')
84        self.browser.open(self.payments_path + '/addop')
85        self.browser.getControl(name="form.p_category").value = ['schoolfee']
86        self.browser.getControl("Create ticket").click()
87        self.assertMatches('...Book and pay for accommodation first...',
88                           self.browser.contents)
89        # We add a fake maint. payment ticket to meet the condition
90        maint_payment = CustomStudentOnlinePayment()
91        self.student['payments']['any_key'] = maint_payment
92        maint_payment.p_category = 'hostel_maintenance'
93        maint_payment.p_state = 'unpaid'
94        maint_payment.p_session = 2004
95        self.browser.getControl(name="form.p_category").value = ['schoolfee']
96        self.browser.getControl("Create ticket").click()
97        self.assertMatches('...Book and pay for accommodation first...',
98                           self.browser.contents)
99        # Ticket must be paid
100        maint_payment.p_state = 'paid'
101        self.browser.getControl(name="form.p_category").value = ['schoolfee']
102        self.browser.getControl("Create ticket").click()
103        self.assertMatches('...ticket created...',
104                           self.browser.contents)
105        ctrl = self.browser.getControl(name='val_id')
106        self.value = ctrl.options[1]
107        self.browser.getLink(self.value).click()
108        self.assertMatches('...Amount Authorized...',
109                           self.browser.contents)
110        self.assertMatches(
111            '...<span>39400.0</span>...',
112            self.browser.contents)
113        self.payment_url = self.browser.url
114
115
116#    def callback_url(self, payment_url, resp, apprAmt):
117#        return payment_url + (
118#            '/isw_callback?echo=' +
119#            '&resp=%s' +
120#            '&desc=Something went wrong' +
121#            '&txnRef=p1331792385335' +
122#            '&payRef=' + '&retRef=' +
123#            '&cardNum=0' +
124#            '&apprAmt=%s' +
125#            '&url=http://xyz') % (resp, apprAmt)
126
127    def test_interswitch_form(self):
128
129        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
130        self.browser.open(self.payments_path)
131        # In KwaraPoly only returning students can create school fee payment
132        # without haveing paid accommodation fee
133        IWorkflowState(self.student).setState('returning')
134        configuration = createObject('waeup.SessionConfiguration')
135        configuration.academic_session = 2005
136        self.app['configuration'].addSessionConfiguration(configuration)
137        self.browser.open(self.payments_path + '/addop')
138        self.browser.getControl(name="form.p_category").value = ['schoolfee']
139        self.browser.getControl("Create ticket").click()
140        self.assertMatches('...ticket created...', self.browser.contents)
141        ctrl = self.browser.getControl(name='val_id')
142        self.value = ctrl.options[0]
143        self.browser.getLink(self.value).click()
144        self.assertMatches('...Amount Authorized...', self.browser.contents)
145        self.assertMatches(
146            '...<span>29500.0</span>...',
147            self.browser.contents)
148        self.payment_url = self.browser.url
149
150        # Manager can access InterswitchForm
151        self.assertEqual(self.student['payments'][self.value].provider_amt, 0.0)
152        self.assertEqual(self.student['payments'][self.value].gateway_amt, 0.0)
153        self.assertEqual(self.student['payments'][self.value].thirdparty_amt, 0.0)
154        self.browser.getLink("CollegePAY", index=0).click()
155        # Split amounts have been set.
156        self.assertEqual(self.student['payments'][self.value].provider_amt, 1200.0)
157        self.assertEqual(self.student['payments'][self.value].gateway_amt, 300.0)
158        self.assertEqual(self.student['payments'][self.value].thirdparty_amt, 1800.0)
159        self.assertMatches('...Total Amount Authorized:...',
160                           self.browser.contents)
161        self.assertTrue(
162            '<input type="hidden" name="amount" value="2950000.0" />' in
163            self.browser.contents)
164        self.assertTrue(
165            'item_name="School Fee" item_amt="2620000" bank_id="120" acct_num="1771180233"' in
166            self.browser.contents)
167        self.assertTrue(
168            'item_name="Dalash" item_amt="180000" bank_id="117" acct_num="1013196791"' in
169            self.browser.contents)
170        self.assertTrue(
171            'item_name="BT Education" item_amt="120000" bank_id="117" acct_num="1010764827"' in
172            self.browser.contents)
173
174        # Let's do the same for maintenance fee payment
175
176        self.browser.open(self.payments_path)
177        self.browser.open(self.payments_path + '/addop')
178        self.browser.getControl(
179            name="form.p_category").value = ['hostel_maintenance']
180        self.browser.getControl("Create ticket").click()
181        self.assertMatches('...You have not yet booked accommodation...',
182                           self.browser.contents)
183        # Students have to book bed first
184        self.browser.open(self.acco_path)
185        IWorkflowState(self.student).setState('admitted')
186        self.browser.getLink("Book accommodation").click()
187        self.assertFalse('Activation Code:' in self.browser.contents)
188        self.browser.getControl("Create bed ticket").click()
189        # Bed is randomly selected but, since there is only
190        # one bed for this student, we know that ...
191        self.assertMatches('...Hall 1, Block A, Room 101, Bed A...',
192                           self.browser.contents)
193        self.assertMatches('...ticket created...',
194                           self.browser.contents)
195        self.browser.open(self.payments_path + '/addop')
196        self.browser.getControl(
197            name="form.p_category").value = ['hostel_maintenance']
198        self.browser.getControl("Create ticket").click()
199        self.assertMatches('...ticket created...',
200                           self.browser.contents)
201        ctrl = self.browser.getControl(name='val_id')
202        value = ctrl.options[1]
203        self.browser.getLink(value).click()
204        self.assertMatches('...Amount Authorized...',
205                           self.browser.contents)
206        # Maint fee is taken from the hostel object
207        self.assertMatches(
208            '...<span>876.0</span>...',
209            self.browser.contents)
210        self.payment_url = self.browser.url
211        # Manager can access InterswitchForm
212        self.browser.getLink("CollegePAY", index=0).click()
213        # Split amounts have been set.
214        self.assertEqual(self.student['payments'][value].provider_amt, 0.0)
215        self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0)
216        self.assertEqual(self.student['payments'][value].gateway_amt, 300.0)
217        # The total amount to be processed by Interswitch
218        # has been reduced by the Interswitch fee of 150 Nairas
219        self.assertMatches('...Total Amount Authorized:...',
220                           self.browser.contents)
221        self.assertMatches(
222            '...<input type="hidden" name="pay_item_id" value="102" />...',
223            self.browser.contents)
224        self.assertMatches(
225            '...<input type="hidden" name="amount" value="87600.0" />...',
226            self.browser.contents)
227        self.assertMatches(
228            '...item_name="Hostel Maintenance Fee" item_amt="57600" bank_id="31" acct_num="0039050937"...',
229            self.browser.contents)
230
231        # Create carryover ticket
232        self.browser.open(self.payments_path + '/addop')
233        self.browser.getControl(name="form.p_category").value = ['carryover1']
234        self.browser.getControl("Create ticket").click()
235        ctrl = self.browser.getControl(name='val_id')
236        value = ctrl.options[2]
237        self.browser.getLink(value).click()
238        self.assertMatches(
239            '...<span>6000.0</span>...',
240            self.browser.contents)
241        # Manager can access InterswitchForm
242        self.browser.getLink("CollegePAY", index=0).click()
243        # Split amounts have been set.
244        self.assertEqual(self.student['payments'][self.value].provider_amt, 1200.0)
245        self.assertEqual(self.student['payments'][self.value].gateway_amt, 300.0)
246        self.assertEqual(self.student['payments'][self.value].thirdparty_amt, 1800.0)
247        self.assertMatches('...<input type="hidden" name="pay_item_id" value="101" />...',
248                           self.browser.contents)
249        self.assertMatches('...Total Amount Authorized:...',
250                           self.browser.contents)
251        self.assertMatches(
252            '...<input type="hidden" name="amount" value="600000.0" />...',
253            self.browser.contents)
254        self.assertMatches(
255            '...item_name="School Fee" item_amt="270000" bank_id="120" acct_num="1771180233"...',
256            self.browser.contents)
257        self.assertMatches(
258            '...item_name="Dalash" item_amt="180000" bank_id="117" acct_num="1013196791"...',
259            self.browser.contents)
260        self.assertMatches(
261            '...item_name="BT Education" item_amt="120000" bank_id="117" acct_num="1010764827"...',
262            self.browser.contents)
263
264    @external_test
265    def test_webservice(self):
266        # First we have open InterswitchPageStudent to set provider_amt
267        # and gateway_amt
268        self.browser.open(self.payment_url + '/goto_interswitch')
269        # Now we can call the webservice
270        self.browser.open(self.payment_url + '/request_webservice')
271        self.assertMatches('...Unsuccessful callback...',
272                          self.browser.contents)
273        # The payment is now in state failed ...
274        self.assertMatches('...<span>Failed</span>...',
275                          self.browser.contents)
276        # ... and the catalog has been updated
277        cat = getUtility(ICatalog, name='payments_catalog')
278        results = list(
279            cat.searchResults(p_state=('failed', 'failed')))
280        self.assertEqual(len(results), 1)
281        self.assertEqual(results[0].p_state, 'failed')
282
283        # Let's replace the p_id with a valid p_id of the Kwarapoly
284        # live system. This is definitely not an appropriate
285        # solution for testing, but we have no choice since
286        # Interswitch doesn't provide any interface
287        # for testing.
288        payment = self.student['payments'][self.value]
289        payment.p_id = 'p3543612043224'
290        self.browser.open(self.payment_url + '/request_webservice')
291        self.assertMatches('...Callback amount does not match...',
292                          self.browser.contents)
293        # The payment is now in state failed ...
294        self.assertMatches('...<span>Failed</span>...',
295                          self.browser.contents)
296        # Let's replace the amount autorized with the amount of the
297        # live system payment
298        payment.amount_auth = payment.r_amount_approved
299        self.browser.open(self.payment_url + '/request_webservice')
300        self.assertMatches('...Successful payment...',
301                          self.browser.contents)
302        # The payment is now in state paid ...
303        self.assertMatches('...<span>Paid</span>...',
304                          self.browser.contents)
305        # ... and the catalog has been updated
306        cat = getUtility(ICatalog, name='payments_catalog')
307        results = list(
308            cat.searchResults(p_state=('paid', 'paid')))
309        self.assertEqual(len(results), 1)
310        self.assertEqual(results[0].p_state, 'paid')
311        # Approval is logged in students.log ...
312        logfile = os.path.join(
313            self.app['datacenter'].storage, 'logs', 'students.log')
314        logcontent = open(logfile).read()
315        self.assertTrue(
316            'zope.mgr - '
317            'waeup.kwarapoly.interswitch.browser.InterswitchPaymentRequestWebservicePageStudent - '
318            'W1000000 - successful schoolfee payment: p3543612043224\n'
319            in logcontent)
320        # ... and in payments.log
321        logfile = os.path.join(
322            self.app['datacenter'].storage, 'logs', 'payments.log')
323        logcontent = open(logfile).read()
324        self.assertTrue(
325            '"zope.mgr",W1000000,p3543612043224,schoolfee,'
326            '52100.0,00,1200.0,300.0,1800.0,,,\n'
327            in logcontent)
328
329
330class InterswitchTestsApplicants(ApplicantsFullSetup):
331    """Tests for the Interswitch payment gateway.
332    """
333
334    layer = FunctionalLayer
335
336    def setUp(self):
337        super(InterswitchTestsApplicants, self).setUp()
338        # Create at least one Kwarapoly faculty
339        self.app['faculties']['CPGS'] = Faculty(code='CPGS')
340        self.app['faculties']['CPGS']['dep1'] = Department(code='dep1')
341        self.certificate2 = createObject('waeup.Certificate')
342        self.certificate2.code = u'CERT2'
343        self.certificate2.application_category = 'ndft'
344        self.certificate2.study_mode = 'nd_ft'
345        self.certificate2.start_level = 100
346        self.certificate2.end_level = 300
347        self.app['faculties']['CPGS']['dep1'].certificates.addCertificate(
348            self.certificate2)
349        self.applicantscontainer.application_category = 'ndft'
350        self.applicant.applicant_id = u'nd_anything'
351       
352        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
353        self.browser.open(self.manage_path)
354        #IWorkflowState(self.student).setState('started')
355        super(InterswitchTestsApplicants, self).fill_correct_values()
356        self.browser.getControl(name="form.course1").value = ['CERT2']
357        self.applicantscontainer.application_fee = 3333.0
358        self.browser.getControl(name="form.nationality").value = ['NG']
359        self.browser.getControl(name="transition").value = ['start']
360        self.browser.getControl("Save").click()
361        self.browser.getControl("Add online").click()
362        self.assertMatches('...ticket created...',
363                           self.browser.contents)
364        #ctrl = self.browser.getControl(name='val_id')
365        #value = ctrl.options[0]
366        #self.browser.getLink(value).click()
367        self.assertMatches('...Amount Authorized...',
368                           self.browser.contents)
369        self.assertMatches(
370            '...<span>3333.0</span>...',
371            self.browser.contents)
372        self.payment_url = self.browser.url
373
374
375    def test_interswitch_form(self):
376
377        # Manager can access InterswitchForm
378        self.browser.getLink("CollegePAY", index=0).click()
379        self.assertMatches('...Total Amount Authorized:...',
380                           self.browser.contents)
381        self.assertTrue(
382            '<input type="hidden" name="amount" value="333300.0" />'
383            in self.browser.contents)
384        self.assertTrue(
385            '<item_detail item_id="1" item_name="application" '
386            'item_amt="253300" bank_id="8" acct_num="2014191363" />'
387            in self.browser.contents)
388
389        # hndft fee goes to another account
390        self.applicant.applicant_id = u'hnd_anything'
391        self.browser.open(self.manage_path)
392        ctrl = self.browser.getControl(name='val_id')
393        value = ctrl.options[0]
394        self.browser.getLink(value).click()
395        self.browser.getLink("CollegePAY", index=0).click()
396        self.assertTrue(
397            '<item_detail item_id="1" item_name="application" '
398            'item_amt="253300" bank_id="9" acct_num="7000016724" />'
399            in self.browser.contents)
400        # Commission or bribe?
401        self.assertTrue(
402            '<item_detail item_id="2" item_name="Dalash" item_amt="20000" '
403            'bank_id="117" acct_num="1013196791" />'
404            in self.browser.contents)
405        self.assertTrue(
406            '<item_detail item_id="3" item_name="BT Education" '
407            'item_amt="30000" bank_id="117" acct_num="1010764827" />'
408            in self.browser.contents)
409
410        # prehndft fee goes to another account
411        self.applicant.applicant_id = u'prehnd_anything'
412        self.browser.open(self.manage_path)
413        ctrl = self.browser.getControl(name='val_id')
414        value = ctrl.options[0]
415        self.browser.getLink(value).click()
416        self.browser.getLink("CollegePAY", index=0).click()
417        self.assertTrue(
418            '<item_detail item_id="1" item_name="application" '
419            'item_amt="303300" bank_id="8" acct_num="2013910271" />'
420            in self.browser.contents)
421        # No 'commission', no provider fee
422        self.assertFalse('Dalash' in self.browser.contents)
423        self.assertFalse('BT Education' in self.browser.contents)
424
425        # prejambites fee goes to another account
426        self.applicant.applicant_id = u'prejambites_anything'
427        self.browser.open(self.manage_path)
428        ctrl = self.browser.getControl(name='val_id')
429        value = ctrl.options[0]
430        self.browser.getLink(value).click()
431        self.browser.getLink("CollegePAY", index=0).click()
432        self.assertTrue(
433            '<item_detail item_id="1" item_name="application" '
434            'item_amt="303300" bank_id="10" acct_num="0106259811" />'
435            in self.browser.contents)
436        # No 'commission', no provider fee
437        self.assertFalse('Dalash' in self.browser.contents)
438        self.assertFalse('BT Education' in self.browser.contents)
Note: See TracBrowser for help on using the repository browser.