From ce6a6d6852f35d635f2bce62ea495c37eca50ec1 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Tue, 28 Feb 2017 18:45:32 +0100 Subject: [PATCH] [ADD] Adyen statement import --- .../README.rst | 69 +++++++++ .../__init__.py | 1 + .../__openerp__.py | 18 +++ .../models/__init__.py | 2 + .../models/account_bank_statement_import.py | 139 ++++++++++++++++++ .../models/account_journal.py | 10 ++ .../test_files/adyen_test.xlsx | Bin 0 -> 17972 bytes .../test_files/adyen_test_credit_fees.xlsx | Bin 0 -> 18800 bytes .../tests/__init__.py | 1 + .../tests/test_import_adyen.py | 55 +++++++ .../views/account_journal.xml | 15 ++ 11 files changed, 310 insertions(+) create mode 100644 account_bank_statement_import_adyen/README.rst create mode 100644 account_bank_statement_import_adyen/__init__.py create mode 100644 account_bank_statement_import_adyen/__openerp__.py create mode 100644 account_bank_statement_import_adyen/models/__init__.py create mode 100644 account_bank_statement_import_adyen/models/account_bank_statement_import.py create mode 100644 account_bank_statement_import_adyen/models/account_journal.py create mode 100644 account_bank_statement_import_adyen/test_files/adyen_test.xlsx create mode 100644 account_bank_statement_import_adyen/test_files/adyen_test_credit_fees.xlsx create mode 100644 account_bank_statement_import_adyen/tests/__init__.py create mode 100644 account_bank_statement_import_adyen/tests/test_import_adyen.py create mode 100644 account_bank_statement_import_adyen/views/account_journal.xml diff --git a/account_bank_statement_import_adyen/README.rst b/account_bank_statement_import_adyen/README.rst new file mode 100644 index 00000000..9b6baaba --- /dev/null +++ b/account_bank_statement_import_adyen/README.rst @@ -0,0 +1,69 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +====================== +Adyen statement import +====================== + +This module processes Adyen transaction statements in xlsx format. You can +import the statements in a dedicated journal. Reconcile your sale invoices +with the credit transations. Reconcile the aggregated counterpart +transaction with the transaction in your real bank journal and register the +aggregated fee line containing commision and markup on the applicable +cost account. + +Configuration +============= + +Configure a pseudo bank journal by creating a new journal with a dedicated +Adyen clearing account as the default ledger account. Set your merchant +account string in the Advanced settings on the journal form. + +Usage +===== + +After installing this module, you can import your Adyen transaction statements +through Menu Finance -> Bank -> Import. Don't enter a journal in the import +wizard. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/174/8.0 + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Stefan Rijnhart + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/account_bank_statement_import_adyen/__init__.py b/account_bank_statement_import_adyen/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/account_bank_statement_import_adyen/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_bank_statement_import_adyen/__openerp__.py b/account_bank_statement_import_adyen/__openerp__.py new file mode 100644 index 00000000..6f47e712 --- /dev/null +++ b/account_bank_statement_import_adyen/__openerp__.py @@ -0,0 +1,18 @@ +# coding: utf-8 +# © 2017 Opener BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + 'name': 'Adyen statement import', + 'version': '8.0.1.0.0', + 'author': 'Opener BV, Odoo Community Association (OCA)', + 'category': 'Banking addons', + 'website': 'https://github.com/oca/bank-statement-import', + 'depends': [ + 'account_bank_statement_import', + 'account_bank_statement_clearing_account', + ], + 'data': [ + 'views/account_journal.xml', + ], + 'installable': True, +} diff --git a/account_bank_statement_import_adyen/models/__init__.py b/account_bank_statement_import_adyen/models/__init__.py new file mode 100644 index 00000000..ba1f4934 --- /dev/null +++ b/account_bank_statement_import_adyen/models/__init__.py @@ -0,0 +1,2 @@ +from . import account_bank_statement_import +from . import account_journal diff --git a/account_bank_statement_import_adyen/models/account_bank_statement_import.py b/account_bank_statement_import_adyen/models/account_bank_statement_import.py new file mode 100644 index 00000000..aae90b71 --- /dev/null +++ b/account_bank_statement_import_adyen/models/account_bank_statement_import.py @@ -0,0 +1,139 @@ +# coding: utf-8 +# © 2017 Opener BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from io import BytesIO +from openpyxl import load_workbook +from zipfile import BadZipfile + +from openerp import models, api +from openerp.exceptions import Warning as UserError +from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT as DATEFMT +from openerp.tools.translate import _ +from openerp.addons.account_bank_statement_import.parserlib import ( + BankStatement) + + +class Import(models.TransientModel): + _inherit = 'account.bank.statement.import' + + @api.model + def _parse_file(self, data_file): + """Parse an Adyen xlsx file and map merchant account strings + to journals. """ + try: + statements = self.import_adyen_xlsx(data_file) + except ValueError: + return super(Import, self)._parse_file(data_file) + + for statement in statements: + merchant_id = statement['account_number'] + journal = self.env['account.journal'].search([ + ('adyen_merchant_account', '=', merchant_id)], limit=1) + if journal: + statement['adyen_journal_id'] = journal.id + else: + raise UserError( + _('Please create a journal with merchant account "%s"') % + merchant_id) + statement['account_number'] = False + return statements + + @api.model + def _import_statement(self, stmt_vals): + """ Propagate found journal to context, fromwhere it is picked up + in _get_journal """ + journal_id = stmt_vals.pop('adyen_journal_id', None) + if journal_id: + self = self.with_context(journal_id=journal_id) + return super(Import, self)._import_statement(stmt_vals) + + @api.model + def balance(self, row): + return -(row[15] or 0) + sum( + row[i] if row[i] else 0.0 + for i in (16, 17, 18, 19, 20)) + + @api.model + def import_adyen_transaction(self, statement, row): + transaction = statement.create_transaction() + transaction.value_date = row[6].strftime(DATEFMT) + transaction.transferred_amount = self.balance(row) + transaction.note = ( + '%s %s %s %s' % (row[2], row[3], row[4], row[21])) + transaction.message = "%s" % (row[3] or row[4] or row[9]) + return transaction + + @api.model + def import_adyen_xlsx(self, data_file): + statements = [] + statement = None + headers = False + fees = 0.0 + balance = 0.0 + payout = 0.0 + + with BytesIO() as buf: + buf.write(data_file) + try: + sheet = load_workbook(buf)._sheets[0] + except BadZipfile as e: + raise ValueError(e) + for row in sheet.rows: + row = [cell.value for cell in row] + if len(row) != 31: + raise ValueError( + 'Not an Adyen statement. Unexpected row length %s ' + 'instead of 31' % len(row)) + if not row[1]: + continue + if not headers: + if row[1] != 'Company Account': + raise ValueError( + 'Not an Adyen statement. Unexpected header "%s" ' + 'instead of "Company Account"', row[1]) + headers = True + continue + if not statement: + statement = BankStatement() + statements.append(statement) + statement.statement_id = '%s %s/%s' % ( + row[2], row[6].strftime('%Y'), int(row[23])) + statement.local_currency = row[14] + statement.local_account = row[2] + date = row[6].strftime(DATEFMT) + if not statement.date or statement.date > date: + statement.date = date + + row[8] = row[8].strip() + if row[8] == 'MerchantPayout': + payout -= self.balance(row) + else: + balance += self.balance(row) + self.import_adyen_transaction(statement, row) + fees += sum( + row[i] if row[i] else 0.0 + for i in (17, 18, 19, 20)) + + if not headers: + raise ValueError( + 'Not an Adyen statement. Did not encounter header row.') + + if fees: + transaction = statement.create_transaction() + transaction.value_date = max( + t.value_date for t in statement['transactions']) + transaction.transferred_amount = -fees + balance -= fees + transaction.message = 'Commision, markup etc. batch %s' % ( + int(row[23])) + + if statement['transactions'] and not payout: + raise UserError( + _('No payout detected in Adyen statement.')) + if self.env.user.company_id.currency_id.compare_amounts( + balance, payout) != 0: + raise UserError( + _('Parse error. Balance %s not equal to merchant ' + 'payout %s') % (balance, payout)) + + return statements diff --git a/account_bank_statement_import_adyen/models/account_journal.py b/account_bank_statement_import_adyen/models/account_journal.py new file mode 100644 index 00000000..d0c431fd --- /dev/null +++ b/account_bank_statement_import_adyen/models/account_journal.py @@ -0,0 +1,10 @@ +# coding: utf-8 +from openerp import fields, models + + +class Journal(models.Model): + _inherit = 'account.journal' + + adyen_merchant_account = fields.Char( + help=('Fill in the exact merchant account string to select this ' + 'journal when importing Adyen statements')) diff --git a/account_bank_statement_import_adyen/test_files/adyen_test.xlsx b/account_bank_statement_import_adyen/test_files/adyen_test.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3adaa8dbf10f9a2a48f2e2538a5f15bc86756b46 GIT binary patch literal 17972 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 E08#;WUH||9 literal 0 HcmV?d00001 diff --git a/account_bank_statement_import_adyen/test_files/adyen_test_credit_fees.xlsx b/account_bank_statement_import_adyen/test_files/adyen_test_credit_fees.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0443fceb3eae260220b96d33b06cf1e8032153ed GIT binary patch literal 18800 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 literal 0 HcmV?d00001 diff --git a/account_bank_statement_import_adyen/tests/__init__.py b/account_bank_statement_import_adyen/tests/__init__.py new file mode 100644 index 00000000..f53fb980 --- /dev/null +++ b/account_bank_statement_import_adyen/tests/__init__.py @@ -0,0 +1 @@ +from . import test_import_adyen diff --git a/account_bank_statement_import_adyen/tests/test_import_adyen.py b/account_bank_statement_import_adyen/tests/test_import_adyen.py new file mode 100644 index 00000000..d4e8a684 --- /dev/null +++ b/account_bank_statement_import_adyen/tests/test_import_adyen.py @@ -0,0 +1,55 @@ +# coding: utf-8 +from openerp.addons.account_bank_statement_import.tests import ( + TestStatementFile) + + +class TestImportAdyen(TestStatementFile): + def setUp(self): + super(TestImportAdyen, self).setUp() + self.journal = self.env['account.journal'].search( + [('type', '=', 'bank')], limit=1) + self.journal.default_debit_account_id.reconcile = True + self.journal.write({ + 'adyen_merchant_account': 'YOURCOMPANY_ACCOUNT', + 'update_posted': True, + }) + + def test_import_adyen(self): + self._test_statement_import( + 'account_bank_statement_import_adyen', 'adyen_test.xlsx', + 'YOURCOMPANY_ACCOUNT 2016/48') + statement = self.env['account.bank.statement'].search( + [], order='create_date desc', limit=1) + self.assertEqual(len(statement.line_ids), 22) + self.assertTrue( + self.env.user.company_id.currency_id.is_zero( + sum(line.amount for line in statement.line_ids))) + + account = self.env['account.account'].search([( + 'type', '=', 'receivable')], limit=1) + for line in statement.line_ids: + line.process_reconciliation([{ + 'debit': -line.amount if line.amount < 0 else 0, + 'credit': line.amount if line.amount > 0 else 0, + 'account_id': account.id}]) + + statement.button_confirm_bank() + self.assertEqual(statement.state, 'confirm') + lines = self.env['account.move.line'].search([ + ('account_id', '=', self.journal.default_debit_account_id.id), + ('statement_id', '=', statement.id)]) + reconcile = lines.mapped('reconcile_id') + self.assertEqual(len(reconcile), 1) + self.assertFalse(lines.mapped('reconcile_partial_id')) + self.assertEqual(lines, reconcile.line_id) + + statement.button_draft() + self.assertEqual(statement.state, 'draft') + self.assertFalse(lines.mapped('reconcile_partial_id')) + self.assertFalse(lines.mapped('reconcile_id')) + + def test_import_adyen_credit_fees(self): + self._test_statement_import( + 'account_bank_statement_import_adyen', + 'adyen_test_credit_fees.xlsx', + 'YOURCOMPANY_ACCOUNT 2016/8') diff --git a/account_bank_statement_import_adyen/views/account_journal.xml b/account_bank_statement_import_adyen/views/account_journal.xml new file mode 100644 index 00000000..2e6f2e6b --- /dev/null +++ b/account_bank_statement_import_adyen/views/account_journal.xml @@ -0,0 +1,15 @@ + + + + + Add Adyen merchant account + account.journal + + + + + + + + +