diff --git a/account_bank_statement_import_guess_partner/README.rst b/account_bank_statement_import_guess_partner/README.rst new file mode 100644 index 00000000..014d4f3b --- /dev/null +++ b/account_bank_statement_import_guess_partner/README.rst @@ -0,0 +1,74 @@ +========================================== +Guess partner on import of statement lines +========================================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fbank--statement--import-lightgray.png?logo=github + :target: https://github.com/OCA/bank-statement-import/tree/13.0/account_bank_statement_import_guess_partner + :alt: OCA/bank-statement-import +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/bank-statement-import-13-0/bank-statement-import-13-0-account_bank_statement_import_guess_partner + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/174/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module uses the ref in an imported transaction to find the partner from the +invoice if possible, and if not set already. + +**Table of contents** + +.. contents:: + :local: + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Therp BV + +Contributors +~~~~~~~~~~~~ + +* Ronald Portier - Therp BV + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +This module is part of the `OCA/bank-statement-import `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_bank_statement_import_guess_partner/__init__.py b/account_bank_statement_import_guess_partner/__init__.py new file mode 100644 index 00000000..31660d6a --- /dev/null +++ b/account_bank_statement_import_guess_partner/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import models diff --git a/account_bank_statement_import_guess_partner/__manifest__.py b/account_bank_statement_import_guess_partner/__manifest__.py new file mode 100644 index 00000000..171aae44 --- /dev/null +++ b/account_bank_statement_import_guess_partner/__manifest__.py @@ -0,0 +1,11 @@ +# Copyright 2022 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Guess partner on import of statement lines", + "version": "13.0.1.0.0", + "category": "Invoicing Management", + "website": "https://github.com/OCA/bank-statement-import", + "author": "Therp BV, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["account_bank_statement_import", "sale"], +} diff --git a/account_bank_statement_import_guess_partner/models/__init__.py b/account_bank_statement_import_guess_partner/models/__init__.py new file mode 100644 index 00000000..6e0045ad --- /dev/null +++ b/account_bank_statement_import_guess_partner/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +"""Import models.""" +from . import account_bank_statement_import diff --git a/account_bank_statement_import_guess_partner/models/account_bank_statement_import.py b/account_bank_statement_import_guess_partner/models/account_bank_statement_import.py new file mode 100644 index 00000000..3d50f888 --- /dev/null +++ b/account_bank_statement_import_guess_partner/models/account_bank_statement_import.py @@ -0,0 +1,59 @@ +# Copyright 2022 Therp BV . +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +"""Try to determine partner from ref in transaction and from invoice.""" +from odoo import models + + +class AccountBankStatementImport(models.TransientModel): + """Try to determine partner from ref in transaction and from invoice.""" + + _inherit = "account.bank.statement.import" + + def _complete_stmts_vals(self, stmts_vals, journal, account_number): + """Try to find partner for each transaction.""" + stmts_vals = super()._complete_stmts_vals(stmts_vals, journal, account_number) + # Loop over statements. + for statement in stmts_vals: + # Loop over transactions in statement. + for transaction in statement["transactions"]: + self._complete_transaction(transaction) + return stmts_vals + + def _complete_transaction(self, transaction): + """Find partner by searching invoice with reference or so name.""" + if transaction.get("partner_id", False): + return + invoice_model = self.env["account.move"] + sale_order_model = self.env["sale.order"] + invoice = None + transaction_keys = ["ref", "name"] + invoice_fields = ["invoice_origin", "ref", "name"] + sale_order_fields = ["client_order_ref", "name"] + for key in transaction_keys: + value = transaction.get(key, False) + if not value: + continue + for fieldname in invoice_fields: + invoice = invoice_model.search([(fieldname, "=", value)], limit=1) + if invoice: + # We need a partner of type contact here because of reconciliation. + # Lines cannot be reconciled if partner is an address + partner = self._get_effective_partner(invoice.partner_id) + transaction["partner_id"] = partner.id + return + for fieldname in sale_order_fields: + sale_order = sale_order_model.search([(fieldname, "=", value)], limit=1) + if sale_order: + partner = self._get_effective_partner(sale_order.partner_id) + transaction["partner_id"] = partner.id + return + + def _get_effective_partner(self, partner): + """Find contact partner for invoice, sale order""" + if partner.type == "contact": + return partner + if partner.parent_id.type == "contact": + return partner.parent_id + # If there's no contact, + # return original partner + return partner diff --git a/account_bank_statement_import_guess_partner/readme/CONTRIBUTORS.rst b/account_bank_statement_import_guess_partner/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..6ee4d1d6 --- /dev/null +++ b/account_bank_statement_import_guess_partner/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Ronald Portier - Therp BV diff --git a/account_bank_statement_import_guess_partner/readme/DESCRIPTION.rst b/account_bank_statement_import_guess_partner/readme/DESCRIPTION.rst new file mode 100644 index 00000000..9f1b8257 --- /dev/null +++ b/account_bank_statement_import_guess_partner/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module uses the ref in an imported transaction to find the partner from the +invoice if possible, and if not set already. diff --git a/account_bank_statement_import_guess_partner/static/description/index.html b/account_bank_statement_import_guess_partner/static/description/index.html new file mode 100644 index 00000000..05e13685 --- /dev/null +++ b/account_bank_statement_import_guess_partner/static/description/index.html @@ -0,0 +1,420 @@ + + + + + + +Guess partner on import of statement lines + + + +
+

Guess partner on import of statement lines

+ + +

Beta License: AGPL-3 OCA/bank-statement-import Translate me on Weblate Try me on Runbot

+

This module uses the ref in an imported transaction to find the partner from the +invoice if possible, and if not set already.

+

Table of contents

+ +
+

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 smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Therp BV
  • +
+
+
+

Contributors

+
    +
  • Ronald Portier - Therp BV
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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.

+

This module is part of the OCA/bank-statement-import project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/account_bank_statement_import_guess_partner/tests/__init__.py b/account_bank_statement_import_guess_partner/tests/__init__.py new file mode 100644 index 00000000..e8899ee0 --- /dev/null +++ b/account_bank_statement_import_guess_partner/tests/__init__.py @@ -0,0 +1,2 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import test_account_bank_statement_import_guess_partner diff --git a/account_bank_statement_import_guess_partner/tests/test_account_bank_statement_import_guess_partner.py b/account_bank_statement_import_guess_partner/tests/test_account_bank_statement_import_guess_partner.py new file mode 100644 index 00000000..c57ba5bd --- /dev/null +++ b/account_bank_statement_import_guess_partner/tests/test_account_bank_statement_import_guess_partner.py @@ -0,0 +1,128 @@ +# Copyright 2022 Therp BV . +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0 +"""Test determining partner from ref in transaction.""" +from odoo.tests import common + +REF = "SO0001" +STMTS_VALS = [ + { + "name": "Test000123", + "date": "2022-03-29", + "transactions": [ + { + "name": "Bla000123", + "date": "2022-03-30", + "amount": 23.95, + "unique_import_id": "random0001", + "ref": REF, + }, + ], + } +] + + +class TestAccountBankStatementImportGuessPartner(common.SavepointCase): + """Test determining partner from ref in transaction.""" + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.account_type = cls.env["account.account.type"].create( + {"name": "Test Account Type", "type": "other", "internal_group": "asset"} + ) + cls.a_receivable = cls.env["account.account"].create( + { + "code": "TAA", + "name": "Test Receivable Account", + "internal_type": "receivable", + "user_type_id": cls.account_type.id, + } + ) + cls.partner = cls.env["res.partner"].create( + {"name": "Test Partner 2", "parent_id": False} + ) + cls.journal = cls.env["account.journal"].create( + {"name": "Test Journal", "type": "sale", "code": "TJS0"} + ) + + def test_invoice_invoice_origin(self): + """Test invoice.invoice_origin = transaction["ref"].""" + self._create_invoice("invoice_origin", REF) + transaction = self._get_completed_transaction() + self.assertIn("partner_id", transaction) + self.assertEqual(transaction["partner_id"], self.partner.id) + + def test_invoice_ref(self): + """Test invoice.ref = transaction["ref"].""" + self._create_invoice("ref", REF) + transaction = self._get_completed_transaction() + self.assertIn("partner_id", transaction) + self.assertEqual(transaction["partner_id"], self.partner.id) + + def test_invoice_name(self): + """Test invoice.name = transaction["ref"].""" + self._create_invoice("name", REF) + transaction = self._get_completed_transaction() + self.assertIn("partner_id", transaction) + self.assertEqual(transaction["partner_id"], self.partner.id) + + def test_invoice_unknown_ref(self): + """Test no value in invoice for transaction["ref"].""" + self._create_invoice("invoice_origin", "DoesAbsolutelyNotExist") + transaction = self._get_completed_transaction() + self.assertNotIn("partner_id", transaction) + + def test_sale_order_name(self): + """Test sale_order.name = transaction["ref"].""" + self._create_sale_order("name", REF) + transaction = self._get_completed_transaction() + self.assertIn("partner_id", transaction) + self.assertEqual(transaction["partner_id"], self.partner.id) + + def test_sale_order_client_order_ref(self): + """Test sale_order.client_order_ref = transaction["ref"].""" + self._create_sale_order("client_order_ref", REF) + transaction = self._get_completed_transaction() + self.assertIn("partner_id", transaction) + self.assertEqual(transaction["partner_id"], self.partner.id) + + def _get_completed_transaction(self): + """Complete statements and return first transaction in first statement.""" + # pylint: disable=protected-access + absi_model = self.env["account.bank.statement.import"] + # Make sure dictionary is "incompleted". + transaction = STMTS_VALS[0]["transactions"][0] + if "partner_id" in transaction: + del transaction["partner_id"] + absi_model._complete_stmts_vals(STMTS_VALS, self.journal, "BNK0001") + return transaction + + def _create_invoice(self, ref_field, ref_value): + """Create an invoice with some reference information.""" + invoice = self.env["account.move"].create( + { + "name": "Test Invoice 3", + "partner_id": self.partner.id, + "type": "out_invoice", + "journal_id": self.journal.id, + "invoice_line_ids": [ + ( + 0, + 0, + { + "account_id": self.a_receivable.id, + "name": "Test line", + "quantity": 1.0, + "price_unit": 100.00, + }, + ) + ], + } + ) + invoice[ref_field] = ref_value # Might also override name. + invoice.post() + + def _create_sale_order(self, ref_field, ref_value): + """Create a sale order with some reference information.""" + sale_order = self.env["sale.order"].create({"partner_id": self.partner.id}) + sale_order[ref_field] = ref_value # Might also override name. diff --git a/setup/account_bank_statement_import_guess_partner/odoo/addons/account_bank_statement_import_guess_partner b/setup/account_bank_statement_import_guess_partner/odoo/addons/account_bank_statement_import_guess_partner new file mode 120000 index 00000000..da7b03cc --- /dev/null +++ b/setup/account_bank_statement_import_guess_partner/odoo/addons/account_bank_statement_import_guess_partner @@ -0,0 +1 @@ +../../../../account_bank_statement_import_guess_partner \ No newline at end of file diff --git a/setup/account_bank_statement_import_guess_partner/setup.py b/setup/account_bank_statement_import_guess_partner/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/account_bank_statement_import_guess_partner/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)