Merge lp:~therp-nl/banking-addons/ba70-add_tests into lp:banking-addons
- ba70-add_tests
- Merge into banking-addons-70
Proposed by
Stefan Rijnhart (Opener)
Status: | Merged |
---|---|
Merged at revision: | 201 |
Proposed branch: | lp:~therp-nl/banking-addons/ba70-add_tests |
Merge into: | lp:banking-addons |
Diff against target: |
392 lines (+375/-0) 3 files modified
account_banking_tests/__openerp__.py (+42/-0) account_banking_tests/tests/__init__.py (+5/-0) account_banking_tests/tests/test_payment_roundtrip.py (+328/-0) |
To merge this branch: | bzr merge lp:~therp-nl/banking-addons/ba70-add_tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Holger Brunn (Therp) | code review | Approve | |
Review via email:
|
Commit message
Description of the change
This is my attempt at adding unit test for a payment/
To post a comment you must log in.
- 190. By Stefan Rijnhart (Opener)
-
[FIX] Additional substitution of out-refactored assertion check
[FIX] Remove debug statement
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Holger Brunn (Therp) (hbrunn) wrote : | # |
review:
Approve
(code review)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'account_banking_tests' |
2 | === added file 'account_banking_tests/__init__.py' |
3 | === added file 'account_banking_tests/__openerp__.py' |
4 | --- account_banking_tests/__openerp__.py 1970-01-01 00:00:00 +0000 |
5 | +++ account_banking_tests/__openerp__.py 2013-09-26 17:55:39 +0000 |
6 | @@ -0,0 +1,42 @@ |
7 | +# -*- coding: utf-8 -*- |
8 | +############################################################################## |
9 | +# |
10 | +# Copyright (C) 2013 Therp BV (<http://therp.nl>) |
11 | +# |
12 | +# This program is free software: you can redistribute it and/or modify |
13 | +# it under the terms of the GNU Affero General Public License as |
14 | +# published by the Free Software Foundation, either version 3 of the |
15 | +# License, or (at your option) any later version. |
16 | +# |
17 | +# This program is distributed in the hope that it will be useful, |
18 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | +# GNU Affero General Public License for more details. |
21 | +# |
22 | +# You should have received a copy of the GNU Affero General Public License |
23 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
24 | +# |
25 | +############################################################################## |
26 | + |
27 | +{ |
28 | + 'name': 'Banking Addons - Tests', |
29 | + 'version': '0.1', |
30 | + 'license': 'AGPL-3', |
31 | + 'author': 'Therp BV', |
32 | + 'website': 'https://launchpad.net/banking-addons', |
33 | + 'category': 'Banking addons', |
34 | + 'depends': [ |
35 | + 'account_accountant', |
36 | + 'account_banking', |
37 | + 'account_banking_sepa_credit_transfer', |
38 | + ], |
39 | + 'description': ''' |
40 | +This addon adds unit tests for the Banking addons. Installing this |
41 | +module will not give you any benefit other than having the tests' |
42 | +dependencies installed, so that you can run the tests. If you only |
43 | +run the tests manually, you don't even have to install this module, |
44 | +only its dependencies. |
45 | + ''', |
46 | + 'auto_install': False, |
47 | + 'installable': True, |
48 | +} |
49 | |
50 | === added directory 'account_banking_tests/tests' |
51 | === added file 'account_banking_tests/tests/__init__.py' |
52 | --- account_banking_tests/tests/__init__.py 1970-01-01 00:00:00 +0000 |
53 | +++ account_banking_tests/tests/__init__.py 2013-09-26 17:55:39 +0000 |
54 | @@ -0,0 +1,5 @@ |
55 | +import test_payment_roundtrip |
56 | + |
57 | +fast_suite = [ |
58 | + test_payment_roundtrip, |
59 | + ] |
60 | |
61 | === added file 'account_banking_tests/tests/test_payment_roundtrip.py' |
62 | --- account_banking_tests/tests/test_payment_roundtrip.py 1970-01-01 00:00:00 +0000 |
63 | +++ account_banking_tests/tests/test_payment_roundtrip.py 2013-09-26 17:55:39 +0000 |
64 | @@ -0,0 +1,328 @@ |
65 | +# -*- coding: utf-8 -*- |
66 | +############################################################################## |
67 | +# |
68 | +# Copyright (C) 2013 Therp BV (<http://therp.nl>) |
69 | +# |
70 | +# This program is free software: you can redistribute it and/or modify |
71 | +# it under the terms of the GNU Affero General Public License as |
72 | +# published by the Free Software Foundation, either version 3 of the |
73 | +# License, or (at your option) any later version. |
74 | +# |
75 | +# This program is distributed in the hope that it will be useful, |
76 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
77 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
78 | +# GNU Affero General Public License for more details. |
79 | +# |
80 | +# You should have received a copy of the GNU Affero General Public License |
81 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
82 | +# |
83 | +############################################################################## |
84 | +from datetime import datetime |
85 | +from openerp.tests.common import SingleTransactionCase |
86 | +from openerp import netsvc |
87 | + |
88 | + |
89 | +class TestPaymentRoundtrip(SingleTransactionCase): |
90 | + |
91 | + def assert_payment_order_state(self, expected): |
92 | + """ |
93 | + Check that the state of our payment order is |
94 | + equal to the 'expected' parameter |
95 | + """ |
96 | + state = self.registry('payment.order').read( |
97 | + self.cr, self.uid, self.payment_order_id, ['state'])['state'] |
98 | + assert state == expected, \ |
99 | + 'Payment order does not go into state \'%s\'.' % expected |
100 | + |
101 | + def assert_invoices_state(self, expected): |
102 | + """ |
103 | + Check that the state of our invoices is |
104 | + equal to the 'expected' parameter |
105 | + """ |
106 | + for invoice in self.registry('account.invoice').read( |
107 | + self.cr, self.uid, self.invoice_ids, ['state']): |
108 | + assert invoice['state'] == expected, \ |
109 | + 'Invoice does not go into state \'%s\'' % expected |
110 | + |
111 | + def setup_company(self, reg, cr, uid): |
112 | + """ |
113 | + Set up a company with a bank account and configure the |
114 | + current user to work with that company |
115 | + """ |
116 | + data_model = reg('ir.model.data') |
117 | + self.country_id = data_model.get_object_reference( |
118 | + cr, uid, 'base', 'nl')[1] |
119 | + self.currency_id = data_model.get_object_reference( |
120 | + cr, uid, 'base', 'EUR')[1] |
121 | + self.bank_id = reg('res.bank').create( |
122 | + cr, uid, { |
123 | + 'name': 'ING Bank', |
124 | + 'bic': 'INGBNL2A', |
125 | + 'country': self.country_id, |
126 | + }) |
127 | + self.company_id = reg('res.company').create( |
128 | + cr, uid, { |
129 | + 'name': '_banking_addons_test_company', |
130 | + 'currency_id': self.currency_id, |
131 | + 'country_id': self.country_id, |
132 | + }) |
133 | + self.partner_id = reg('res.company').read( |
134 | + cr, uid, self.company_id, ['partner_id'])['partner_id'][0] |
135 | + self.partner_bank_id = reg('res.partner.bank').create( |
136 | + cr, uid, { |
137 | + 'state': 'iban', |
138 | + 'acc_number': 'NL08INGB0000000555', |
139 | + 'bank': self.bank_id, |
140 | + 'bank_bic': 'INGBNL2A', |
141 | + 'partner_id': self.partner_id, |
142 | + 'company_id': self.company_id, |
143 | + }) |
144 | + reg('res.users').write( |
145 | + cr, uid, [uid], { |
146 | + 'company_ids': [(4, self.company_id)]}) |
147 | + reg('res.users').write( |
148 | + cr, uid, [uid], { |
149 | + 'company_id': self.company_id}) |
150 | + |
151 | + def setup_chart(self, reg, cr, uid): |
152 | + """ |
153 | + Set up the configurable chart of accounts and create periods |
154 | + """ |
155 | + data_model = reg('ir.model.data') |
156 | + chart_setup_model = reg('wizard.multi.charts.accounts') |
157 | + chart_template_id = data_model.get_object_reference( |
158 | + cr, uid, 'account', 'configurable_chart_template')[1] |
159 | + chart_values = { |
160 | + 'company_id': self.company_id, |
161 | + 'currency_id': self.currency_id, |
162 | + 'chart_template_id': chart_template_id} |
163 | + chart_values.update( |
164 | + chart_setup_model.onchange_chart_template_id( |
165 | + cr, uid, [], 1)['value']) |
166 | + chart_setup_id = chart_setup_model.create( |
167 | + cr, uid, chart_values) |
168 | + chart_setup_model.execute( |
169 | + cr, uid, [chart_setup_id]) |
170 | + year = datetime.now().strftime('%Y') |
171 | + fiscalyear_id = reg('account.fiscalyear').create( |
172 | + cr, uid, { |
173 | + 'name': year, |
174 | + 'code': year, |
175 | + 'company_id': self.company_id, |
176 | + 'date_start': '%s-01-01' % year, |
177 | + 'date_stop': '%s-12-31' % year, |
178 | + }) |
179 | + reg('account.fiscalyear').create_period( |
180 | + cr, uid, [fiscalyear_id]) |
181 | + |
182 | + def setup_payables(self, reg, cr, uid): |
183 | + """ |
184 | + Set up suppliers and invoice them. Check that the invoices |
185 | + can be validated properly. |
186 | + """ |
187 | + partner_model = reg('res.partner') |
188 | + supplier1 = partner_model.create( |
189 | + cr, uid, { |
190 | + 'name': 'Supplier 1', |
191 | + 'supplier': True, |
192 | + 'country_id': self.country_id, |
193 | + 'bank_ids': [(0, False, { |
194 | + 'state': 'iban', |
195 | + 'acc_number': 'NL42INGB0000454000', |
196 | + 'bank': self.bank_id, |
197 | + 'bank_bic': 'INGBNL2A', |
198 | + })], |
199 | + }) |
200 | + supplier2 = partner_model.create( |
201 | + cr, uid, { |
202 | + 'name': 'Supplier 2', |
203 | + 'supplier': True, |
204 | + 'country_id': self.country_id, |
205 | + 'bank_ids': [(0, False, { |
206 | + 'state': 'iban', |
207 | + 'acc_number': 'NL86INGB0002445588', |
208 | + 'bank': self.bank_id, |
209 | + 'bank_bic': 'INGBNL2A', |
210 | + })], |
211 | + }) |
212 | + self.payable_id = reg('account.account').search( |
213 | + cr, uid, [ |
214 | + ('company_id', '=', self.company_id), |
215 | + ('code', '=', '120000')])[0] |
216 | + expense_id = reg('account.account').search( |
217 | + cr, uid, [ |
218 | + ('company_id', '=', self.company_id), |
219 | + ('code', '=', '123000')])[0] |
220 | + invoice_model = reg('account.invoice') |
221 | + values = { |
222 | + 'type': 'in_invoice', |
223 | + 'partner_id': supplier1, |
224 | + 'account_id': self.payable_id, |
225 | + 'invoice_line': [(0, False, { |
226 | + 'name': 'Purchase 1', |
227 | + 'price_unit': 100.0, |
228 | + 'quantity': 1, |
229 | + 'account_id': expense_id,})], |
230 | + } |
231 | + self.invoice_ids = [ |
232 | + invoice_model.create( |
233 | + cr, uid, values, context={ |
234 | + 'type': 'in_invoice', |
235 | + })] |
236 | + values.update({ |
237 | + 'partner_id': supplier2, |
238 | + 'name': 'Purchase 2'}) |
239 | + self.invoice_ids.append( |
240 | + invoice_model.create( |
241 | + cr, uid, values, context={ |
242 | + 'type': 'in_invoice'})) |
243 | + wf_service = netsvc.LocalService('workflow') |
244 | + for invoice_id in self.invoice_ids: |
245 | + wf_service.trg_validate( |
246 | + uid, 'account.invoice', invoice_id, 'invoice_open', cr) |
247 | + self.assert_invoices_state('open') |
248 | + |
249 | + def setup_payment_config(self, reg, cr, uid): |
250 | + """ |
251 | + Configure an additional account and journal for payments |
252 | + in transit and configure a payment mode with them. |
253 | + """ |
254 | + account_parent_id = reg('account.account').search( |
255 | + cr, uid, [ |
256 | + ('company_id', '=', self.company_id), |
257 | + ('parent_id', '=', False)])[0] |
258 | + user_type = reg('ir.model.data').get_object_reference( |
259 | + cr, uid, 'account', 'data_account_type_liability')[1] |
260 | + transfer_account_id = reg('account.account').create( |
261 | + cr, uid, { |
262 | + 'company_id': self.company_id, |
263 | + 'parent_id': account_parent_id, |
264 | + 'code': 'TRANS', |
265 | + 'name': 'Transfer account', |
266 | + 'type': 'other', |
267 | + 'user_type': user_type, |
268 | + 'reconcile': True, |
269 | + }) |
270 | + transfer_journal_id = reg('account.journal').search( |
271 | + cr, uid, [ |
272 | + ('company_id', '=', self.company_id), |
273 | + ('code', '=', 'MISC')])[0] |
274 | + self.bank_journal_id = reg('account.journal').search( |
275 | + cr, uid, [ |
276 | + ('company_id', '=', self.company_id), |
277 | + ('type', '=', 'bank')])[0] |
278 | + payment_mode_type_id = reg('ir.model.data').get_object_reference( |
279 | + cr, uid, 'account_banking_sepa_credit_transfer', |
280 | + 'export_sepa_sct_001_001_03')[1] |
281 | + self.payment_mode_id = reg('payment.mode').create( |
282 | + cr, uid, { |
283 | + 'name': 'SEPA Mode', |
284 | + 'bank_id': self.partner_bank_id, |
285 | + 'journal': self.bank_journal_id, |
286 | + 'company_id': self.company_id, |
287 | + 'transfer_account_id': transfer_account_id, |
288 | + 'transfer_journal_id': transfer_journal_id, |
289 | + 'type': payment_mode_type_id, |
290 | + }) |
291 | + |
292 | + def setup_payment(self, reg, cr, uid): |
293 | + """ |
294 | + Create a payment order with the invoices' payable move lines. |
295 | + Check that the payment order can be confirmed. |
296 | + """ |
297 | + self.payment_order_id = reg('payment.order').create( |
298 | + cr, uid, { |
299 | + 'reference': 'PAY001', |
300 | + 'mode': self.payment_mode_id, |
301 | + }) |
302 | + context = {'active_id': self.payment_order_id} |
303 | + entries = reg('account.move.line').search( |
304 | + cr, uid, [ |
305 | + ('company_id', '=', self.company_id), |
306 | + ('account_id', '=', self.payable_id), |
307 | + ]) |
308 | + self.payment_order_create_id = reg('payment.order.create').create( |
309 | + cr, uid, { |
310 | + 'entries': [(6, 0, entries)], |
311 | + }, context=context) |
312 | + reg('payment.order.create').create_payment( |
313 | + cr, uid, [self.payment_order_create_id], context=context) |
314 | + wf_service = netsvc.LocalService('workflow') |
315 | + wf_service.trg_validate( |
316 | + uid, 'payment.order', self.payment_order_id, 'open', cr) |
317 | + self.assert_payment_order_state('open') |
318 | + |
319 | + def export_payment(self, reg, cr, uid): |
320 | + """ |
321 | + Call the SEPA export wizard on the payment order |
322 | + and check that the payment order and related invoices' |
323 | + states are moved forward afterwards |
324 | + """ |
325 | + export_model = reg('banking.export.sepa.wizard') |
326 | + export_id = export_model.create( |
327 | + cr, uid, { |
328 | + 'msg_identification': 'EXP001'}, |
329 | + context={'active_ids': [self.payment_order_id]}) |
330 | + export_model.create_sepa( |
331 | + cr, uid, [export_id]) |
332 | + export_model.save_sepa( |
333 | + cr, uid, [export_id]) |
334 | + self.assert_payment_order_state('sent') |
335 | + self.assert_invoices_state('paid') |
336 | + |
337 | + def setup_bank_statement(self, reg, cr, uid): |
338 | + """ |
339 | + Create a bank statement with a single line. Call the reconciliation |
340 | + wizard to match the line with the open payment order. Confirm the |
341 | + bank statement. Check if the payment order is done. |
342 | + """ |
343 | + statement_model = reg('account.bank.statement') |
344 | + line_model = reg('account.bank.statement.line') |
345 | + wizard_model = reg('banking.transaction.wizard') |
346 | + statement_id = statement_model.create( |
347 | + cr, uid, { |
348 | + 'name': 'Statement', |
349 | + 'journal_id': self.bank_journal_id, |
350 | + 'balance_end_real': -200.0, |
351 | + 'period_id': reg('account.period').find(cr, uid)[0] |
352 | + }) |
353 | + line_id = line_model.create( |
354 | + cr, uid, { |
355 | + 'name': 'Statement line', |
356 | + 'statement_id': statement_id, |
357 | + 'amount': -200.0, |
358 | + 'account_id': self.payable_id, |
359 | + }) |
360 | + wizard_id = wizard_model.create( |
361 | + cr, uid, {'statement_line_id': line_id}) |
362 | + wizard_model.write( |
363 | + cr, uid, [wizard_id], { |
364 | + 'manual_payment_order_id': self.payment_order_id}) |
365 | + statement_model.button_confirm_bank(cr, uid, [statement_id]) |
366 | + self.assert_payment_order_state('done') |
367 | + |
368 | + def check_reconciliations(self, reg, cr, uid): |
369 | + """ |
370 | + Check if the payment order has any lines and that |
371 | + the transit move lines of those payment lines are |
372 | + reconciled by now. |
373 | + """ |
374 | + payment_order = reg('payment.order').browse( |
375 | + cr, uid, self.payment_order_id) |
376 | + assert payment_order.line_ids, 'Payment order has no payment lines' |
377 | + for line in payment_order.line_ids: |
378 | + assert line.transit_move_line_id, \ |
379 | + 'Payment order has no transfer move line' |
380 | + assert line.transit_move_line_id.reconcile_id, \ |
381 | + 'Transfer move line on payment line is not reconciled' |
382 | + |
383 | + def test_payment_roundtrip(self): |
384 | + reg, cr, uid, = self.registry, self.cr, self.uid |
385 | + self.setup_company(reg, cr, uid) |
386 | + self.setup_chart(reg, cr, uid) |
387 | + self.setup_payables(reg, cr, uid) |
388 | + self.setup_payment_config(reg, cr, uid) |
389 | + self.setup_payment(reg, cr, uid) |
390 | + self.export_payment(reg, cr, uid) |
391 | + self.setup_bank_statement(reg, cr, uid) |
392 | + self.check_reconciliations(reg, cr, uid) |
Yes, adding tests is a very good idea