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

Last change on this file since 10132 was 10131, checked in by Henrik Bettermann, 12 years ago

Configure application fee payment.

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