banking-addons-team team mailing list archive
-
banking-addons-team team
-
Mailing list archive
-
Message #00946
[Merge] lp:~therp-nl/banking-addons/ba70-add_tests into lp:banking-addons
Stefan Rijnhart (Therp) has proposed merging lp:~therp-nl/banking-addons/ba70-add_tests into lp:banking-addons.
Requested reviews:
Banking Addons Core Editors (banking-addons-team)
For more details, see:
https://code.launchpad.net/~therp-nl/banking-addons/ba70-add_tests/+merge/187780
This is my attempt at adding unit test for a payment/reconciliation roundtrip. I don't think I could have put it in any of the existing modules, because soon the payment export, workflow integration and reconciliation functionalities will no longer be necessary dependencies. Therefore, I put the test in its own module that depends on all needed functionality.
--
https://code.launchpad.net/~therp-nl/banking-addons/ba70-add_tests/+merge/187780
Your team Banking Addons Core Editors is requested to review the proposed merge of lp:~therp-nl/banking-addons/ba70-add_tests into lp:banking-addons.
=== added directory 'account_banking_tests'
=== added file 'account_banking_tests/__init__.py'
=== added file 'account_banking_tests/__openerp__.py'
--- account_banking_tests/__openerp__.py 1970-01-01 00:00:00 +0000
+++ account_banking_tests/__openerp__.py 2013-09-26 13:31:18 +0000
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2013 Therp BV (<http://therp.nl>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Banking Addons - Tests',
+ 'version': '0.1',
+ 'license': 'AGPL-3',
+ 'author': 'Therp BV',
+ 'website': 'https://launchpad.net/banking-addons',
+ 'category': 'Banking addons',
+ 'depends': [
+ 'account_accountant',
+ 'account_banking',
+ 'account_banking_sepa_credit_transfer',
+ ],
+ 'description': '''
+This addon adds unit tests for the Banking addons. Installing this
+module will not give you any benefit other than having the tests'
+dependencies installed, so that you can run the tests. If you only
+run the tests manually, you don't even have to install this module,
+only its dependencies.
+ ''',
+ 'auto_install': False,
+ 'installable': True,
+}
=== added directory 'account_banking_tests/tests'
=== added file 'account_banking_tests/tests/__init__.py'
--- account_banking_tests/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ account_banking_tests/tests/__init__.py 2013-09-26 13:31:18 +0000
@@ -0,0 +1,5 @@
+import test_payment_roundtrip
+
+fast_suite = [
+ test_payment_roundtrip,
+ ]
=== added file 'account_banking_tests/tests/test_payment_roundtrip.py'
--- account_banking_tests/tests/test_payment_roundtrip.py 1970-01-01 00:00:00 +0000
+++ account_banking_tests/tests/test_payment_roundtrip.py 2013-09-26 13:31:18 +0000
@@ -0,0 +1,331 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2013 Therp BV (<http://therp.nl>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from datetime import datetime
+from openerp.tests.common import SingleTransactionCase
+from openerp import netsvc
+
+
+class TestPaymentRoundtrip(SingleTransactionCase):
+
+ def assert_payment_order_state(self, expected):
+ """
+ Check that the state of our payment order is
+ equal to the 'expected' parameter
+ """
+ state = self.registry('payment.order').read(
+ self.cr, self.uid, self.payment_order_id, ['state'])['state']
+ assert state == expected, \
+ 'Payment order does not go into state \'%s\'.' % expected
+
+ def assert_invoices_state(self, expected):
+ """
+ Check that the state of our invoices is
+ equal to the 'expected' parameter
+ """
+ for invoice in self.registry('account.invoice').read(
+ self.cr, self.uid, self.invoice_ids, ['state']):
+ assert invoice['state'] == expected, \
+ 'Invoice does not go into state \'%s\'' % expected
+
+ def setup_company(self, reg, cr, uid):
+ """
+ Set up a company with a bank account and configure the
+ current user to work with that company
+ """
+ data_model = reg('ir.model.data')
+ self.country_id = data_model.get_object_reference(
+ cr, uid, 'base', 'nl')[1]
+ self.currency_id = data_model.get_object_reference(
+ cr, uid, 'base', 'EUR')[1]
+ self.bank_id = reg('res.bank').create(
+ cr, uid, {
+ 'name': 'ING Bank',
+ 'bic': 'INGBNL2A',
+ 'country': self.country_id,
+ })
+ self.company_id = reg('res.company').create(
+ cr, uid, {
+ 'name': '_banking_addons_test_company',
+ 'currency_id': self.currency_id,
+ 'country_id': self.country_id,
+ })
+ self.partner_id = reg('res.company').read(
+ cr, uid, self.company_id, ['partner_id'])['partner_id'][0]
+ self.partner_bank_id = reg('res.partner.bank').create(
+ cr, uid, {
+ 'state': 'iban',
+ 'acc_number': 'NL08INGB0000000555',
+ 'bank': self.bank_id,
+ 'bank_bic': 'INGBNL2A',
+ 'partner_id': self.partner_id,
+ 'company_id': self.company_id,
+ })
+ reg('res.users').write(
+ cr, uid, [uid], {
+ 'company_ids': [(4, self.company_id)]})
+ reg('res.users').write(
+ cr, uid, [uid], {
+ 'company_id': self.company_id})
+
+ def setup_chart(self, reg, cr, uid):
+ """
+ Set up the configurable chart of accounts and create periods
+ """
+ data_model = reg('ir.model.data')
+ chart_setup_model = reg('wizard.multi.charts.accounts')
+ chart_template_id = data_model.get_object_reference(
+ cr, uid, 'account', 'configurable_chart_template')[1]
+ chart_values = {
+ 'company_id': self.company_id,
+ 'currency_id': self.currency_id,
+ 'chart_template_id': chart_template_id}
+ chart_values.update(
+ chart_setup_model.onchange_chart_template_id(
+ cr, uid, [], 1)['value'])
+ chart_setup_id = chart_setup_model.create(
+ cr, uid, chart_values)
+ chart_setup_model.read(cr, uid, chart_setup_id)
+ chart_setup_model.execute(
+ cr, uid, [chart_setup_id])
+ year = datetime.now().strftime('%Y')
+ fiscalyear_id = reg('account.fiscalyear').create(
+ cr, uid, {
+ 'name': year,
+ 'code': year,
+ 'company_id': self.company_id,
+ 'date_start': '%s-01-01' % year,
+ 'date_stop': '%s-12-31' % year,
+ })
+ reg('account.fiscalyear').create_period(
+ cr, uid, [fiscalyear_id])
+
+ def setup_payables(self, reg, cr, uid):
+ """
+ Set up suppliers and invoice them. Check that the invoices
+ can be validated properly.
+ """
+ partner_model = reg('res.partner')
+ supplier1 = partner_model.create(
+ cr, uid, {
+ 'name': 'Supplier 1',
+ 'supplier': True,
+ 'country_id': self.country_id,
+ 'bank_ids': [(0, False, {
+ 'state': 'iban',
+ 'acc_number': 'NL42INGB0000454000',
+ 'bank': self.bank_id,
+ 'bank_bic': 'INGBNL2A',
+ })],
+ })
+ supplier2 = partner_model.create(
+ cr, uid, {
+ 'name': 'Supplier 2',
+ 'supplier': True,
+ 'country_id': self.country_id,
+ 'bank_ids': [(0, False, {
+ 'state': 'iban',
+ 'acc_number': 'NL86INGB0002445588',
+ 'bank': self.bank_id,
+ 'bank_bic': 'INGBNL2A',
+ })],
+ })
+ self.payable_id = reg('account.account').search(
+ cr, uid, [
+ ('company_id', '=', self.company_id),
+ ('code', '=', '120000')])[0]
+ expense_id = reg('account.account').search(
+ cr, uid, [
+ ('company_id', '=', self.company_id),
+ ('code', '=', '123000')])[0]
+ invoice_model = reg('account.invoice')
+ values = {
+ 'type': 'in_invoice',
+ 'partner_id': supplier1,
+ 'account_id': self.payable_id,
+ 'invoice_line': [(0, False, {
+ 'name': 'Purchase 1',
+ 'price_unit': 100.0,
+ 'quantity': 1,
+ 'account_id': expense_id,})],
+ }
+ self.invoice_ids = [
+ invoice_model.create(
+ cr, uid, values, context={
+ 'type': 'in_invoice',
+ })]
+ values.update({
+ 'partner_id': supplier2,
+ 'name': 'Purchase 2'})
+ self.invoice_ids.append(
+ invoice_model.create(
+ cr, uid, values, context={
+ 'type': 'in_invoice'}))
+ wf_service = netsvc.LocalService('workflow')
+ for invoice_id in self.invoice_ids:
+ wf_service.trg_validate(
+ uid, 'account.invoice', invoice_id, 'invoice_open', cr)
+ self.assert_invoices_state('open')
+
+ def setup_payment_config(self, reg, cr, uid):
+ """
+ Configure an additional account and journal for payments
+ in transit and configure a payment mode with them.
+ """
+ account_parent_id = reg('account.account').search(
+ cr, uid, [
+ ('company_id', '=', self.company_id),
+ ('parent_id', '=', False)])[0]
+ user_type = reg('ir.model.data').get_object_reference(
+ cr, uid, 'account', 'data_account_type_liability')[1]
+ transfer_account_id = reg('account.account').create(
+ cr, uid, {
+ 'company_id': self.company_id,
+ 'parent_id': account_parent_id,
+ 'code': 'TRANS',
+ 'name': 'Transfer account',
+ 'type': 'other',
+ 'user_type': user_type,
+ 'reconcile': True,
+ })
+ transfer_journal_id = reg('account.journal').search(
+ cr, uid, [
+ ('company_id', '=', self.company_id),
+ ('code', '=', 'MISC')])[0]
+ self.bank_journal_id = reg('account.journal').search(
+ cr, uid, [
+ ('company_id', '=', self.company_id),
+ ('type', '=', 'bank')])[0]
+ payment_mode_type_id = reg('ir.model.data').get_object_reference(
+ cr, uid, 'account_banking_sepa_credit_transfer',
+ 'export_sepa_sct_001_001_03')[1]
+ self.payment_mode_id = reg('payment.mode').create(
+ cr, uid, {
+ 'name': 'SEPA Mode',
+ 'bank_id': self.partner_bank_id,
+ 'journal': self.bank_journal_id,
+ 'company_id': self.company_id,
+ 'transfer_account_id': transfer_account_id,
+ 'transfer_journal_id': transfer_journal_id,
+ 'type': payment_mode_type_id,
+ })
+
+ def setup_payment(self, reg, cr, uid):
+ """
+ Create a payment order with the invoices' payable move lines.
+ Check that the payment order can be confirmed.
+ """
+ self.payment_order_id = reg('payment.order').create(
+ cr, uid, {
+ 'reference': 'PAY001',
+ 'mode': self.payment_mode_id,
+ })
+ context = {'active_id': self.payment_order_id}
+ entries = reg('account.move.line').search(
+ cr, uid, [
+ ('company_id', '=', self.company_id),
+ ('account_id', '=', self.payable_id),
+ ])
+ self.payment_order_create_id = reg('payment.order.create').create(
+ cr, uid, {
+ 'entries': [(6, 0, entries)],
+ }, context=context)
+ reg('payment.order.create').create_payment(
+ cr, uid, [self.payment_order_create_id], context=context)
+ wf_service = netsvc.LocalService('workflow')
+ wf_service.trg_validate(
+ uid, 'payment.order', self.payment_order_id, 'open', cr)
+ self.assert_payment_order_state('open')
+
+ def export_payment(self, reg, cr, uid):
+ """
+ Call the SEPA export wizard on the payment order
+ and check that the payment order and related invoices'
+ states are moved forward afterwards
+ """
+ export_model = reg('banking.export.sepa.wizard')
+ export_id = export_model.create(
+ cr, uid, {
+ 'msg_identification': 'EXP001'},
+ context={'active_ids': [self.payment_order_id]})
+ export_model.create_sepa(
+ cr, uid, [export_id])
+ export_model.save_sepa(
+ cr, uid, [export_id])
+ self.assert_payment_order_state('sent')
+ self.assert_invoices_state('paid')
+
+ def setup_bank_statement(self, reg, cr, uid):
+ """
+ Create a bank statement with a single line. Call the reconciliation
+ wizard to match the line with the open payment order. Confirm the
+ bank statement. Check if the payment order is done.
+ """
+ statement_model = reg('account.bank.statement')
+ line_model = reg('account.bank.statement.line')
+ wizard_model = reg('banking.transaction.wizard')
+ statement_id = statement_model.create(
+ cr, uid, {
+ 'name': 'Statement',
+ 'journal_id': self.bank_journal_id,
+ 'balance_end_real': -200.0,
+ 'period_id': reg('account.period').find(cr, uid)[0]
+ })
+ line_id = line_model.create(
+ cr, uid, {
+ 'name': 'Statement line',
+ 'statement_id': statement_id,
+ 'amount': -200.0,
+ 'account_id': self.payable_id,
+ })
+ wizard_id = wizard_model.create(
+ cr, uid, {'statement_line_id': line_id})
+ wizard_model.write(
+ cr, uid, [wizard_id], {
+ 'manual_payment_order_id': self.payment_order_id})
+ statement_model.button_confirm_bank(cr, uid, [statement_id])
+ state = reg('payment.order').read(
+ cr, uid, self.payment_order_id, ['state'])['state']
+ assert state == 'done', 'Payment order does not go into state \'done\'.'
+
+ def check_reconciliations(self, reg, cr, uid):
+ """
+ Check if the payment order has any lines and that
+ the transit move lines of those payment lines are
+ reconciled by now.
+ """
+ payment_order = reg('payment.order').browse(
+ cr, uid, self.payment_order_id)
+ assert payment_order.line_ids, 'Payment order has no payment lines'
+ for line in payment_order.line_ids:
+ assert line.transit_move_line_id, \
+ 'Payment order has no transfer move line'
+ assert line.transit_move_line_id.reconcile_id, \
+ 'Transfer move line on payment line is not reconciled'
+
+ def test_payment_roundtrip(self):
+ reg, cr, uid, = self.registry, self.cr, self.uid
+ self.setup_company(reg, cr, uid)
+ self.setup_chart(reg, cr, uid)
+ self.setup_payables(reg, cr, uid)
+ self.setup_payment_config(reg, cr, uid)
+ self.setup_payment(reg, cr, uid)
+ self.export_payment(reg, cr, uid)
+ self.setup_bank_statement(reg, cr, uid)
+ self.check_reconciliations(reg, cr, uid)
Follow ups