diff --git a/account_bank_statement_import_split/__manifest__.py b/account_bank_statement_import_split/__manifest__.py index 4d4162c9..434819e3 100644 --- a/account_bank_statement_import_split/__manifest__.py +++ b/account_bank_statement_import_split/__manifest__.py @@ -3,21 +3,15 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { - 'name': 'Account Bank Statement Import: Split by date', - 'version': '12.0.1.0.1', - 'author': - 'CorporateHub, ' - 'Odoo Community Association (OCA)', - 'maintainers': ['alexey-pelykh'], - 'website': 'https://github.com/OCA/bank-statement-import/', - 'license': 'AGPL-3', - 'category': 'Accounting', - 'summary': 'Split statements by date during import', - 'depends': [ - 'account_bank_statement_import', - ], - 'data': [ - 'views/account_bank_statement_import.xml', - ], - 'installable': True, + "name": "Account Bank Statement Import: Split by date", + "version": "12.0.1.0.1", + "author": "CorporateHub, " "Odoo Community Association (OCA)", + "maintainers": ["alexey-pelykh"], + "website": "https://github.com/OCA/bank-statement-import/", + "license": "AGPL-3", + "category": "Accounting", + "summary": "Split statements by date during import", + "depends": ["account_bank_statement_import",], + "data": ["views/account_bank_statement_import.xml",], + "installable": True, } diff --git a/account_bank_statement_import_split/models/account_bank_statement_import.py b/account_bank_statement_import_split/models/account_bank_statement_import.py index c28f6b0c..a73adac0 100644 --- a/account_bank_statement_import_split/models/account_bank_statement_import.py +++ b/account_bank_statement_import_split/models/account_bank_statement_import.py @@ -1,54 +1,57 @@ # Copyright 2019 Brainbean Apps (https://brainbeanapps.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models - -from dateutil.relativedelta import relativedelta, MO from decimal import Decimal +from dateutil.relativedelta import MO, relativedelta + +from odoo import api, fields, models + class AccountBankStatementImport(models.TransientModel): - _inherit = 'account.bank.statement.import' + _inherit = "account.bank.statement.import" import_mode = fields.Selection( selection=[ - ('single', 'Single statement'), - ('daily', 'Daily statements'), - ('weekly', 'Weekly statements'), - ('monthly', 'Monthly statements'), + ("single", "Single statement"), + ("daily", "Daily statements"), + ("weekly", "Weekly statements"), + ("monthly", "Monthly statements"), ], - default='single', + default="single", ) def _complete_stmts_vals(self, stmts_vals, journal, account_number): - stmts_vals = super()._complete_stmts_vals( - stmts_vals, - journal, - account_number - ) - if not self.import_mode or self.import_mode == 'single': + stmts_vals = super()._complete_stmts_vals(stmts_vals, journal, account_number) + if not self.import_mode or self.import_mode == "single": return stmts_vals statements = [] for st_vals in stmts_vals: - transactions = list(sorted( - map( - lambda transaction: self._prepare_transaction( - transaction + transactions = list( + sorted( + map( + lambda transaction: self._prepare_transaction(transaction), + st_vals["transactions"], ), - st_vals['transactions'] - ), - key=lambda transaction: transaction['date'] - )) + key=lambda transaction: transaction["date"], + ) + ) if not transactions: continue - del st_vals['transactions'] + del st_vals["transactions"] - balance_start = Decimal(st_vals['balance_start']) \ - if 'balance_start' in st_vals else None - balance_end = Decimal(st_vals['balance_end_real']) \ - if 'balance_end_real' in st_vals else None + balance_start = ( + Decimal(st_vals["balance_start"]) + if "balance_start" in st_vals + else None + ) + balance_end = ( + Decimal(st_vals["balance_end_real"]) + if "balance_end_real" in st_vals + else None + ) statement_date_since = self._get_statement_date_since( - transactions[0]['date'] + transactions[0]["date"] ) while transactions: statement_date_until = ( @@ -57,7 +60,7 @@ class AccountBankStatementImport(models.TransientModel): last_transaction_index = None for index, transaction in enumerate(transactions): - if transaction['date'] >= statement_date_until: + if transaction["date"] >= statement_date_until: break last_transaction_index = index if last_transaction_index is None: @@ -65,36 +68,34 @@ class AccountBankStatementImport(models.TransientModel): statement_date_since = statement_date_until continue - statement_transactions = \ - transactions[0:last_transaction_index + 1] - transactions = transactions[last_transaction_index + 1:] + statement_transactions = transactions[0 : last_transaction_index + 1] + transactions = transactions[last_transaction_index + 1 :] statement_values = dict(st_vals) - statement_values.update({ - 'name': self._get_statement_name( - journal, - statement_date_since, - statement_date_until, - ), - 'date': self._get_statement_date( - statement_date_since, - statement_date_until, - ), - 'transactions': statement_transactions, - }) + statement_values.update( + { + "name": self._get_statement_name( + journal, statement_date_since, statement_date_until, + ), + "date": self._get_statement_date( + statement_date_since, statement_date_until, + ), + "transactions": statement_transactions, + } + ) if balance_start is not None: - statement_values.update({ - 'balance_start': float(balance_start), - }) + statement_values.update( + {"balance_start": float(balance_start),} + ) for transaction in statement_transactions: - balance_start += Decimal(transaction['amount']) + balance_start += Decimal(transaction["amount"]) if balance_end is not None: statement_balance_end = balance_end for transaction in transactions: - statement_balance_end -= Decimal(transaction['amount']) - statement_values.update({ - 'balance_end_real': float(statement_balance_end), - }) + statement_balance_end -= Decimal(transaction["amount"]) + statement_values.update( + {"balance_end_real": float(statement_balance_end),} + ) statements.append(statement_values) statement_date_since = statement_date_until @@ -102,40 +103,30 @@ class AccountBankStatementImport(models.TransientModel): @api.multi def _prepare_transaction(self, transaction): - transaction.update({ - 'date': fields.Date.from_string(transaction['date']), - }) + transaction.update( + {"date": fields.Date.from_string(transaction["date"]),} + ) return transaction @api.multi def _get_statement_date_since(self, date): self.ensure_one() - if self.import_mode == 'daily': + if self.import_mode == "daily": return date - elif self.import_mode == 'weekly': + elif self.import_mode == "weekly": return date + relativedelta(weekday=MO(-1)) - elif self.import_mode == 'monthly': - return date.replace( - day=1, - ) + elif self.import_mode == "monthly": + return date.replace(day=1,) @api.multi def _get_statement_date_step(self): self.ensure_one() - if self.import_mode == 'daily': - return relativedelta( - days=1, - ) - elif self.import_mode == 'weekly': - return relativedelta( - weeks=1, - weekday=MO, - ) - elif self.import_mode == 'monthly': - return relativedelta( - months=1, - day=1, - ) + if self.import_mode == "daily": + return relativedelta(days=1,) + elif self.import_mode == "weekly": + return relativedelta(weeks=1, weekday=MO,) + elif self.import_mode == "monthly": + return relativedelta(months=1, day=1,) @api.multi def _get_statement_date(self, date_since, date_until): diff --git a/account_bank_statement_import_split/tests/test_account_bank_statement_import_split.py b/account_bank_statement_import_split/tests/test_account_bank_statement_import_split.py index d352fc36..5b167998 100644 --- a/account_bank_statement_import_split/tests/test_account_bank_statement_import_split.py +++ b/account_bank_statement_import_split/tests/test_account_bank_statement_import_split.py @@ -1,159 +1,166 @@ # Copyright 2019 Brainbean Apps (https://brainbeanapps.com) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import fields -from odoo.tests import common - from base64 import b64encode from unittest import mock +from odoo import fields +from odoo.tests import common + _parse_file_method = ( - 'odoo.addons.account_bank_statement_import' - '.account_bank_statement_import.AccountBankStatementImport._parse_file' + "odoo.addons.account_bank_statement_import" + ".account_bank_statement_import.AccountBankStatementImport._parse_file" ) class TestAccountBankAccountStatementImportSplit(common.TransactionCase): - def setUp(self): super().setUp() self.now = fields.Datetime.now() - self.currency_usd = self.env.ref('base.USD') + self.currency_usd = self.env.ref("base.USD") self.empty_data_file = b64encode( - 'TestAccountBankAccountStatementImportSplit'.encode('utf-8') + b"TestAccountBankAccountStatementImportSplit" ) - self.AccountJournal = self.env['account.journal'] - self.AccountBankStatement = self.env['account.bank.statement'] - self.AccountBankStatementImport = self.env[ - 'account.bank.statement.import' - ] + self.AccountJournal = self.env["account.journal"] + self.AccountBankStatement = self.env["account.bank.statement"] + self.AccountBankStatementImport = self.env["account.bank.statement.import"] def test_default_import_mode(self): - journal = self.AccountJournal.create({ - 'name': 'Bank', - 'type': 'bank', - 'code': 'BANK', - 'currency_id': self.currency_usd.id, - }) - wizard = self.AccountBankStatementImport.with_context({ - 'journal_id': journal.id, - }).create({ - 'filename': 'file.ext', - 'data_file': self.empty_data_file, - }) + journal = self.AccountJournal.create( + { + "name": "Bank", + "type": "bank", + "code": "BANK", + "currency_id": self.currency_usd.id, + } + ) + wizard = self.AccountBankStatementImport.with_context( + {"journal_id": journal.id,} + ).create({"filename": "file.ext", "data_file": self.empty_data_file,}) data = ( journal.currency_id.name, journal.bank_account_id.acc_number, - [{ - 'name': 'STATEMENT', - 'date': '2019-01-01', - 'balance_start': 0.0, - 'balance_end_real': 100.0, - 'transactions': [{ - 'name': 'TRANSACTION', - 'amount': '100.0', - 'date': '2019-01-01', - 'note': 'NOTE', - 'unique_import_id': 'TRANSACTION-ID', - }], - }], + [ + { + "name": "STATEMENT", + "date": "2019-01-01", + "balance_start": 0.0, + "balance_end_real": 100.0, + "transactions": [ + { + "name": "TRANSACTION", + "amount": "100.0", + "date": "2019-01-01", + "note": "NOTE", + "unique_import_id": "TRANSACTION-ID", + } + ], + } + ], ) with mock.patch(_parse_file_method, return_value=data): - wizard.with_context({ - 'journal_id': journal.id, - }).import_file() - statement = self.AccountBankStatement.search([ - ('journal_id', '=', journal.id), - ]) + wizard.with_context({"journal_id": journal.id,}).import_file() + statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),]) self.assertEqual(len(statement), 1) self.assertEqual(len(statement.line_ids), 1) def test_single_import_mode(self): - journal = self.AccountJournal.create({ - 'name': 'Bank', - 'type': 'bank', - 'code': 'BANK', - 'currency_id': self.currency_usd.id, - }) - wizard = self.AccountBankStatementImport.with_context({ - 'journal_id': journal.id, - }).create({ - 'filename': 'file.ext', - 'data_file': self.empty_data_file, - 'import_mode': 'single', - }) + journal = self.AccountJournal.create( + { + "name": "Bank", + "type": "bank", + "code": "BANK", + "currency_id": self.currency_usd.id, + } + ) + wizard = self.AccountBankStatementImport.with_context( + {"journal_id": journal.id,} + ).create( + { + "filename": "file.ext", + "data_file": self.empty_data_file, + "import_mode": "single", + } + ) data = ( journal.currency_id.name, journal.bank_account_id.acc_number, - [{ - 'name': 'STATEMENT', - 'date': '2019-01-01', - 'balance_start': 0.0, - 'balance_end_real': 100.0, - 'transactions': [{ - 'name': 'TRANSACTION', - 'amount': '100.0', - 'date': '2019-01-01', - 'note': 'NOTE', - 'unique_import_id': 'TRANSACTION-ID', - }], - }], + [ + { + "name": "STATEMENT", + "date": "2019-01-01", + "balance_start": 0.0, + "balance_end_real": 100.0, + "transactions": [ + { + "name": "TRANSACTION", + "amount": "100.0", + "date": "2019-01-01", + "note": "NOTE", + "unique_import_id": "TRANSACTION-ID", + } + ], + } + ], ) with mock.patch(_parse_file_method, return_value=data): - wizard.with_context({ - 'journal_id': journal.id, - }).import_file() - statement = self.AccountBankStatement.search([ - ('journal_id', '=', journal.id), - ]) + wizard.with_context({"journal_id": journal.id,}).import_file() + statement = self.AccountBankStatement.search([("journal_id", "=", journal.id),]) self.assertEqual(len(statement), 1) self.assertEqual(len(statement.line_ids), 1) def test_daily_import_mode(self): - journal = self.AccountJournal.create({ - 'name': 'Bank', - 'type': 'bank', - 'code': 'BANK', - 'currency_id': self.currency_usd.id, - }) - wizard = self.AccountBankStatementImport.with_context({ - 'journal_id': journal.id, - }).create({ - 'filename': 'file.ext', - 'data_file': self.empty_data_file, - 'import_mode': 'daily', - }) + journal = self.AccountJournal.create( + { + "name": "Bank", + "type": "bank", + "code": "BANK", + "currency_id": self.currency_usd.id, + } + ) + wizard = self.AccountBankStatementImport.with_context( + {"journal_id": journal.id,} + ).create( + { + "filename": "file.ext", + "data_file": self.empty_data_file, + "import_mode": "daily", + } + ) data = ( journal.currency_id.name, journal.bank_account_id.acc_number, - [{ - 'name': 'STATEMENT', - 'date': '2019-01-01', - 'balance_start': 0.0, - 'balance_end_real': 100.0, - 'transactions': [{ - 'name': 'TRANSACTION-1', - 'amount': '50.0', - 'date': '2019-01-01', - 'note': 'NOTE', - 'unique_import_id': 'TRANSACTION-ID-1', - }, { - 'name': 'TRANSACTION-2', - 'amount': '50.0', - 'date': '2019-01-03', - 'note': 'NOTE', - 'unique_import_id': 'TRANSACTION-ID-2', - }], - }], + [ + { + "name": "STATEMENT", + "date": "2019-01-01", + "balance_start": 0.0, + "balance_end_real": 100.0, + "transactions": [ + { + "name": "TRANSACTION-1", + "amount": "50.0", + "date": "2019-01-01", + "note": "NOTE", + "unique_import_id": "TRANSACTION-ID-1", + }, + { + "name": "TRANSACTION-2", + "amount": "50.0", + "date": "2019-01-03", + "note": "NOTE", + "unique_import_id": "TRANSACTION-ID-2", + }, + ], + } + ], ) with mock.patch(_parse_file_method, return_value=data): - wizard.with_context({ - 'journal_id': journal.id, - }).import_file() - statements = self.AccountBankStatement.search([ - ('journal_id', '=', journal.id), - ]).sorted(key=lambda statement: statement.date) + wizard.with_context({"journal_id": journal.id,}).import_file() + statements = self.AccountBankStatement.search( + [("journal_id", "=", journal.id),] + ).sorted(key=lambda statement: statement.date) self.assertEqual(len(statements), 2) self.assertEqual(len(statements[0].line_ids), 1) self.assertEqual(statements[0].balance_start, 0.0) @@ -163,49 +170,56 @@ class TestAccountBankAccountStatementImportSplit(common.TransactionCase): self.assertEqual(statements[1].balance_end_real, 100.0) def test_weekly_import_mode(self): - journal = self.AccountJournal.create({ - 'name': 'Bank', - 'type': 'bank', - 'code': 'BANK', - 'currency_id': self.currency_usd.id, - }) - wizard = self.AccountBankStatementImport.with_context({ - 'journal_id': journal.id, - }).create({ - 'filename': 'file.ext', - 'data_file': self.empty_data_file, - 'import_mode': 'weekly', - }) + journal = self.AccountJournal.create( + { + "name": "Bank", + "type": "bank", + "code": "BANK", + "currency_id": self.currency_usd.id, + } + ) + wizard = self.AccountBankStatementImport.with_context( + {"journal_id": journal.id,} + ).create( + { + "filename": "file.ext", + "data_file": self.empty_data_file, + "import_mode": "weekly", + } + ) data = ( journal.currency_id.name, journal.bank_account_id.acc_number, - [{ - 'name': 'STATEMENT', - 'date': '2019-01-01', - 'balance_start': 0.0, - 'balance_end_real': 100.0, - 'transactions': [{ - 'name': 'TRANSACTION-1', - 'amount': '50.0', - 'date': '2019-01-01', - 'note': 'NOTE', - 'unique_import_id': 'TRANSACTION-ID-1', - }, { - 'name': 'TRANSACTION-2', - 'amount': '50.0', - 'date': '2019-01-15', - 'note': 'NOTE', - 'unique_import_id': 'TRANSACTION-ID-2', - }], - }], + [ + { + "name": "STATEMENT", + "date": "2019-01-01", + "balance_start": 0.0, + "balance_end_real": 100.0, + "transactions": [ + { + "name": "TRANSACTION-1", + "amount": "50.0", + "date": "2019-01-01", + "note": "NOTE", + "unique_import_id": "TRANSACTION-ID-1", + }, + { + "name": "TRANSACTION-2", + "amount": "50.0", + "date": "2019-01-15", + "note": "NOTE", + "unique_import_id": "TRANSACTION-ID-2", + }, + ], + } + ], ) with mock.patch(_parse_file_method, return_value=data): - wizard.with_context({ - 'journal_id': journal.id, - }).import_file() - statements = self.AccountBankStatement.search([ - ('journal_id', '=', journal.id), - ]).sorted(key=lambda statement: statement.date) + wizard.with_context({"journal_id": journal.id,}).import_file() + statements = self.AccountBankStatement.search( + [("journal_id", "=", journal.id),] + ).sorted(key=lambda statement: statement.date) self.assertEqual(len(statements), 2) self.assertEqual(len(statements[0].line_ids), 1) self.assertEqual(statements[0].balance_start, 0.0) @@ -215,49 +229,56 @@ class TestAccountBankAccountStatementImportSplit(common.TransactionCase): self.assertEqual(statements[1].balance_end_real, 100.0) def test_monthly_import_mode(self): - journal = self.AccountJournal.create({ - 'name': 'Bank', - 'type': 'bank', - 'code': 'BANK', - 'currency_id': self.currency_usd.id, - }) - wizard = self.AccountBankStatementImport.with_context({ - 'journal_id': journal.id, - }).create({ - 'filename': 'file.ext', - 'data_file': self.empty_data_file, - 'import_mode': 'monthly', - }) + journal = self.AccountJournal.create( + { + "name": "Bank", + "type": "bank", + "code": "BANK", + "currency_id": self.currency_usd.id, + } + ) + wizard = self.AccountBankStatementImport.with_context( + {"journal_id": journal.id,} + ).create( + { + "filename": "file.ext", + "data_file": self.empty_data_file, + "import_mode": "monthly", + } + ) data = ( journal.currency_id.name, journal.bank_account_id.acc_number, - [{ - 'name': 'STATEMENT', - 'date': '2019-01-01', - 'balance_start': 0.0, - 'balance_end_real': 100.0, - 'transactions': [{ - 'name': 'TRANSACTION-1', - 'amount': '50.0', - 'date': '2019-01-01', - 'note': 'NOTE', - 'unique_import_id': 'TRANSACTION-ID-1', - }, { - 'name': 'TRANSACTION-2', - 'amount': '50.0', - 'date': '2019-03-01', - 'note': 'NOTE', - 'unique_import_id': 'TRANSACTION-ID-2', - }], - }], + [ + { + "name": "STATEMENT", + "date": "2019-01-01", + "balance_start": 0.0, + "balance_end_real": 100.0, + "transactions": [ + { + "name": "TRANSACTION-1", + "amount": "50.0", + "date": "2019-01-01", + "note": "NOTE", + "unique_import_id": "TRANSACTION-ID-1", + }, + { + "name": "TRANSACTION-2", + "amount": "50.0", + "date": "2019-03-01", + "note": "NOTE", + "unique_import_id": "TRANSACTION-ID-2", + }, + ], + } + ], ) with mock.patch(_parse_file_method, return_value=data): - wizard.with_context({ - 'journal_id': journal.id, - }).import_file() - statements = self.AccountBankStatement.search([ - ('journal_id', '=', journal.id), - ]).sorted(key=lambda statement: statement.date) + wizard.with_context({"journal_id": journal.id,}).import_file() + statements = self.AccountBankStatement.search( + [("journal_id", "=", journal.id),] + ).sorted(key=lambda statement: statement.date) self.assertEqual(len(statements), 2) self.assertEqual(len(statements[0].line_ids), 1) self.assertEqual(statements[0].balance_start, 0.0) diff --git a/account_bank_statement_import_split/views/account_bank_statement_import.xml b/account_bank_statement_import_split/views/account_bank_statement_import.xml index fe35a52f..c1c4541c 100644 --- a/account_bank_statement_import_split/views/account_bank_statement_import.xml +++ b/account_bank_statement_import_split/views/account_bank_statement_import.xml @@ -1,19 +1,21 @@ - + - account.bank.statement.import - + -

Please select how you'd like to split the imported statement file:

- +

Please select how you'd like to split the imported statement file:

+
-
diff --git a/setup/account_bank_statement_import_split/odoo/addons/account_bank_statement_import_split b/setup/account_bank_statement_import_split/odoo/addons/account_bank_statement_import_split new file mode 120000 index 00000000..2687a326 --- /dev/null +++ b/setup/account_bank_statement_import_split/odoo/addons/account_bank_statement_import_split @@ -0,0 +1 @@ +../../../../account_bank_statement_import_split \ No newline at end of file diff --git a/setup/account_bank_statement_import_split/setup.py b/setup/account_bank_statement_import_split/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/account_bank_statement_import_split/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)