From 18969c011f9ec6f02f113e8275d3cadb8c514b5c Mon Sep 17 00:00:00 2001 From: Jordi Ballester Alomar Date: Tue, 18 Dec 2018 02:05:57 +0100 Subject: [PATCH 01/13] [11.0][add][account_invoice_alternate_payer] --- account_invoice_alternate_payer/README.rst | 83 ++++ account_invoice_alternate_payer/__init__.py | 1 + .../__manifest__.py | 16 + .../i18n/account_invoice_alternate_payer.pot | 58 +++ .../models/__init__.py | 2 + .../models/account_invoice.py | 66 +++ .../models/account_payment.py | 50 ++ .../readme/CONTRIBUTORS.rst | 2 + .../readme/DESCRIPTION.rst | 5 + .../readme/USAGE.rst | 1 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 434 ++++++++++++++++++ .../tests/__init__.py | 1 + .../tests/test_account_invoice.py | 257 +++++++++++ .../views/account_invoice_views.xml | 28 ++ 15 files changed, 1004 insertions(+) create mode 100644 account_invoice_alternate_payer/README.rst create mode 100644 account_invoice_alternate_payer/__init__.py create mode 100644 account_invoice_alternate_payer/__manifest__.py create mode 100644 account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot create mode 100644 account_invoice_alternate_payer/models/__init__.py create mode 100644 account_invoice_alternate_payer/models/account_invoice.py create mode 100644 account_invoice_alternate_payer/models/account_payment.py create mode 100644 account_invoice_alternate_payer/readme/CONTRIBUTORS.rst create mode 100644 account_invoice_alternate_payer/readme/DESCRIPTION.rst create mode 100644 account_invoice_alternate_payer/readme/USAGE.rst create mode 100644 account_invoice_alternate_payer/static/description/icon.png create mode 100644 account_invoice_alternate_payer/static/description/index.html create mode 100644 account_invoice_alternate_payer/tests/__init__.py create mode 100644 account_invoice_alternate_payer/tests/test_account_invoice.py create mode 100644 account_invoice_alternate_payer/views/account_invoice_views.xml diff --git a/account_invoice_alternate_payer/README.rst b/account_invoice_alternate_payer/README.rst new file mode 100644 index 000000000000..4e67fdaf63bb --- /dev/null +++ b/account_invoice_alternate_payer/README.rst @@ -0,0 +1,83 @@ +=============================== +Account Invoice Alternate Payer +=============================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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%2Faccount--invoicing-lightgray.png?logo=github + :target: https://github.com/OCA/account-invoicing/tree/11.0/account_invoice_alternate_payer + :alt: OCA/account-invoicing +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-invoicing-11-0/account-invoicing-11-0-account_invoice_alternate_payer + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/95/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to enter an alternative payer in the +customer invoice or vendor bill. + +This allows, that we pay or expect to get paid by another partner other +than the main partner. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Access to the invoice and change the Alternate Payor/Payee of the invoice. + +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 +~~~~~~~ + +* Eficent + +Contributors +~~~~~~~~~~~~ + +* Eficent Business and IT Consulting Services, S.L. (https://www.eficent.com) + * Jordi Ballester Alomar + +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/account-invoicing `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_invoice_alternate_payer/__init__.py b/account_invoice_alternate_payer/__init__.py new file mode 100644 index 000000000000..0650744f6bc6 --- /dev/null +++ b/account_invoice_alternate_payer/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py new file mode 100644 index 000000000000..a569c4837f82 --- /dev/null +++ b/account_invoice_alternate_payer/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + 'name': 'Account Invoice Alternate Payer', + 'summary': 'Set a alternate payor/payee in invoices', + 'version': '11.0.1.0.0', + 'license': 'AGPL-3', + 'category': 'Accounting', + 'author': 'Eficent,Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/account-invoicing/', + 'depends': ['account'], + 'data': [ + 'views/account_invoice_views.xml', + ], +} diff --git a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot new file mode 100644 index 000000000000..34c072a76a47 --- /dev/null +++ b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot @@ -0,0 +1,58 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_invoice_alternate_payer +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_invoice_alternate_payer +#: model:ir.ui.view,arch_db:account_invoice_alternate_payer.invoice_supplier_form +msgid "Alternate Payee" +msgstr "" + +#. module: account_invoice_alternate_payer +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_invoice_alternate_payer_id +msgid "Alternate Payer" +msgstr "" + +#. module: account_invoice_alternate_payer +#: model:ir.ui.view,arch_db:account_invoice_alternate_payer.invoice_form +msgid "Alternate Payor" +msgstr "" + +#. module: account_invoice_alternate_payer +#: code:addons/account_invoice_alternate_payer/models/account_invoice.py:51 +#, python-format +msgid "Cannot find a chart of accounts for this company, You should configure it. \n" +"Please go to Account Configuration." +msgstr "" + +#. module: account_invoice_alternate_payer +#: code:addons/account_invoice_alternate_payer/models/account_invoice.py:56 +#, python-format +msgid "Go to the configuration panel" +msgstr "" + +#. module: account_invoice_alternate_payer +#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_invoice_alternate_payer_id +msgid "If set, this partner will be the that we expect to pay or to be paid by. If not set, the payor is by default the commercial" +msgstr "" + +#. module: account_invoice_alternate_payer +#: model:ir.model,name:account_invoice_alternate_payer.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: account_invoice_alternate_payer +#: model:ir.model,name:account_invoice_alternate_payer.model_account_register_payments +msgid "Register payments on multiple invoices" +msgstr "" + diff --git a/account_invoice_alternate_payer/models/__init__.py b/account_invoice_alternate_payer/models/__init__.py new file mode 100644 index 000000000000..515ed99ce64c --- /dev/null +++ b/account_invoice_alternate_payer/models/__init__.py @@ -0,0 +1,2 @@ +from . import account_invoice +from . import account_payment diff --git a/account_invoice_alternate_payer/models/account_invoice.py b/account_invoice_alternate_payer/models/account_invoice.py new file mode 100644 index 000000000000..4941b881621b --- /dev/null +++ b/account_invoice_alternate_payer/models/account_invoice.py @@ -0,0 +1,66 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ +from odoo.exceptions import RedirectWarning + + +class AccountInvoice(models.Model): + + _inherit = 'account.invoice' + + alternate_payer_id = fields.Many2one( + 'res.partner', string='Alternate Payer', + readonly=True, states={'draft': [('readonly', False)]}, + help="If set, this partner will be the that we expect to pay or to " + "be paid by. If not set, the payor is by default the " + "commercial") + + @api.model + def line_get_convert(self, line, part): + res = super(AccountInvoice, self).line_get_convert(line, part) + if line.get('type', False) == 'dest' and self.alternate_payer_id: + res['partner_id'] = self.alternate_payer_id.id + return res + + @api.onchange('partner_id', 'company_id', 'alternate_payer_id') + def _onchange_partner_id(self): + res = super(AccountInvoice, self)._onchange_partner_id() + company_id = self.company_id.id + domain = {} + if self.type in ('in_invoice', 'out_refund') and \ + self.alternate_payer_id: + bank_ids = self.alternate_payer_id.bank_ids.filtered( + lambda b: b.company_id.id == company_id or not b.company_id) + bank_id = bank_ids[0].id if bank_ids else False + self.partner_bank_id = bank_id + domain = {'partner_bank_id': [('id', 'in', bank_ids.ids)]} + if domain: + res['domain'] = domain + if self.alternate_payer_id: + account_id = False + payment_term_id = False + p = self.alternate_payer_id if not company_id else \ + self.alternate_payer_id.with_context(force_company=company_id) + type = self.type + if p: + rec_account = p.property_account_receivable_id + pay_account = p.property_account_payable_id + if not rec_account and not pay_account: + action = self.env.ref('account.action_account_config') + msg = _( + 'Cannot find a chart of accounts for this company, ' + 'You should configure it. \nPlease go to Account ' + 'Configuration.') + raise RedirectWarning(msg, action.id, + _('Go to the configuration panel')) + + if type in ('out_invoice', 'out_refund'): + account_id = rec_account.id + payment_term_id = p.property_payment_term_id.id + else: + account_id = pay_account.id + payment_term_id = p.property_supplier_payment_term_id.id + self.account_id = account_id + self.payment_term_id = payment_term_id + return res diff --git a/account_invoice_alternate_payer/models/account_payment.py b/account_invoice_alternate_payer/models/account_payment.py new file mode 100644 index 000000000000..5116425345f5 --- /dev/null +++ b/account_invoice_alternate_payer/models/account_payment.py @@ -0,0 +1,50 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, models +from odoo.addons.account.models.account_payment import \ + MAP_INVOICE_TYPE_PARTNER_TYPE + + +class AccountRegisterPayments(models.TransientModel): + _inherit = "account.register.payments" + + @api.model + def default_get(self, fields): + rec = super(AccountRegisterPayments, self).default_get(fields) + active_ids = self._context.get('active_ids') + invoices = self.env['account.invoice'].browse(active_ids) + + # Look if we are mixin multiple alternate_payer or + # customer invoices with vendor bills + payer = invoices[0].alternate_payer_id or \ + invoices[0].commercial_partner_id + multi = any(inv.alternate_payer_id or inv.commercial_partner_id != + payer for inv in invoices) + payer_id = invoices[0].alternate_payer_id.id or \ + invoices[0].commercial_partner_id.id + rec['partner_id'] = False if multi else payer_id + rec['multi'] = multi + return rec + + @api.multi + def _groupby_invoices(self): + # We have to re-group because the old groups are not valid anymore + super(AccountRegisterPayments, self)._groupby_invoices() + results = {} + for inv in self.invoice_ids: + payer = inv.alternate_payer_id.id or inv.commercial_partner_id.id + key = (payer, MAP_INVOICE_TYPE_PARTNER_TYPE[inv.type]) + if key not in results: + results[key] = self.env['account.invoice'] + results[key] += inv + return results + + @api.multi + def _prepare_payment_vals(self, invoices): + res = super(AccountRegisterPayments, self)._prepare_payment_vals( + invoices) + payer_id = invoices[0].alternate_payer_id.id or \ + invoices[0].commercial_partner_id.id + res['partner_id'] = payer_id + return res diff --git a/account_invoice_alternate_payer/readme/CONTRIBUTORS.rst b/account_invoice_alternate_payer/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000000..6466f8907657 --- /dev/null +++ b/account_invoice_alternate_payer/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Eficent Business and IT Consulting Services, S.L. (https://www.eficent.com) + * Jordi Ballester Alomar diff --git a/account_invoice_alternate_payer/readme/DESCRIPTION.rst b/account_invoice_alternate_payer/readme/DESCRIPTION.rst new file mode 100644 index 000000000000..5ac4a0bd5863 --- /dev/null +++ b/account_invoice_alternate_payer/readme/DESCRIPTION.rst @@ -0,0 +1,5 @@ +This module allows to enter an alternative payer in the +customer invoice or vendor bill. + +This allows, that we pay or expect to get paid by another partner other +than the main partner. diff --git a/account_invoice_alternate_payer/readme/USAGE.rst b/account_invoice_alternate_payer/readme/USAGE.rst new file mode 100644 index 000000000000..aea8f7fafd17 --- /dev/null +++ b/account_invoice_alternate_payer/readme/USAGE.rst @@ -0,0 +1 @@ +Access to the invoice and change the Alternate Payor/Payee of the invoice. diff --git a/account_invoice_alternate_payer/static/description/icon.png b/account_invoice_alternate_payer/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/account_invoice_alternate_payer/static/description/index.html b/account_invoice_alternate_payer/static/description/index.html new file mode 100644 index 000000000000..0cdab016b9ee --- /dev/null +++ b/account_invoice_alternate_payer/static/description/index.html @@ -0,0 +1,434 @@ + + + + + + +Account Invoice Alternate Payer + + + +
+

Account Invoice Alternate Payer

+ + +

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

+

This module allows to enter an alternative payer in the +customer invoice or vendor bill.

+

This allows, that we pay or expect to get paid by another partner other +than the main partner.

+

Table of contents

+ +
+

Usage

+

Access to the invoice and change the Alternate Payor/Payee of the invoice.

+
+
+

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

+
    +
  • Eficent
  • +
+
+
+

Contributors

+ +
+
+

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/account-invoicing project on GitHub.

+

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

+
+
+
+ + diff --git a/account_invoice_alternate_payer/tests/__init__.py b/account_invoice_alternate_payer/tests/__init__.py new file mode 100644 index 000000000000..d7555d02125e --- /dev/null +++ b/account_invoice_alternate_payer/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_invoice diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py new file mode 100644 index 000000000000..439aacefca2d --- /dev/null +++ b/account_invoice_alternate_payer/tests/test_account_invoice.py @@ -0,0 +1,257 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase +from odoo import fields + + +class TestAccountInvoiceAlternateCommercialPartner(TransactionCase): + + def setUp(self): + """ + Setup test instances + """ + super(TestAccountInvoiceAlternateCommercialPartner, self).setUp() + self.company = self.env.ref('base.main_company') + self.currency_usd_id = self.env.ref("base.USD").id + # Instance: account type (receivable) + self.type_recv = self.env.ref('account.data_account_type_receivable') + # Instance: account type (payable) + self.type_payable = self.env.ref('account.data_account_type_payable') + # Instance: account type (expense) + self.type_expense = self.env.ref('account.data_account_type_expenses') + # Instance: account type (revenue) + self.type_revenue = self.env.ref('account.data_account_type_revenue') + self.register_payments_model = self.env['account.register.payments'] + # account (receivable) + self.account_recv = self.env['account.account'].create({ + 'name': 'test_account_receivable', + 'code': '123', + 'user_type_id': self.type_recv.id, + 'company_id': self.company.id, + 'reconcile': True}) + # account (payable) + self.account_payable = self.env['account.account'].create({ + 'name': 'test_account_payable', + 'code': '321', + 'user_type_id': self.type_payable.id, + 'company_id': self.company.id, + 'reconcile': True}) + self.account_payable_2 = self.env['account.account'].create({ + 'name': 'test_account_payable', + 'code': '3211', + 'user_type_id': self.type_payable.id, + 'company_id': self.company.id, + 'reconcile': True}) + self.account_expense = self.env['account.account'].create({ + 'name': 'test_account_expense', + 'code': 'expense', + 'user_type_id': self.type_expense.id, + 'company_id': self.company.id, + 'reconcile': False}) + self.account_revenue = self.env['account.account'].create({ + 'name': 'test_account_revenue', + 'code': 'revenue', + 'user_type_id': self.type_revenue.id, + 'company_id': self.company.id, + 'reconcile': False}) + self.customer_commercial = self.env['res.partner'].create({ + 'name': 'Customer commercial partner', + 'property_account_receivable_id': self.account_recv.id, + 'is_company': True, + }) + self.customer = self.env['res.partner'].create({ + 'name': 'Customer', + 'property_account_receivable_id': self.account_recv.id, + 'company_id': self.company.id, + 'parent_id': self.customer_commercial.id, + }) + self.vendor_commercial = self.env['res.partner'].create({ + 'name': 'Vendor commercial partner', + 'property_account_payable_id': self.account_payable.id, + 'is_company': True, + }) + self.vendor = self.env['res.partner'].create({ + 'name': 'Vendor', + 'property_account_payable_id': self.account_payable.id, + 'company_id': self.company.id, + 'parent_id': self.vendor_commercial.id, + }) + self.payor = self.env['res.partner'].create({ + 'name': 'Payor for customer', + 'property_account_receivable_id': self.account_recv.id, + 'company_id': self.company.id, + }) + self.payee = self.env['res.partner'].create({ + 'name': 'Payee for vendor', + 'property_account_payable_id': self.account_payable_2.id, + 'company_id': self.company.id, + }) + self.payee_bank = self.env['res.partner.bank'].create({ + 'partner_id': self.payee.id, + 'acc_number': 'ES66 2100 0418 4012 3456 7891', + 'company_id': self.company.id, + }) + self.purchase_journal = self.env['account.journal'].create( + {'name': 'Purchase Journal - TST', + 'code': 'PJT', + 'type': 'purchase', + 'company_id': self.company.id}) + self.sale_journal = self.env['account.journal'].create( + {'name': 'Sale Journal - TST', + 'code': 'SJT', + 'type': 'sale', + 'company_id': self.company.id}) + self.bank_journal_usd = self.env['account.journal'].create( + {'name': 'Bank US TEST', 'type': 'bank', 'code': 'BJT'}) + self.product = self.env['product.product'].create({ + 'type': 'service', + 'name': 'Sample product' + }) + self.invoice_line = self.env['account.invoice.line'].create({ + 'name': 'test', + 'account_id': self.account_expense.id, + 'price_unit': 2000.00, + 'quantity': 1, + 'product_id': self.product.id}) + # Instance: invoice + self.vendor_invoice = self.env['account.invoice'].create({ + 'partner_id': self.vendor.id, + 'type': 'in_invoice', + 'account_id': self.account_payable.id, + 'payment_term_id': False, + 'journal_id': self.purchase_journal.id, + 'company_id': self.company.id, + 'currency_id': self.currency_usd_id, + 'invoice_line_ids': [(4, self.invoice_line.id)]}) + invoice_line = self.env['account.invoice.line'].create({ + 'name': 'test', + 'account_id': self.account_revenue.id, + 'price_unit': 2000.00, + 'quantity': 1, + 'product_id': self.product.id}) + # Instance: invoice + self.customer_invoice = self.env['account.invoice'].create({ + 'partner_id': self.customer.id, + 'type': 'out_invoice', + 'account_id': self.account_recv.id, + 'payment_term_id': False, + 'journal_id': self.sale_journal.id, + 'company_id': self.company.id, + 'currency_id': self.currency_usd_id, + 'invoice_line_ids': [(4, invoice_line.id)]}) + + def test_01_onchange(self): + # Instance: invoice + supplier_invoice = self.env['account.invoice'].new({ + 'partner_id': self.vendor.id, + 'type': 'in_invoice', + 'account_id': self.account_payable.id, + 'payment_term_id': False, + 'journal_id': self.purchase_journal.id, + 'currency_id': self.currency_usd_id, + 'company_id': self.company.id, + 'invoice_line_ids': [ + (0, 0, {'name': 'test', + 'account_id': self.account_expense.id, + 'price_unit': 2000.00, + 'quantity': 1, + 'product_id': self.product.id + } + ) + ]}) + supplier_invoice.alternate_payer_id = self.payee + supplier_invoice._onchange_partner_id() + self.assertEqual(supplier_invoice.partner_bank_id, self.payee_bank) + self.assertEqual(supplier_invoice.account_id, self.account_payable_2) + + def test_02_invoice(self): + """ + Test Setting an alternate commercial partner + """ + # Customer invoices + self.customer_invoice.alternate_payer_id = self.payor.id + self.customer_invoice._onchange_partner_id() + self.customer_invoice.action_invoice_open() + self.assertEqual(self.customer_invoice.state, 'open') + line = self.customer_invoice.move_id.line_ids.filtered( + lambda li: li.account_id == self.account_recv) + self.assertEqual(line.partner_id, self.payor) + ctx = {'active_model': 'account.invoice', + 'active_ids': [self.customer_invoice.id]} + register_payments = self.register_payments_model.with_context( + ctx).create({ + 'payment_date': fields.Date.today(), + 'journal_id': self.bank_journal_usd.id, + 'payment_method_id': self.env.ref( + 'account.account_payment_method_manual_in').id, + }) + register_payments.create_payments() + self.assertEqual(self.customer_invoice.state, 'paid') + # Vendor bills + self.vendor_invoice.alternate_payer_id = self.payee + self.vendor_invoice._onchange_partner_id() + self.vendor_invoice.action_invoice_open() + self.assertEqual(self.vendor_invoice.state, 'open') + line = self.vendor_invoice.move_id.line_ids.filtered( + lambda li: li.account_id == self.account_payable_2) + self.assertEqual(line.partner_id, self.payee) + ctx = {'active_model': 'account.invoice', + 'active_ids': [self.vendor_invoice.id] + } + register_payments = self.register_payments_model.with_context( + ctx).create({ + 'payment_date': fields.Date.today(), + 'journal_id': self.bank_journal_usd.id, + 'payment_method_id': self.env.ref( + 'account.account_payment_method_manual_out').id, + }) + register_payments.create_payments() + self.assertEqual(self.vendor_invoice.state, 'paid') + + def test_03_payment_multiple_invoices(self): + """ + Test selecting multiple invoices with different alternate payer + """ + supplier_invoice_1 = self.env['account.invoice'].create({ + 'partner_id': self.customer.id, + 'type': 'in_invoice', + 'account_id': self.account_payable.id, + 'payment_term_id': False, + 'journal_id': self.purchase_journal.id, + 'currency_id': self.currency_usd_id, + 'company_id': self.company.id, + 'invoice_line_ids': [ + (0, 0, {'name': 'test', + 'account_id': self.account_expense.id, + 'price_unit': 2000.00, + 'quantity': 1, + 'product_id': self.product.id + } + ) + ]}) + supplier_invoice_2 = supplier_invoice_1.copy() + supplier_invoice_2.alternate_payer_id = self.payee + supplier_invoice_3 = supplier_invoice_1.copy() + supplier_invoice_1._onchange_partner_id() + supplier_invoice_1.action_invoice_open() + supplier_invoice_2._onchange_partner_id() + supplier_invoice_2.action_invoice_open() + supplier_invoice_3._onchange_partner_id() + supplier_invoice_3.action_invoice_open() + ctx = {'active_model': 'account.invoice', + 'active_ids': [supplier_invoice_1.id, supplier_invoice_2.id, + supplier_invoice_3.id]} + register_payments = self.register_payments_model.with_context( + ctx).create({ + 'payment_date': fields.Date.today(), + 'journal_id': self.bank_journal_usd.id, + 'payment_method_id': self.env.ref( + 'account.account_payment_method_manual_out').id, + }) + res = register_payments.create_payments() + # ['domain'][('id', 'in', payments.ids), ('state', '=', 'posted')] + self.assertEqual(len(res['domain'][0][2]), 2) + self.assertEqual(supplier_invoice_1.state, 'paid') + self.assertEqual(supplier_invoice_2.state, 'paid') + self.assertEqual(supplier_invoice_3.state, 'paid') diff --git a/account_invoice_alternate_payer/views/account_invoice_views.xml b/account_invoice_alternate_payer/views/account_invoice_views.xml new file mode 100644 index 000000000000..572fe2955211 --- /dev/null +++ b/account_invoice_alternate_payer/views/account_invoice_views.xml @@ -0,0 +1,28 @@ + + + + + + account.invoice.supplier.form + account.invoice + + + + + + + + + + account.invoice.form + account.invoice + + + + + + + + + + From 3199dffca6062a3c96e42b454fb4af77db32320e Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Wed, 4 Mar 2020 21:24:10 +0100 Subject: [PATCH 02/13] [MIG][12.0] account_invoice_alternate_payer --- .../__manifest__.py | 2 +- .../models/account_invoice.py | 23 +++++++++++++++++-- .../tests/test_account_invoice.py | 22 ++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py index a569c4837f82..b74a906eb196 100644 --- a/account_invoice_alternate_payer/__manifest__.py +++ b/account_invoice_alternate_payer/__manifest__.py @@ -4,7 +4,7 @@ { 'name': 'Account Invoice Alternate Payer', 'summary': 'Set a alternate payor/payee in invoices', - 'version': '11.0.1.0.0', + 'version': '12.0.1.0.0', 'license': 'AGPL-3', 'category': 'Accounting', 'author': 'Eficent,Odoo Community Association (OCA)', diff --git a/account_invoice_alternate_payer/models/account_invoice.py b/account_invoice_alternate_payer/models/account_invoice.py index 4941b881621b..79ec31b5d8c8 100644 --- a/account_invoice_alternate_payer/models/account_invoice.py +++ b/account_invoice_alternate_payer/models/account_invoice.py @@ -3,6 +3,7 @@ from odoo import api, fields, models, _ from odoo.exceptions import RedirectWarning +from odoo.exceptions import ValidationError class AccountInvoice(models.Model): @@ -42,7 +43,6 @@ def _onchange_partner_id(self): payment_term_id = False p = self.alternate_payer_id if not company_id else \ self.alternate_payer_id.with_context(force_company=company_id) - type = self.type if p: rec_account = p.property_account_receivable_id pay_account = p.property_account_payable_id @@ -55,7 +55,7 @@ def _onchange_partner_id(self): raise RedirectWarning(msg, action.id, _('Go to the configuration panel')) - if type in ('out_invoice', 'out_refund'): + if self.type in ('out_invoice', 'out_refund'): account_id = rec_account.id payment_term_id = p.property_payment_term_id.id else: @@ -64,3 +64,22 @@ def _onchange_partner_id(self): self.account_id = account_id self.payment_term_id = payment_term_id return res + + @api.constrains('partner_id', 'partner_bank_id') + def validate_partner_bank_id(self): + for record in self: + if record.partner_bank_id: + partner = record.alternate_payer_id or record.partner_id + bank_partner = record.partner_bank_id.partner_id + if record.type in ( + 'in_invoice', 'out_refund' + ) and bank_partner != partner.commercial_partner_id: + raise ValidationError(_( + "Commercial partner and vendor account owners must " + "be identical.")) + elif record.type in ( + 'out_invoice', 'in_refund' + ) and record.company_id not in bank_partner.ref_company_ids: + raise ValidationError(_( + "The account selected for payment does not belong to " + "the same company as this invoice.")) diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py index 439aacefca2d..e6065043d702 100644 --- a/account_invoice_alternate_payer/tests/test_account_invoice.py +++ b/account_invoice_alternate_payer/tests/test_account_invoice.py @@ -3,6 +3,7 @@ from odoo.tests.common import TransactionCase from odoo import fields +from odoo.exceptions import ValidationError class TestAccountInvoiceAlternateCommercialPartner(TransactionCase): @@ -255,3 +256,24 @@ def test_03_payment_multiple_invoices(self): self.assertEqual(supplier_invoice_1.state, 'paid') self.assertEqual(supplier_invoice_2.state, 'paid') self.assertEqual(supplier_invoice_3.state, 'paid') + + def test_constrains(self): + with self.assertRaises(ValidationError): + self.env['account.invoice'].create({ + 'partner_id': self.vendor.id, + 'type': 'in_invoice', + 'account_id': self.account_payable.id, + 'payment_term_id': False, + 'journal_id': self.purchase_journal.id, + 'currency_id': self.currency_usd_id, + 'company_id': self.company.id, + 'partner_bank_id': self.payee_bank.id, + 'invoice_line_ids': [ + (0, 0, {'name': 'test', + 'account_id': self.account_expense.id, + 'price_unit': 2000.00, + 'quantity': 1, + 'product_id': self.product.id + } + ) + ]}) From 63bdbab3eead2e65b54fc8a509cf721afb09d4f4 Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Mon, 21 Jun 2021 09:40:15 +0200 Subject: [PATCH 03/13] [IMP] account_invoice_alternate_payer: black, isort, prettier --- .../__manifest__.py | 20 +- .../models/account_invoice.py | 91 ++-- .../models/account_payment.py | 38 +- .../tests/test_account_invoice.py | 507 ++++++++++-------- .../views/account_invoice_views.xml | 13 +- 5 files changed, 382 insertions(+), 287 deletions(-) diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py index b74a906eb196..1b84a8cd309d 100644 --- a/account_invoice_alternate_payer/__manifest__.py +++ b/account_invoice_alternate_payer/__manifest__.py @@ -2,15 +2,13 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { - 'name': 'Account Invoice Alternate Payer', - 'summary': 'Set a alternate payor/payee in invoices', - 'version': '12.0.1.0.0', - 'license': 'AGPL-3', - 'category': 'Accounting', - 'author': 'Eficent,Odoo Community Association (OCA)', - 'website': 'https://github.com/OCA/account-invoicing/', - 'depends': ['account'], - 'data': [ - 'views/account_invoice_views.xml', - ], + "name": "Account Invoice Alternate Payer", + "summary": "Set a alternate payor/payee in invoices", + "version": "12.0.1.0.0", + "license": "AGPL-3", + "category": "Accounting", + "author": "Eficent,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-invoicing/", + "depends": ["account"], + "data": ["views/account_invoice_views.xml",], } diff --git a/account_invoice_alternate_payer/models/account_invoice.py b/account_invoice_alternate_payer/models/account_invoice.py index 79ec31b5d8c8..db614136df64 100644 --- a/account_invoice_alternate_payer/models/account_invoice.py +++ b/account_invoice_alternate_payer/models/account_invoice.py @@ -1,61 +1,68 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, _ -from odoo.exceptions import RedirectWarning -from odoo.exceptions import ValidationError +from odoo import _, api, fields, models +from odoo.exceptions import RedirectWarning, ValidationError class AccountInvoice(models.Model): - _inherit = 'account.invoice' + _inherit = "account.invoice" alternate_payer_id = fields.Many2one( - 'res.partner', string='Alternate Payer', - readonly=True, states={'draft': [('readonly', False)]}, + "res.partner", + string="Alternate Payer", + readonly=True, + states={"draft": [("readonly", False)]}, help="If set, this partner will be the that we expect to pay or to " - "be paid by. If not set, the payor is by default the " - "commercial") + "be paid by. If not set, the payor is by default the " + "commercial", + ) @api.model def line_get_convert(self, line, part): res = super(AccountInvoice, self).line_get_convert(line, part) - if line.get('type', False) == 'dest' and self.alternate_payer_id: - res['partner_id'] = self.alternate_payer_id.id + if line.get("type", False) == "dest" and self.alternate_payer_id: + res["partner_id"] = self.alternate_payer_id.id return res - @api.onchange('partner_id', 'company_id', 'alternate_payer_id') + @api.onchange("partner_id", "company_id", "alternate_payer_id") def _onchange_partner_id(self): res = super(AccountInvoice, self)._onchange_partner_id() company_id = self.company_id.id domain = {} - if self.type in ('in_invoice', 'out_refund') and \ - self.alternate_payer_id: + if self.type in ("in_invoice", "out_refund") and self.alternate_payer_id: bank_ids = self.alternate_payer_id.bank_ids.filtered( - lambda b: b.company_id.id == company_id or not b.company_id) + lambda b: b.company_id.id == company_id or not b.company_id + ) bank_id = bank_ids[0].id if bank_ids else False self.partner_bank_id = bank_id - domain = {'partner_bank_id': [('id', 'in', bank_ids.ids)]} + domain = {"partner_bank_id": [("id", "in", bank_ids.ids)]} if domain: - res['domain'] = domain + res["domain"] = domain if self.alternate_payer_id: account_id = False payment_term_id = False - p = self.alternate_payer_id if not company_id else \ - self.alternate_payer_id.with_context(force_company=company_id) + p = ( + self.alternate_payer_id + if not company_id + else self.alternate_payer_id.with_context(force_company=company_id) + ) if p: rec_account = p.property_account_receivable_id pay_account = p.property_account_payable_id if not rec_account and not pay_account: - action = self.env.ref('account.action_account_config') + action = self.env.ref("account.action_account_config") msg = _( - 'Cannot find a chart of accounts for this company, ' - 'You should configure it. \nPlease go to Account ' - 'Configuration.') - raise RedirectWarning(msg, action.id, - _('Go to the configuration panel')) + "Cannot find a chart of accounts for this company, " + "You should configure it. \nPlease go to Account " + "Configuration." + ) + raise RedirectWarning( + msg, action.id, _("Go to the configuration panel") + ) - if self.type in ('out_invoice', 'out_refund'): + if self.type in ("out_invoice", "out_refund"): account_id = rec_account.id payment_term_id = p.property_payment_term_id.id else: @@ -65,21 +72,29 @@ def _onchange_partner_id(self): self.payment_term_id = payment_term_id return res - @api.constrains('partner_id', 'partner_bank_id') + @api.constrains("partner_id", "partner_bank_id") def validate_partner_bank_id(self): for record in self: if record.partner_bank_id: partner = record.alternate_payer_id or record.partner_id bank_partner = record.partner_bank_id.partner_id - if record.type in ( - 'in_invoice', 'out_refund' - ) and bank_partner != partner.commercial_partner_id: - raise ValidationError(_( - "Commercial partner and vendor account owners must " - "be identical.")) - elif record.type in ( - 'out_invoice', 'in_refund' - ) and record.company_id not in bank_partner.ref_company_ids: - raise ValidationError(_( - "The account selected for payment does not belong to " - "the same company as this invoice.")) + if ( + record.type in ("in_invoice", "out_refund") + and bank_partner != partner.commercial_partner_id + ): + raise ValidationError( + _( + "Commercial partner and vendor account owners must " + "be identical." + ) + ) + elif ( + record.type in ("out_invoice", "in_refund") + and record.company_id not in bank_partner.ref_company_ids + ): + raise ValidationError( + _( + "The account selected for payment does not belong to " + "the same company as this invoice." + ) + ) diff --git a/account_invoice_alternate_payer/models/account_payment.py b/account_invoice_alternate_payer/models/account_payment.py index 5116425345f5..2726ff847b54 100644 --- a/account_invoice_alternate_payer/models/account_payment.py +++ b/account_invoice_alternate_payer/models/account_payment.py @@ -2,8 +2,8 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo import api, models -from odoo.addons.account.models.account_payment import \ - MAP_INVOICE_TYPE_PARTNER_TYPE + +from odoo.addons.account.models.account_payment import MAP_INVOICE_TYPE_PARTNER_TYPE class AccountRegisterPayments(models.TransientModel): @@ -12,19 +12,21 @@ class AccountRegisterPayments(models.TransientModel): @api.model def default_get(self, fields): rec = super(AccountRegisterPayments, self).default_get(fields) - active_ids = self._context.get('active_ids') - invoices = self.env['account.invoice'].browse(active_ids) + active_ids = self._context.get("active_ids") + invoices = self.env["account.invoice"].browse(active_ids) # Look if we are mixin multiple alternate_payer or # customer invoices with vendor bills - payer = invoices[0].alternate_payer_id or \ - invoices[0].commercial_partner_id - multi = any(inv.alternate_payer_id or inv.commercial_partner_id != - payer for inv in invoices) - payer_id = invoices[0].alternate_payer_id.id or \ - invoices[0].commercial_partner_id.id - rec['partner_id'] = False if multi else payer_id - rec['multi'] = multi + payer = invoices[0].alternate_payer_id or invoices[0].commercial_partner_id + multi = any( + inv.alternate_payer_id or inv.commercial_partner_id != payer + for inv in invoices + ) + payer_id = ( + invoices[0].alternate_payer_id.id or invoices[0].commercial_partner_id.id + ) + rec["partner_id"] = False if multi else payer_id + rec["multi"] = multi return rec @api.multi @@ -36,15 +38,15 @@ def _groupby_invoices(self): payer = inv.alternate_payer_id.id or inv.commercial_partner_id.id key = (payer, MAP_INVOICE_TYPE_PARTNER_TYPE[inv.type]) if key not in results: - results[key] = self.env['account.invoice'] + results[key] = self.env["account.invoice"] results[key] += inv return results @api.multi def _prepare_payment_vals(self, invoices): - res = super(AccountRegisterPayments, self)._prepare_payment_vals( - invoices) - payer_id = invoices[0].alternate_payer_id.id or \ - invoices[0].commercial_partner_id.id - res['partner_id'] = payer_id + res = super(AccountRegisterPayments, self)._prepare_payment_vals(invoices) + payer_id = ( + invoices[0].alternate_payer_id.id or invoices[0].commercial_partner_id.id + ) + res["partner_id"] = payer_id return res diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py index e6065043d702..6dfa242c4836 100644 --- a/account_invoice_alternate_payer/tests/test_account_invoice.py +++ b/account_invoice_alternate_payer/tests/test_account_invoice.py @@ -1,166 +1,219 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo.tests.common import TransactionCase from odoo import fields from odoo.exceptions import ValidationError +from odoo.tests.common import TransactionCase class TestAccountInvoiceAlternateCommercialPartner(TransactionCase): - def setUp(self): """ Setup test instances """ super(TestAccountInvoiceAlternateCommercialPartner, self).setUp() - self.company = self.env.ref('base.main_company') + self.company = self.env.ref("base.main_company") self.currency_usd_id = self.env.ref("base.USD").id # Instance: account type (receivable) - self.type_recv = self.env.ref('account.data_account_type_receivable') + self.type_recv = self.env.ref("account.data_account_type_receivable") # Instance: account type (payable) - self.type_payable = self.env.ref('account.data_account_type_payable') + self.type_payable = self.env.ref("account.data_account_type_payable") # Instance: account type (expense) - self.type_expense = self.env.ref('account.data_account_type_expenses') + self.type_expense = self.env.ref("account.data_account_type_expenses") # Instance: account type (revenue) - self.type_revenue = self.env.ref('account.data_account_type_revenue') - self.register_payments_model = self.env['account.register.payments'] + self.type_revenue = self.env.ref("account.data_account_type_revenue") + self.register_payments_model = self.env["account.register.payments"] # account (receivable) - self.account_recv = self.env['account.account'].create({ - 'name': 'test_account_receivable', - 'code': '123', - 'user_type_id': self.type_recv.id, - 'company_id': self.company.id, - 'reconcile': True}) + self.account_recv = self.env["account.account"].create( + { + "name": "test_account_receivable", + "code": "123", + "user_type_id": self.type_recv.id, + "company_id": self.company.id, + "reconcile": True, + } + ) # account (payable) - self.account_payable = self.env['account.account'].create({ - 'name': 'test_account_payable', - 'code': '321', - 'user_type_id': self.type_payable.id, - 'company_id': self.company.id, - 'reconcile': True}) - self.account_payable_2 = self.env['account.account'].create({ - 'name': 'test_account_payable', - 'code': '3211', - 'user_type_id': self.type_payable.id, - 'company_id': self.company.id, - 'reconcile': True}) - self.account_expense = self.env['account.account'].create({ - 'name': 'test_account_expense', - 'code': 'expense', - 'user_type_id': self.type_expense.id, - 'company_id': self.company.id, - 'reconcile': False}) - self.account_revenue = self.env['account.account'].create({ - 'name': 'test_account_revenue', - 'code': 'revenue', - 'user_type_id': self.type_revenue.id, - 'company_id': self.company.id, - 'reconcile': False}) - self.customer_commercial = self.env['res.partner'].create({ - 'name': 'Customer commercial partner', - 'property_account_receivable_id': self.account_recv.id, - 'is_company': True, - }) - self.customer = self.env['res.partner'].create({ - 'name': 'Customer', - 'property_account_receivable_id': self.account_recv.id, - 'company_id': self.company.id, - 'parent_id': self.customer_commercial.id, - }) - self.vendor_commercial = self.env['res.partner'].create({ - 'name': 'Vendor commercial partner', - 'property_account_payable_id': self.account_payable.id, - 'is_company': True, - }) - self.vendor = self.env['res.partner'].create({ - 'name': 'Vendor', - 'property_account_payable_id': self.account_payable.id, - 'company_id': self.company.id, - 'parent_id': self.vendor_commercial.id, - }) - self.payor = self.env['res.partner'].create({ - 'name': 'Payor for customer', - 'property_account_receivable_id': self.account_recv.id, - 'company_id': self.company.id, - }) - self.payee = self.env['res.partner'].create({ - 'name': 'Payee for vendor', - 'property_account_payable_id': self.account_payable_2.id, - 'company_id': self.company.id, - }) - self.payee_bank = self.env['res.partner.bank'].create({ - 'partner_id': self.payee.id, - 'acc_number': 'ES66 2100 0418 4012 3456 7891', - 'company_id': self.company.id, - }) - self.purchase_journal = self.env['account.journal'].create( - {'name': 'Purchase Journal - TST', - 'code': 'PJT', - 'type': 'purchase', - 'company_id': self.company.id}) - self.sale_journal = self.env['account.journal'].create( - {'name': 'Sale Journal - TST', - 'code': 'SJT', - 'type': 'sale', - 'company_id': self.company.id}) - self.bank_journal_usd = self.env['account.journal'].create( - {'name': 'Bank US TEST', 'type': 'bank', 'code': 'BJT'}) - self.product = self.env['product.product'].create({ - 'type': 'service', - 'name': 'Sample product' - }) - self.invoice_line = self.env['account.invoice.line'].create({ - 'name': 'test', - 'account_id': self.account_expense.id, - 'price_unit': 2000.00, - 'quantity': 1, - 'product_id': self.product.id}) + self.account_payable = self.env["account.account"].create( + { + "name": "test_account_payable", + "code": "321", + "user_type_id": self.type_payable.id, + "company_id": self.company.id, + "reconcile": True, + } + ) + self.account_payable_2 = self.env["account.account"].create( + { + "name": "test_account_payable", + "code": "3211", + "user_type_id": self.type_payable.id, + "company_id": self.company.id, + "reconcile": True, + } + ) + self.account_expense = self.env["account.account"].create( + { + "name": "test_account_expense", + "code": "expense", + "user_type_id": self.type_expense.id, + "company_id": self.company.id, + "reconcile": False, + } + ) + self.account_revenue = self.env["account.account"].create( + { + "name": "test_account_revenue", + "code": "revenue", + "user_type_id": self.type_revenue.id, + "company_id": self.company.id, + "reconcile": False, + } + ) + self.customer_commercial = self.env["res.partner"].create( + { + "name": "Customer commercial partner", + "property_account_receivable_id": self.account_recv.id, + "is_company": True, + } + ) + self.customer = self.env["res.partner"].create( + { + "name": "Customer", + "property_account_receivable_id": self.account_recv.id, + "company_id": self.company.id, + "parent_id": self.customer_commercial.id, + } + ) + self.vendor_commercial = self.env["res.partner"].create( + { + "name": "Vendor commercial partner", + "property_account_payable_id": self.account_payable.id, + "is_company": True, + } + ) + self.vendor = self.env["res.partner"].create( + { + "name": "Vendor", + "property_account_payable_id": self.account_payable.id, + "company_id": self.company.id, + "parent_id": self.vendor_commercial.id, + } + ) + self.payor = self.env["res.partner"].create( + { + "name": "Payor for customer", + "property_account_receivable_id": self.account_recv.id, + "company_id": self.company.id, + } + ) + self.payee = self.env["res.partner"].create( + { + "name": "Payee for vendor", + "property_account_payable_id": self.account_payable_2.id, + "company_id": self.company.id, + } + ) + self.payee_bank = self.env["res.partner.bank"].create( + { + "partner_id": self.payee.id, + "acc_number": "ES66 2100 0418 4012 3456 7891", + "company_id": self.company.id, + } + ) + self.purchase_journal = self.env["account.journal"].create( + { + "name": "Purchase Journal - TST", + "code": "PJT", + "type": "purchase", + "company_id": self.company.id, + } + ) + self.sale_journal = self.env["account.journal"].create( + { + "name": "Sale Journal - TST", + "code": "SJT", + "type": "sale", + "company_id": self.company.id, + } + ) + self.bank_journal_usd = self.env["account.journal"].create( + {"name": "Bank US TEST", "type": "bank", "code": "BJT"} + ) + self.product = self.env["product.product"].create( + {"type": "service", "name": "Sample product"} + ) + self.invoice_line = self.env["account.invoice.line"].create( + { + "name": "test", + "account_id": self.account_expense.id, + "price_unit": 2000.00, + "quantity": 1, + "product_id": self.product.id, + } + ) # Instance: invoice - self.vendor_invoice = self.env['account.invoice'].create({ - 'partner_id': self.vendor.id, - 'type': 'in_invoice', - 'account_id': self.account_payable.id, - 'payment_term_id': False, - 'journal_id': self.purchase_journal.id, - 'company_id': self.company.id, - 'currency_id': self.currency_usd_id, - 'invoice_line_ids': [(4, self.invoice_line.id)]}) - invoice_line = self.env['account.invoice.line'].create({ - 'name': 'test', - 'account_id': self.account_revenue.id, - 'price_unit': 2000.00, - 'quantity': 1, - 'product_id': self.product.id}) + self.vendor_invoice = self.env["account.invoice"].create( + { + "partner_id": self.vendor.id, + "type": "in_invoice", + "account_id": self.account_payable.id, + "payment_term_id": False, + "journal_id": self.purchase_journal.id, + "company_id": self.company.id, + "currency_id": self.currency_usd_id, + "invoice_line_ids": [(4, self.invoice_line.id)], + } + ) + invoice_line = self.env["account.invoice.line"].create( + { + "name": "test", + "account_id": self.account_revenue.id, + "price_unit": 2000.00, + "quantity": 1, + "product_id": self.product.id, + } + ) # Instance: invoice - self.customer_invoice = self.env['account.invoice'].create({ - 'partner_id': self.customer.id, - 'type': 'out_invoice', - 'account_id': self.account_recv.id, - 'payment_term_id': False, - 'journal_id': self.sale_journal.id, - 'company_id': self.company.id, - 'currency_id': self.currency_usd_id, - 'invoice_line_ids': [(4, invoice_line.id)]}) + self.customer_invoice = self.env["account.invoice"].create( + { + "partner_id": self.customer.id, + "type": "out_invoice", + "account_id": self.account_recv.id, + "payment_term_id": False, + "journal_id": self.sale_journal.id, + "company_id": self.company.id, + "currency_id": self.currency_usd_id, + "invoice_line_ids": [(4, invoice_line.id)], + } + ) def test_01_onchange(self): # Instance: invoice - supplier_invoice = self.env['account.invoice'].new({ - 'partner_id': self.vendor.id, - 'type': 'in_invoice', - 'account_id': self.account_payable.id, - 'payment_term_id': False, - 'journal_id': self.purchase_journal.id, - 'currency_id': self.currency_usd_id, - 'company_id': self.company.id, - 'invoice_line_ids': [ - (0, 0, {'name': 'test', - 'account_id': self.account_expense.id, - 'price_unit': 2000.00, - 'quantity': 1, - 'product_id': self.product.id - } - ) - ]}) + supplier_invoice = self.env["account.invoice"].new( + { + "partner_id": self.vendor.id, + "type": "in_invoice", + "account_id": self.account_payable.id, + "payment_term_id": False, + "journal_id": self.purchase_journal.id, + "currency_id": self.currency_usd_id, + "company_id": self.company.id, + "invoice_line_ids": [ + ( + 0, + 0, + { + "name": "test", + "account_id": self.account_expense.id, + "price_unit": 2000.00, + "quantity": 1, + "product_id": self.product.id, + }, + ) + ], + } + ) supplier_invoice.alternate_payer_id = self.payee supplier_invoice._onchange_partner_id() self.assertEqual(supplier_invoice.partner_bank_id, self.payee_bank) @@ -174,63 +227,79 @@ def test_02_invoice(self): self.customer_invoice.alternate_payer_id = self.payor.id self.customer_invoice._onchange_partner_id() self.customer_invoice.action_invoice_open() - self.assertEqual(self.customer_invoice.state, 'open') + self.assertEqual(self.customer_invoice.state, "open") line = self.customer_invoice.move_id.line_ids.filtered( - lambda li: li.account_id == self.account_recv) + lambda li: li.account_id == self.account_recv + ) self.assertEqual(line.partner_id, self.payor) - ctx = {'active_model': 'account.invoice', - 'active_ids': [self.customer_invoice.id]} - register_payments = self.register_payments_model.with_context( - ctx).create({ - 'payment_date': fields.Date.today(), - 'journal_id': self.bank_journal_usd.id, - 'payment_method_id': self.env.ref( - 'account.account_payment_method_manual_in').id, - }) + ctx = { + "active_model": "account.invoice", + "active_ids": [self.customer_invoice.id], + } + register_payments = self.register_payments_model.with_context(ctx).create( + { + "payment_date": fields.Date.today(), + "journal_id": self.bank_journal_usd.id, + "payment_method_id": self.env.ref( + "account.account_payment_method_manual_in" + ).id, + } + ) register_payments.create_payments() - self.assertEqual(self.customer_invoice.state, 'paid') + self.assertEqual(self.customer_invoice.state, "paid") # Vendor bills self.vendor_invoice.alternate_payer_id = self.payee self.vendor_invoice._onchange_partner_id() self.vendor_invoice.action_invoice_open() - self.assertEqual(self.vendor_invoice.state, 'open') + self.assertEqual(self.vendor_invoice.state, "open") line = self.vendor_invoice.move_id.line_ids.filtered( - lambda li: li.account_id == self.account_payable_2) + lambda li: li.account_id == self.account_payable_2 + ) self.assertEqual(line.partner_id, self.payee) - ctx = {'active_model': 'account.invoice', - 'active_ids': [self.vendor_invoice.id] - } - register_payments = self.register_payments_model.with_context( - ctx).create({ - 'payment_date': fields.Date.today(), - 'journal_id': self.bank_journal_usd.id, - 'payment_method_id': self.env.ref( - 'account.account_payment_method_manual_out').id, - }) + ctx = { + "active_model": "account.invoice", + "active_ids": [self.vendor_invoice.id], + } + register_payments = self.register_payments_model.with_context(ctx).create( + { + "payment_date": fields.Date.today(), + "journal_id": self.bank_journal_usd.id, + "payment_method_id": self.env.ref( + "account.account_payment_method_manual_out" + ).id, + } + ) register_payments.create_payments() - self.assertEqual(self.vendor_invoice.state, 'paid') + self.assertEqual(self.vendor_invoice.state, "paid") def test_03_payment_multiple_invoices(self): """ Test selecting multiple invoices with different alternate payer """ - supplier_invoice_1 = self.env['account.invoice'].create({ - 'partner_id': self.customer.id, - 'type': 'in_invoice', - 'account_id': self.account_payable.id, - 'payment_term_id': False, - 'journal_id': self.purchase_journal.id, - 'currency_id': self.currency_usd_id, - 'company_id': self.company.id, - 'invoice_line_ids': [ - (0, 0, {'name': 'test', - 'account_id': self.account_expense.id, - 'price_unit': 2000.00, - 'quantity': 1, - 'product_id': self.product.id - } - ) - ]}) + supplier_invoice_1 = self.env["account.invoice"].create( + { + "partner_id": self.customer.id, + "type": "in_invoice", + "account_id": self.account_payable.id, + "payment_term_id": False, + "journal_id": self.purchase_journal.id, + "currency_id": self.currency_usd_id, + "company_id": self.company.id, + "invoice_line_ids": [ + ( + 0, + 0, + { + "name": "test", + "account_id": self.account_expense.id, + "price_unit": 2000.00, + "quantity": 1, + "product_id": self.product.id, + }, + ) + ], + } + ) supplier_invoice_2 = supplier_invoice_1.copy() supplier_invoice_2.alternate_payer_id = self.payee supplier_invoice_3 = supplier_invoice_1.copy() @@ -240,40 +309,54 @@ def test_03_payment_multiple_invoices(self): supplier_invoice_2.action_invoice_open() supplier_invoice_3._onchange_partner_id() supplier_invoice_3.action_invoice_open() - ctx = {'active_model': 'account.invoice', - 'active_ids': [supplier_invoice_1.id, supplier_invoice_2.id, - supplier_invoice_3.id]} - register_payments = self.register_payments_model.with_context( - ctx).create({ - 'payment_date': fields.Date.today(), - 'journal_id': self.bank_journal_usd.id, - 'payment_method_id': self.env.ref( - 'account.account_payment_method_manual_out').id, - }) + ctx = { + "active_model": "account.invoice", + "active_ids": [ + supplier_invoice_1.id, + supplier_invoice_2.id, + supplier_invoice_3.id, + ], + } + register_payments = self.register_payments_model.with_context(ctx).create( + { + "payment_date": fields.Date.today(), + "journal_id": self.bank_journal_usd.id, + "payment_method_id": self.env.ref( + "account.account_payment_method_manual_out" + ).id, + } + ) res = register_payments.create_payments() # ['domain'][('id', 'in', payments.ids), ('state', '=', 'posted')] - self.assertEqual(len(res['domain'][0][2]), 2) - self.assertEqual(supplier_invoice_1.state, 'paid') - self.assertEqual(supplier_invoice_2.state, 'paid') - self.assertEqual(supplier_invoice_3.state, 'paid') + self.assertEqual(len(res["domain"][0][2]), 2) + self.assertEqual(supplier_invoice_1.state, "paid") + self.assertEqual(supplier_invoice_2.state, "paid") + self.assertEqual(supplier_invoice_3.state, "paid") def test_constrains(self): with self.assertRaises(ValidationError): - self.env['account.invoice'].create({ - 'partner_id': self.vendor.id, - 'type': 'in_invoice', - 'account_id': self.account_payable.id, - 'payment_term_id': False, - 'journal_id': self.purchase_journal.id, - 'currency_id': self.currency_usd_id, - 'company_id': self.company.id, - 'partner_bank_id': self.payee_bank.id, - 'invoice_line_ids': [ - (0, 0, {'name': 'test', - 'account_id': self.account_expense.id, - 'price_unit': 2000.00, - 'quantity': 1, - 'product_id': self.product.id - } - ) - ]}) + self.env["account.invoice"].create( + { + "partner_id": self.vendor.id, + "type": "in_invoice", + "account_id": self.account_payable.id, + "payment_term_id": False, + "journal_id": self.purchase_journal.id, + "currency_id": self.currency_usd_id, + "company_id": self.company.id, + "partner_bank_id": self.payee_bank.id, + "invoice_line_ids": [ + ( + 0, + 0, + { + "name": "test", + "account_id": self.account_expense.id, + "price_unit": 2000.00, + "quantity": 1, + "product_id": self.product.id, + }, + ) + ], + } + ) diff --git a/account_invoice_alternate_payer/views/account_invoice_views.xml b/account_invoice_alternate_payer/views/account_invoice_views.xml index 572fe2955211..5213c0359081 100644 --- a/account_invoice_alternate_payer/views/account_invoice_views.xml +++ b/account_invoice_alternate_payer/views/account_invoice_views.xml @@ -1,28 +1,25 @@ - + - account.invoice.supplier.form account.invoice - + - + - account.invoice.form account.invoice - + - + - From 08af3e21b748e5b2fcd4c7b2b357dc92b52b9b3a Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Mon, 21 Jun 2021 11:15:35 +0200 Subject: [PATCH 04/13] [MIG] account_invoice_alternate_payer: Migration to 13.0 --- account_invoice_alternate_payer/README.rst | 10 +- .../__manifest__.py | 4 +- .../i18n/account_invoice_alternate_payer.pot | 40 +- .../migrations/13.0.1.0.0/post-migration.py | 32 ++ .../models/__init__.py | 2 +- .../models/account_invoice.py | 100 ---- .../models/account_move.py | 120 ++++ .../models/account_payment.py | 49 +- .../static/description/index.html | 6 +- .../tests/test_account_invoice.py | 535 +++++++----------- .../views/account_invoice_views.xml | 25 - .../views/account_move_views.xml | 13 + 12 files changed, 431 insertions(+), 505 deletions(-) create mode 100644 account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py delete mode 100644 account_invoice_alternate_payer/models/account_invoice.py create mode 100644 account_invoice_alternate_payer/models/account_move.py delete mode 100644 account_invoice_alternate_payer/views/account_invoice_views.xml create mode 100644 account_invoice_alternate_payer/views/account_move_views.xml diff --git a/account_invoice_alternate_payer/README.rst b/account_invoice_alternate_payer/README.rst index 4e67fdaf63bb..ec24af360412 100644 --- a/account_invoice_alternate_payer/README.rst +++ b/account_invoice_alternate_payer/README.rst @@ -14,13 +14,13 @@ Account Invoice Alternate Payer :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github - :target: https://github.com/OCA/account-invoicing/tree/11.0/account_invoice_alternate_payer + :target: https://github.com/OCA/account-invoicing/tree/13.0/account_invoice_alternate_payer :alt: OCA/account-invoicing .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/account-invoicing-11-0/account-invoicing-11-0-account_invoice_alternate_payer + :target: https://translation.odoo-community.org/projects/account-invoicing-13-0/account-invoicing-13-0-account_invoice_alternate_payer :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/95/11.0 + :target: https://runbot.odoo-community.org/runbot/95/13.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -47,7 +47,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -78,6 +78,6 @@ 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/account-invoicing `_ project on GitHub. +This module is part of the `OCA/account-invoicing `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py index 1b84a8cd309d..36dd42394367 100644 --- a/account_invoice_alternate_payer/__manifest__.py +++ b/account_invoice_alternate_payer/__manifest__.py @@ -4,11 +4,11 @@ { "name": "Account Invoice Alternate Payer", "summary": "Set a alternate payor/payee in invoices", - "version": "12.0.1.0.0", + "version": "13.0.1.0.0", "license": "AGPL-3", "category": "Accounting", "author": "Eficent,Odoo Community Association (OCA)", "website": "https://github.com/OCA/account-invoicing/", "depends": ["account"], - "data": ["views/account_invoice_views.xml",], + "data": ["views/account_move_views.xml"], } diff --git a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot index 34c072a76a47..4cc3eae10200 100644 --- a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot +++ b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot @@ -1,12 +1,12 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * account_invoice_alternate_payer +# * account_invoice_alternate_payer # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 11.0\n" +"Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: <>\n" +"Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -14,45 +14,45 @@ msgstr "" "Plural-Forms: \n" #. module: account_invoice_alternate_payer -#: model:ir.ui.view,arch_db:account_invoice_alternate_payer.invoice_supplier_form +#: model_terms:ir.ui.view,arch_db:account_invoice_alternate_payer.view_move_form msgid "Alternate Payee" msgstr "" #. module: account_invoice_alternate_payer -#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_invoice_alternate_payer_id +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__alternate_payer_id msgid "Alternate Payer" msgstr "" #. module: account_invoice_alternate_payer -#: model:ir.ui.view,arch_db:account_invoice_alternate_payer.invoice_form -msgid "Alternate Payor" +#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_move__alternate_payer_id +msgid "" +"If set, this will be the partner that we expect to pay or to be paid by. If " +"not set, the payor is by default the commercial" msgstr "" #. module: account_invoice_alternate_payer -#: code:addons/account_invoice_alternate_payer/models/account_invoice.py:51 -#, python-format -msgid "Cannot find a chart of accounts for this company, You should configure it. \n" -"Please go to Account Configuration." +#: model:ir.model,name:account_invoice_alternate_payer.model_account_move +msgid "Journal Entries" msgstr "" #. module: account_invoice_alternate_payer -#: code:addons/account_invoice_alternate_payer/models/account_invoice.py:56 +#: code:addons/account_invoice_alternate_payer/models/account_move.py:0 #, python-format -msgid "Go to the configuration panel" +msgid "Outstanding credits" msgstr "" #. module: account_invoice_alternate_payer -#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_invoice_alternate_payer_id -msgid "If set, this partner will be the that we expect to pay or to be paid by. If not set, the payor is by default the commercial" +#: code:addons/account_invoice_alternate_payer/models/account_move.py:0 +#, python-format +msgid "Outstanding debits" msgstr "" #. module: account_invoice_alternate_payer -#: model:ir.model,name:account_invoice_alternate_payer.model_account_invoice -msgid "Invoice" +#: model:ir.model,name:account_invoice_alternate_payer.model_account_payment +msgid "Payments" msgstr "" #. module: account_invoice_alternate_payer -#: model:ir.model,name:account_invoice_alternate_payer.model_account_register_payments -msgid "Register payments on multiple invoices" +#: model:ir.model,name:account_invoice_alternate_payer.model_account_payment_register +msgid "Register Payment" msgstr "" - diff --git a/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py b/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py new file mode 100644 index 000000000000..3cd7f21532be --- /dev/null +++ b/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py @@ -0,0 +1,32 @@ +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + openupgrade.logged_query( + env.cr, + """ + UPDATE account_move am + SET alternate_payer_id = ai.alternate_payer_id + FROM account_invoice ai + WHERE ai.alternate_payer_id IS NOT NULL + AND ai.id = am.old_invoice_id + """, + ) + openupgrade.logged_query( + env.cr, + """ + UPDATE account_move_line aml + SET partner_id = am.alternate_payer_id + FROM + account_move am, + account_account as aa, + account_account_type as aat + WHERE am.alternate_payer_id IS NOT NULL + AND am.id = aml.move_id + AND am.state = 'draft' + AND aat.type in ('receivable', 'payable') + AND aa.id = aml.account_id + AND aat.id = aa.user_type_id + """, + ) diff --git a/account_invoice_alternate_payer/models/__init__.py b/account_invoice_alternate_payer/models/__init__.py index 515ed99ce64c..11623d4e5329 100644 --- a/account_invoice_alternate_payer/models/__init__.py +++ b/account_invoice_alternate_payer/models/__init__.py @@ -1,2 +1,2 @@ -from . import account_invoice +from . import account_move from . import account_payment diff --git a/account_invoice_alternate_payer/models/account_invoice.py b/account_invoice_alternate_payer/models/account_invoice.py deleted file mode 100644 index db614136df64..000000000000 --- a/account_invoice_alternate_payer/models/account_invoice.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2018 Eficent Business and IT Consulting Services, S.L. -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - -from odoo import _, api, fields, models -from odoo.exceptions import RedirectWarning, ValidationError - - -class AccountInvoice(models.Model): - - _inherit = "account.invoice" - - alternate_payer_id = fields.Many2one( - "res.partner", - string="Alternate Payer", - readonly=True, - states={"draft": [("readonly", False)]}, - help="If set, this partner will be the that we expect to pay or to " - "be paid by. If not set, the payor is by default the " - "commercial", - ) - - @api.model - def line_get_convert(self, line, part): - res = super(AccountInvoice, self).line_get_convert(line, part) - if line.get("type", False) == "dest" and self.alternate_payer_id: - res["partner_id"] = self.alternate_payer_id.id - return res - - @api.onchange("partner_id", "company_id", "alternate_payer_id") - def _onchange_partner_id(self): - res = super(AccountInvoice, self)._onchange_partner_id() - company_id = self.company_id.id - domain = {} - if self.type in ("in_invoice", "out_refund") and self.alternate_payer_id: - bank_ids = self.alternate_payer_id.bank_ids.filtered( - lambda b: b.company_id.id == company_id or not b.company_id - ) - bank_id = bank_ids[0].id if bank_ids else False - self.partner_bank_id = bank_id - domain = {"partner_bank_id": [("id", "in", bank_ids.ids)]} - if domain: - res["domain"] = domain - if self.alternate_payer_id: - account_id = False - payment_term_id = False - p = ( - self.alternate_payer_id - if not company_id - else self.alternate_payer_id.with_context(force_company=company_id) - ) - if p: - rec_account = p.property_account_receivable_id - pay_account = p.property_account_payable_id - if not rec_account and not pay_account: - action = self.env.ref("account.action_account_config") - msg = _( - "Cannot find a chart of accounts for this company, " - "You should configure it. \nPlease go to Account " - "Configuration." - ) - raise RedirectWarning( - msg, action.id, _("Go to the configuration panel") - ) - - if self.type in ("out_invoice", "out_refund"): - account_id = rec_account.id - payment_term_id = p.property_payment_term_id.id - else: - account_id = pay_account.id - payment_term_id = p.property_supplier_payment_term_id.id - self.account_id = account_id - self.payment_term_id = payment_term_id - return res - - @api.constrains("partner_id", "partner_bank_id") - def validate_partner_bank_id(self): - for record in self: - if record.partner_bank_id: - partner = record.alternate_payer_id or record.partner_id - bank_partner = record.partner_bank_id.partner_id - if ( - record.type in ("in_invoice", "out_refund") - and bank_partner != partner.commercial_partner_id - ): - raise ValidationError( - _( - "Commercial partner and vendor account owners must " - "be identical." - ) - ) - elif ( - record.type in ("out_invoice", "in_refund") - and record.company_id not in bank_partner.ref_company_ids - ): - raise ValidationError( - _( - "The account selected for payment does not belong to " - "the same company as this invoice." - ) - ) diff --git a/account_invoice_alternate_payer/models/account_move.py b/account_invoice_alternate_payer/models/account_move.py new file mode 100644 index 000000000000..b52d8dd2c9f9 --- /dev/null +++ b/account_invoice_alternate_payer/models/account_move.py @@ -0,0 +1,120 @@ +# Copyright 2018 Eficent Business and IT Consulting Services, S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import json + +from odoo import _, api, fields, models +from odoo.tools import float_is_zero + + +class AccountMove(models.Model): + + _inherit = "account.move" + + alternate_payer_id = fields.Many2one( + "res.partner", + string="Alternate Payer", + readonly=True, + states={"draft": [("readonly", False)]}, + help="If set, this will be the partner that we expect to pay or to " + "be paid by. If not set, the payor is by default the " + "commercial", + ) + + @api.depends("commercial_partner_id", "alternate_payer_id") + def _compute_bank_partner_id(self): + super( + AccountMove, + self.filtered(lambda r: not r.alternate_payer_id or not r.is_outbound()), + )._compute_bank_partner_id() + for move in self: + if move.is_outbound() and move.alternate_payer_id: + move.bank_partner_id = move.alternate_payer_id + + @api.onchange("partner_id", "alternate_payer_id") + def _onchange_partner_id(self): + return super()._onchange_partner_id() + + def _recompute_payment_terms_lines(self): + super()._recompute_payment_terms_lines() + for invoice in self: + if invoice.alternate_payer_id: + invoice.line_ids.filtered( + lambda r: r.account_id.user_type_id.type + in ("receivable", "payable") + ).update({"partner_id": invoice.alternate_payer_id.id}) + + def _compute_payments_widget_to_reconcile_info(self): + super( + AccountMove, self.filtered(lambda r: not r.alternate_payer_id) + )._compute_payments_widget_to_reconcile_info() + for move in self: + if not self.alternate_payer_id: + continue + move.invoice_outstanding_credits_debits_widget = json.dumps(False) + move.invoice_has_outstanding = False + if ( + move.state != "posted" + or move.invoice_payment_state != "not_paid" + or not move.is_invoice(include_receipts=True) + ): + continue + pay_term_line_ids = move.line_ids.filtered( + lambda line: line.account_id.user_type_id.type + in ("receivable", "payable") + ) + + domain = [ + ("account_id", "in", pay_term_line_ids.mapped("account_id").ids), + "|", + ("move_id.state", "=", "posted"), + "&", + ("move_id.state", "=", "draft"), + ("journal_id.post_at", "=", "bank_rec"), + ("partner_id", "=", move.alternate_payer_id.id), + ("reconciled", "=", False), + "|", + ("amount_residual", "!=", 0.0), + ("amount_residual_currency", "!=", 0.0), + ] + + if move.is_inbound(): + domain.extend([("credit", ">", 0), ("debit", "=", 0)]) + type_payment = _("Outstanding credits") + else: + domain.extend([("credit", "=", 0), ("debit", ">", 0)]) + type_payment = _("Outstanding debits") + info = {"title": "", "outstanding": True, "content": [], "move_id": move.id} + lines = self.env["account.move.line"].search(domain) + currency_id = move.currency_id + if len(lines) != 0: + for line in lines: + # get the outstanding residual value in invoice currency + if line.currency_id and line.currency_id == move.currency_id: + amount_to_show = abs(line.amount_residual_currency) + else: + currency = line.company_id.currency_id + amount_to_show = currency._convert( + abs(line.amount_residual), + move.currency_id, + move.company_id, + line.date or fields.Date.today(), + ) + if float_is_zero( + amount_to_show, precision_rounding=move.currency_id.rounding + ): + continue + info["content"].append( + { + "journal_name": line.ref or line.move_id.name, + "amount": amount_to_show, + "currency": currency_id.symbol, + "id": line.id, + "position": currency_id.position, + "digits": [69, move.currency_id.decimal_places], + "payment_date": fields.Date.to_string(line.date), + } + ) + info["title"] = type_payment + move.invoice_outstanding_credits_debits_widget = json.dumps(info) + move.invoice_has_outstanding = True diff --git a/account_invoice_alternate_payer/models/account_payment.py b/account_invoice_alternate_payer/models/account_payment.py index 2726ff847b54..0be5cdcbde30 100644 --- a/account_invoice_alternate_payer/models/account_payment.py +++ b/account_invoice_alternate_payer/models/account_payment.py @@ -3,48 +3,31 @@ from odoo import api, models -from odoo.addons.account.models.account_payment import MAP_INVOICE_TYPE_PARTNER_TYPE - -class AccountRegisterPayments(models.TransientModel): - _inherit = "account.register.payments" +class AccountPayment(models.Model): + _inherit = "account.payment" @api.model - def default_get(self, fields): - rec = super(AccountRegisterPayments, self).default_get(fields) + def default_get(self, default_fields): + rec = super().default_get(default_fields) + if self.env.context.get("active_model") != "account.move": + return rec active_ids = self._context.get("active_ids") - invoices = self.env["account.invoice"].browse(active_ids) - - # Look if we are mixin multiple alternate_payer or - # customer invoices with vendor bills - payer = invoices[0].alternate_payer_id or invoices[0].commercial_partner_id - multi = any( - inv.alternate_payer_id or inv.commercial_partner_id != payer - for inv in invoices - ) - payer_id = ( - invoices[0].alternate_payer_id.id or invoices[0].commercial_partner_id.id + invoices = ( + self.env["account.move"] + .browse(active_ids) + .filtered(lambda move: move.is_invoice(include_receipts=True)) ) - rec["partner_id"] = False if multi else payer_id - rec["multi"] = multi + if invoices and invoices[0].alternate_payer_id: + rec.update({"partner_id": invoices[0].alternate_payer_id.id}) return rec - @api.multi - def _groupby_invoices(self): - # We have to re-group because the old groups are not valid anymore - super(AccountRegisterPayments, self)._groupby_invoices() - results = {} - for inv in self.invoice_ids: - payer = inv.alternate_payer_id.id or inv.commercial_partner_id.id - key = (payer, MAP_INVOICE_TYPE_PARTNER_TYPE[inv.type]) - if key not in results: - results[key] = self.env["account.invoice"] - results[key] += inv - return results - @api.multi +class AccountPaymentRegister(models.TransientModel): + _inherit = "account.payment.register" + def _prepare_payment_vals(self, invoices): - res = super(AccountRegisterPayments, self)._prepare_payment_vals(invoices) + res = super()._prepare_payment_vals(invoices) payer_id = ( invoices[0].alternate_payer_id.id or invoices[0].commercial_partner_id.id ) diff --git a/account_invoice_alternate_payer/static/description/index.html b/account_invoice_alternate_payer/static/description/index.html index 0cdab016b9ee..ffa32435c024 100644 --- a/account_invoice_alternate_payer/static/description/index.html +++ b/account_invoice_alternate_payer/static/description/index.html @@ -367,7 +367,7 @@

Account Invoice Alternate Payer

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

This module allows to enter an alternative payer in the customer invoice or vendor bill.

This allows, that we pay or expect to get paid by another partner other @@ -394,7 +394,7 @@

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.

+feedback.

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

@@ -425,7 +425,7 @@

Maintainers

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/account-invoicing project on GitHub.

+

This module is part of the OCA/account-invoicing project on GitHub.

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

diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py index 6dfa242c4836..119db82de8e4 100644 --- a/account_invoice_alternate_payer/tests/test_account_invoice.py +++ b/account_invoice_alternate_payer/tests/test_account_invoice.py @@ -1,362 +1,265 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import fields -from odoo.exceptions import ValidationError -from odoo.tests.common import TransactionCase +from odoo.tests import Form +from odoo.addons.account.tests.account_test_savepoint import AccountTestInvoicingCommon -class TestAccountInvoiceAlternateCommercialPartner(TransactionCase): - def setUp(self): - """ - Setup test instances - """ - super(TestAccountInvoiceAlternateCommercialPartner, self).setUp() - self.company = self.env.ref("base.main_company") - self.currency_usd_id = self.env.ref("base.USD").id - # Instance: account type (receivable) - self.type_recv = self.env.ref("account.data_account_type_receivable") - # Instance: account type (payable) - self.type_payable = self.env.ref("account.data_account_type_payable") - # Instance: account type (expense) - self.type_expense = self.env.ref("account.data_account_type_expenses") - # Instance: account type (revenue) - self.type_revenue = self.env.ref("account.data_account_type_revenue") - self.register_payments_model = self.env["account.register.payments"] - # account (receivable) - self.account_recv = self.env["account.account"].create( - { - "name": "test_account_receivable", - "code": "123", - "user_type_id": self.type_recv.id, - "company_id": self.company.id, - "reconcile": True, - } + +class TestAccountInvoiceAlternateCommercialPartner(AccountTestInvoicingCommon): + @classmethod + def setUpClass(cls, chart_template_ref=None): + super().setUpClass(chart_template_ref=chart_template_ref) + cls.in_invoice = cls.init_invoice("in_invoice") + cls.out_invoice = cls.init_invoice("out_invoice") + cls.in_invoice_02 = cls.init_invoice("in_invoice") + cls.out_invoice_02 = cls.init_invoice("out_invoice") + cls.alternate_partner = cls.env["res.partner"].create( + {"name": "Alternate Payer"} ) - # account (payable) - self.account_payable = self.env["account.account"].create( - { - "name": "test_account_payable", - "code": "321", - "user_type_id": self.type_payable.id, - "company_id": self.company.id, - "reconcile": True, - } + cls.payment_method_manual_out = cls.env.ref( + "account.account_payment_method_manual_out" ) - self.account_payable_2 = self.env["account.account"].create( - { - "name": "test_account_payable", - "code": "3211", - "user_type_id": self.type_payable.id, - "company_id": self.company.id, - "reconcile": True, - } + cls.payment_method_manual_in = cls.env.ref( + "account.account_payment_method_manual_in" ) - self.account_expense = self.env["account.account"].create( - { - "name": "test_account_expense", - "code": "expense", - "user_type_id": self.type_expense.id, - "company_id": self.company.id, - "reconcile": False, - } + cls.bank_journal_euro = cls.env["account.journal"].create( + {"name": "Bank", "type": "bank", "code": "BNK67"} ) - self.account_revenue = self.env["account.account"].create( + cls.bank_account = cls.env["account.account"].create( { - "name": "test_account_revenue", - "code": "revenue", - "user_type_id": self.type_revenue.id, - "company_id": self.company.id, - "reconcile": False, + "name": "Demo Bank account", + "code": "demo_bank_account", + "user_type_id": cls.env.ref("account.data_account_type_liquidity").id, } ) - self.customer_commercial = self.env["res.partner"].create( - { - "name": "Customer commercial partner", - "property_account_receivable_id": self.account_recv.id, - "is_company": True, - } - ) - self.customer = self.env["res.partner"].create( - { - "name": "Customer", - "property_account_receivable_id": self.account_recv.id, - "company_id": self.company.id, - "parent_id": self.customer_commercial.id, - } + + def test_01_onchange_out_invoice(self): + with Form(self.out_invoice) as form: + form.alternate_payer_id = self.alternate_partner + self.assertEqual( + self.out_invoice.line_ids.filtered( + lambda r: r.account_id.user_type_id.type in ("receivable", "payable") + ).mapped("partner_id"), + self.alternate_partner, ) - self.vendor_commercial = self.env["res.partner"].create( - { - "name": "Vendor commercial partner", - "property_account_payable_id": self.account_payable.id, - "is_company": True, - } + self.assertEqual( + self.out_invoice.line_ids.filtered( + lambda r: r.account_id.user_type_id.type + not in ("receivable", "payable") + ).mapped("partner_id"), + self.out_invoice.partner_id, ) - self.vendor = self.env["res.partner"].create( - { - "name": "Vendor", - "property_account_payable_id": self.account_payable.id, - "company_id": self.company.id, - "parent_id": self.vendor_commercial.id, - } + self.assertEqual( + self.out_invoice.bank_partner_id, self.out_invoice.company_id.partner_id ) - self.payor = self.env["res.partner"].create( - { - "name": "Payor for customer", - "property_account_receivable_id": self.account_recv.id, - "company_id": self.company.id, - } - ) - self.payee = self.env["res.partner"].create( - { - "name": "Payee for vendor", - "property_account_payable_id": self.account_payable_2.id, - "company_id": self.company.id, - } + + def test_02_onchange_in_invoice(self): + with Form(self.in_invoice) as form: + form.alternate_payer_id = self.alternate_partner + self.assertEqual( + self.in_invoice.line_ids.filtered( + lambda r: r.account_id.user_type_id.type in ("receivable", "payable") + ).mapped("partner_id"), + self.alternate_partner, ) - self.payee_bank = self.env["res.partner.bank"].create( - { - "partner_id": self.payee.id, - "acc_number": "ES66 2100 0418 4012 3456 7891", - "company_id": self.company.id, - } + self.assertEqual( + self.in_invoice.line_ids.filtered( + lambda r: r.account_id.user_type_id.type + not in ("receivable", "payable") + ).mapped("partner_id"), + self.out_invoice.partner_id, ) - self.purchase_journal = self.env["account.journal"].create( - { - "name": "Purchase Journal - TST", - "code": "PJT", - "type": "purchase", - "company_id": self.company.id, - } + self.assertEqual(self.in_invoice.bank_partner_id, self.alternate_partner) + + def test_03_payment_out_invoice(self): + with Form(self.out_invoice) as form: + form.alternate_payer_id = self.alternate_partner + self.out_invoice.post() + records = self.out_invoice + action = ( + self.env["account.payment"] + .with_context(active_model=records._name, active_ids=records.ids) + .action_register_payment() ) - self.sale_journal = self.env["account.journal"].create( - { - "name": "Sale Journal - TST", - "code": "SJT", - "type": "sale", - "company_id": self.company.id, - } + payment = ( + self.env[action["res_model"]] + .with_context(action["context"]) + .create( + { + "payment_method_id": self.payment_method_manual_out.id, + "journal_id": self.bank_journal_euro.id, + } + ) ) - self.bank_journal_usd = self.env["account.journal"].create( - {"name": "Bank US TEST", "type": "bank", "code": "BJT"} + payment.post() + self.assertEqual(payment.partner_id, self.alternate_partner) + + def test_04_payment_in_invoice(self): + with Form(self.in_invoice) as form: + form.alternate_payer_id = self.alternate_partner + self.in_invoice.post() + records = self.in_invoice + action = ( + self.env["account.payment"] + .with_context(active_model=records._name, active_ids=records.ids) + .action_register_payment() ) - self.product = self.env["product.product"].create( - {"type": "service", "name": "Sample product"} + payment = ( + self.env[action["res_model"]] + .with_context(action["context"]) + .create( + { + "payment_method_id": self.payment_method_manual_in.id, + "journal_id": self.bank_journal_euro.id, + } + ) ) - self.invoice_line = self.env["account.invoice.line"].create( - { - "name": "test", - "account_id": self.account_expense.id, - "price_unit": 2000.00, - "quantity": 1, - "product_id": self.product.id, - } + payment.post() + self.assertEqual(payment.partner_id, self.alternate_partner) + + def test_05_payment_out_invoices(self): + with Form(self.out_invoice) as form: + form.alternate_payer_id = self.alternate_partner + self.out_invoice.post() + with Form(self.out_invoice_02) as form: + form.alternate_payer_id = self.alternate_partner + self.out_invoice_02.post() + records = self.out_invoice | self.out_invoice_02 + action = ( + self.env["account.payment"] + .with_context(active_model=records._name, active_ids=records.ids) + .action_register_payment() ) - # Instance: invoice - self.vendor_invoice = self.env["account.invoice"].create( - { - "partner_id": self.vendor.id, - "type": "in_invoice", - "account_id": self.account_payable.id, - "payment_term_id": False, - "journal_id": self.purchase_journal.id, - "company_id": self.company.id, - "currency_id": self.currency_usd_id, - "invoice_line_ids": [(4, self.invoice_line.id)], - } + action = ( + self.env[action["res_model"]] + .with_context(action["context"]) + .create( + { + "payment_method_id": self.payment_method_manual_out.id, + "journal_id": self.bank_journal_euro.id, + } + ) + .create_payments() ) - invoice_line = self.env["account.invoice.line"].create( - { - "name": "test", - "account_id": self.account_revenue.id, - "price_unit": 2000.00, - "quantity": 1, - "product_id": self.product.id, - } + payments = self.env[action["res_model"]] + if action.get("res_ids", False): + payments = payments.browse(action["res_id"]) + else: + payments = payments.search(action["domain"]) + for payment in payments: + self.assertEqual(payment.partner_id, self.alternate_partner) + + def test_06_payment_in_invoices(self): + with Form(self.in_invoice) as form: + form.alternate_payer_id = self.alternate_partner + self.in_invoice.post() + with Form(self.in_invoice_02) as form: + form.alternate_payer_id = self.alternate_partner + self.in_invoice_02.post() + records = self.in_invoice | self.in_invoice_02 + action = ( + self.env["account.payment"] + .with_context(active_model=records._name, active_ids=records.ids) + .action_register_payment() ) - # Instance: invoice - self.customer_invoice = self.env["account.invoice"].create( - { - "partner_id": self.customer.id, - "type": "out_invoice", - "account_id": self.account_recv.id, - "payment_term_id": False, - "journal_id": self.sale_journal.id, - "company_id": self.company.id, - "currency_id": self.currency_usd_id, - "invoice_line_ids": [(4, invoice_line.id)], - } + action = ( + self.env[action["res_model"]] + .with_context(action["context"]) + .create( + { + "payment_method_id": self.payment_method_manual_out.id, + "journal_id": self.bank_journal_euro.id, + } + ) + .create_payments() ) + payments = self.env[action["res_model"]] + if action.get("res_ids", False): + payments = payments.browse(action["res_id"]) + else: + payments = payments.search(action["domain"]) + for payment in payments: + self.assertEqual(payment.partner_id, self.alternate_partner) - def test_01_onchange(self): - # Instance: invoice - supplier_invoice = self.env["account.invoice"].new( + def test_07_payment_widget_in_invoices(self): + with Form(self.in_invoice) as form: + form.alternate_payer_id = self.alternate_partner + line = self.in_invoice.line_ids.filtered( + lambda r: r.account_id.user_type_id.type in ("receivable", "payable") + ) + payment_move = self.env["account.move"].create( { - "partner_id": self.vendor.id, - "type": "in_invoice", - "account_id": self.account_payable.id, - "payment_term_id": False, - "journal_id": self.purchase_journal.id, - "currency_id": self.currency_usd_id, - "company_id": self.company.id, - "invoice_line_ids": [ + "journal_id": self.bank_journal_euro.id, + "line_ids": [ + ( + 0, + 0, + { + "account_id": line.account_id.id, + "partner_id": line.partner_id.id, + "debit": line.credit, + "credit": line.debit, + }, + ), ( 0, 0, { - "name": "test", - "account_id": self.account_expense.id, - "price_unit": 2000.00, - "quantity": 1, - "product_id": self.product.id, + "account_id": self.bank_account.id, + "debit": line.debit, + "credit": line.credit, }, - ) + ), ], } ) - supplier_invoice.alternate_payer_id = self.payee - supplier_invoice._onchange_partner_id() - self.assertEqual(supplier_invoice.partner_bank_id, self.payee_bank) - self.assertEqual(supplier_invoice.account_id, self.account_payable_2) + payment_move.action_post() + self.assertFalse(self.in_invoice.invoice_has_outstanding) + self.in_invoice.post() + self.in_invoice.refresh() + self.assertTrue(self.in_invoice.invoice_has_outstanding) + self.in_invoice.write({"invoice_payment_state": "paid"}) + self.in_invoice.refresh() + self.assertFalse(self.in_invoice.invoice_has_outstanding) - def test_02_invoice(self): - """ - Test Setting an alternate commercial partner - """ - # Customer invoices - self.customer_invoice.alternate_payer_id = self.payor.id - self.customer_invoice._onchange_partner_id() - self.customer_invoice.action_invoice_open() - self.assertEqual(self.customer_invoice.state, "open") - line = self.customer_invoice.move_id.line_ids.filtered( - lambda li: li.account_id == self.account_recv + def test_08_payment_widget_out_invoices(self): + with Form(self.out_invoice) as form: + form.alternate_payer_id = self.alternate_partner + line = self.out_invoice.line_ids.filtered( + lambda r: r.account_id.user_type_id.type in ("receivable", "payable") ) - self.assertEqual(line.partner_id, self.payor) - ctx = { - "active_model": "account.invoice", - "active_ids": [self.customer_invoice.id], - } - register_payments = self.register_payments_model.with_context(ctx).create( + payment_move = self.env["account.move"].create( { - "payment_date": fields.Date.today(), - "journal_id": self.bank_journal_usd.id, - "payment_method_id": self.env.ref( - "account.account_payment_method_manual_in" - ).id, - } - ) - register_payments.create_payments() - self.assertEqual(self.customer_invoice.state, "paid") - # Vendor bills - self.vendor_invoice.alternate_payer_id = self.payee - self.vendor_invoice._onchange_partner_id() - self.vendor_invoice.action_invoice_open() - self.assertEqual(self.vendor_invoice.state, "open") - line = self.vendor_invoice.move_id.line_ids.filtered( - lambda li: li.account_id == self.account_payable_2 - ) - self.assertEqual(line.partner_id, self.payee) - ctx = { - "active_model": "account.invoice", - "active_ids": [self.vendor_invoice.id], - } - register_payments = self.register_payments_model.with_context(ctx).create( - { - "payment_date": fields.Date.today(), - "journal_id": self.bank_journal_usd.id, - "payment_method_id": self.env.ref( - "account.account_payment_method_manual_out" - ).id, - } - ) - register_payments.create_payments() - self.assertEqual(self.vendor_invoice.state, "paid") - - def test_03_payment_multiple_invoices(self): - """ - Test selecting multiple invoices with different alternate payer - """ - supplier_invoice_1 = self.env["account.invoice"].create( - { - "partner_id": self.customer.id, - "type": "in_invoice", - "account_id": self.account_payable.id, - "payment_term_id": False, - "journal_id": self.purchase_journal.id, - "currency_id": self.currency_usd_id, - "company_id": self.company.id, - "invoice_line_ids": [ + "journal_id": self.bank_journal_euro.id, + "line_ids": [ + ( + 0, + 0, + { + "account_id": line.account_id.id, + "partner_id": line.partner_id.id, + "debit": line.credit, + "credit": line.debit, + }, + ), ( 0, 0, { - "name": "test", - "account_id": self.account_expense.id, - "price_unit": 2000.00, - "quantity": 1, - "product_id": self.product.id, + "account_id": self.bank_account.id, + "debit": line.debit, + "credit": line.credit, }, - ) + ), ], } ) - supplier_invoice_2 = supplier_invoice_1.copy() - supplier_invoice_2.alternate_payer_id = self.payee - supplier_invoice_3 = supplier_invoice_1.copy() - supplier_invoice_1._onchange_partner_id() - supplier_invoice_1.action_invoice_open() - supplier_invoice_2._onchange_partner_id() - supplier_invoice_2.action_invoice_open() - supplier_invoice_3._onchange_partner_id() - supplier_invoice_3.action_invoice_open() - ctx = { - "active_model": "account.invoice", - "active_ids": [ - supplier_invoice_1.id, - supplier_invoice_2.id, - supplier_invoice_3.id, - ], - } - register_payments = self.register_payments_model.with_context(ctx).create( - { - "payment_date": fields.Date.today(), - "journal_id": self.bank_journal_usd.id, - "payment_method_id": self.env.ref( - "account.account_payment_method_manual_out" - ).id, - } - ) - res = register_payments.create_payments() - # ['domain'][('id', 'in', payments.ids), ('state', '=', 'posted')] - self.assertEqual(len(res["domain"][0][2]), 2) - self.assertEqual(supplier_invoice_1.state, "paid") - self.assertEqual(supplier_invoice_2.state, "paid") - self.assertEqual(supplier_invoice_3.state, "paid") - - def test_constrains(self): - with self.assertRaises(ValidationError): - self.env["account.invoice"].create( - { - "partner_id": self.vendor.id, - "type": "in_invoice", - "account_id": self.account_payable.id, - "payment_term_id": False, - "journal_id": self.purchase_journal.id, - "currency_id": self.currency_usd_id, - "company_id": self.company.id, - "partner_bank_id": self.payee_bank.id, - "invoice_line_ids": [ - ( - 0, - 0, - { - "name": "test", - "account_id": self.account_expense.id, - "price_unit": 2000.00, - "quantity": 1, - "product_id": self.product.id, - }, - ) - ], - } - ) + payment_move.action_post() + self.assertFalse(self.out_invoice.invoice_has_outstanding) + self.out_invoice.post() + self.out_invoice.refresh() + self.assertTrue(self.out_invoice.invoice_has_outstanding) + self.out_invoice.write({"invoice_payment_state": "paid"}) + self.out_invoice.refresh() + self.assertFalse(self.out_invoice.invoice_has_outstanding) diff --git a/account_invoice_alternate_payer/views/account_invoice_views.xml b/account_invoice_alternate_payer/views/account_invoice_views.xml deleted file mode 100644 index 5213c0359081..000000000000 --- a/account_invoice_alternate_payer/views/account_invoice_views.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - account.invoice.supplier.form - account.invoice - - - - - - - - - account.invoice.form - account.invoice - - - - - - - - - diff --git a/account_invoice_alternate_payer/views/account_move_views.xml b/account_invoice_alternate_payer/views/account_move_views.xml new file mode 100644 index 000000000000..58c0e0368e83 --- /dev/null +++ b/account_invoice_alternate_payer/views/account_move_views.xml @@ -0,0 +1,13 @@ + + + + account.move.supplier.form + account.move + + + + + + + + From cbad9a06c34019338b6826654e26eb57fc395e49 Mon Sep 17 00:00:00 2001 From: Olga Marco Date: Mon, 24 Jan 2022 13:06:47 +0100 Subject: [PATCH 05/13] [IMP] account_invoice_alternate_payer: black, isort, prettier --- account_invoice_alternate_payer/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py index 36dd42394367..baf7edd632f2 100644 --- a/account_invoice_alternate_payer/__manifest__.py +++ b/account_invoice_alternate_payer/__manifest__.py @@ -8,7 +8,7 @@ "license": "AGPL-3", "category": "Accounting", "author": "Eficent,Odoo Community Association (OCA)", - "website": "https://github.com/OCA/account-invoicing/", + "website": "https://github.com/OCA/account-invoicing", "depends": ["account"], "data": ["views/account_move_views.xml"], } From fd8fe003159b2c7cf52a2d2d64e51d082ebbe8d1 Mon Sep 17 00:00:00 2001 From: Olga Marco Date: Mon, 24 Jan 2022 13:09:08 +0100 Subject: [PATCH 06/13] [MIG] account_invoice_alternate_payer: Migration to 14.0 --- .../__manifest__.py | 2 +- .../models/account_move.py | 9 +- .../tests/test_account_invoice.py | 87 +++++++------------ .../views/account_move_views.xml | 2 +- 4 files changed, 35 insertions(+), 65 deletions(-) diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py index baf7edd632f2..774c768f58d1 100644 --- a/account_invoice_alternate_payer/__manifest__.py +++ b/account_invoice_alternate_payer/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Account Invoice Alternate Payer", "summary": "Set a alternate payor/payee in invoices", - "version": "13.0.1.0.0", + "version": "14.0.1.0.0", "license": "AGPL-3", "category": "Accounting", "author": "Eficent,Odoo Community Association (OCA)", diff --git a/account_invoice_alternate_payer/models/account_move.py b/account_invoice_alternate_payer/models/account_move.py index b52d8dd2c9f9..8cf1c724d534 100644 --- a/account_invoice_alternate_payer/models/account_move.py +++ b/account_invoice_alternate_payer/models/account_move.py @@ -31,9 +31,9 @@ def _compute_bank_partner_id(self): if move.is_outbound() and move.alternate_payer_id: move.bank_partner_id = move.alternate_payer_id - @api.onchange("partner_id", "alternate_payer_id") - def _onchange_partner_id(self): - return super()._onchange_partner_id() + @api.onchange("alternate_payer_id") + def _onchange_alternate_payer_id(self): + return self._onchange_partner_id() def _recompute_payment_terms_lines(self): super()._recompute_payment_terms_lines() @@ -55,7 +55,7 @@ def _compute_payments_widget_to_reconcile_info(self): move.invoice_has_outstanding = False if ( move.state != "posted" - or move.invoice_payment_state != "not_paid" + or move.payment_state != "not_paid" or not move.is_invoice(include_receipts=True) ): continue @@ -70,7 +70,6 @@ def _compute_payments_widget_to_reconcile_info(self): ("move_id.state", "=", "posted"), "&", ("move_id.state", "=", "draft"), - ("journal_id.post_at", "=", "bank_rec"), ("partner_id", "=", move.alternate_payer_id.id), ("reconciled", "=", False), "|", diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py index 119db82de8e4..c2630426d84c 100644 --- a/account_invoice_alternate_payer/tests/test_account_invoice.py +++ b/account_invoice_alternate_payer/tests/test_account_invoice.py @@ -1,19 +1,20 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo.tests import Form +from odoo.tests import Form, tagged -from odoo.addons.account.tests.account_test_savepoint import AccountTestInvoicingCommon +from odoo.addons.account.tests.common import AccountTestInvoicingCommon +@tagged("post_install", "-at_install") class TestAccountInvoiceAlternateCommercialPartner(AccountTestInvoicingCommon): @classmethod def setUpClass(cls, chart_template_ref=None): super().setUpClass(chart_template_ref=chart_template_ref) - cls.in_invoice = cls.init_invoice("in_invoice") - cls.out_invoice = cls.init_invoice("out_invoice") - cls.in_invoice_02 = cls.init_invoice("in_invoice") - cls.out_invoice_02 = cls.init_invoice("out_invoice") + cls.in_invoice = cls.init_invoice("in_invoice", products=cls.product_b) + cls.out_invoice = cls.init_invoice("out_invoice", products=cls.product_a) + cls.in_invoice_02 = cls.init_invoice("in_invoice", products=cls.product_a) + cls.out_invoice_02 = cls.init_invoice("out_invoice", products=cls.product_b) cls.alternate_partner = cls.env["res.partner"].create( {"name": "Alternate Payer"} ) @@ -75,16 +76,12 @@ def test_02_onchange_in_invoice(self): def test_03_payment_out_invoice(self): with Form(self.out_invoice) as form: form.alternate_payer_id = self.alternate_partner - self.out_invoice.post() + self.out_invoice._post() records = self.out_invoice - action = ( - self.env["account.payment"] - .with_context(active_model=records._name, active_ids=records.ids) - .action_register_payment() - ) + ctx = {"active_model": records._name, "active_ids": records.ids} payment = ( - self.env[action["res_model"]] - .with_context(action["context"]) + self.env["account.payment"] + .with_context(ctx) .create( { "payment_method_id": self.payment_method_manual_out.id, @@ -92,22 +89,17 @@ def test_03_payment_out_invoice(self): } ) ) - payment.post() self.assertEqual(payment.partner_id, self.alternate_partner) def test_04_payment_in_invoice(self): with Form(self.in_invoice) as form: form.alternate_payer_id = self.alternate_partner - self.in_invoice.post() + self.in_invoice._post() records = self.in_invoice - action = ( - self.env["account.payment"] - .with_context(active_model=records._name, active_ids=records.ids) - .action_register_payment() - ) + ctx = {"active_model": records._name, "active_ids": records.ids} payment = ( - self.env[action["res_model"]] - .with_context(action["context"]) + self.env["account.payment"] + .with_context(ctx) .create( { "payment_method_id": self.payment_method_manual_in.id, @@ -115,70 +107,49 @@ def test_04_payment_in_invoice(self): } ) ) - payment.post() self.assertEqual(payment.partner_id, self.alternate_partner) def test_05_payment_out_invoices(self): with Form(self.out_invoice) as form: form.alternate_payer_id = self.alternate_partner - self.out_invoice.post() + self.out_invoice._post() with Form(self.out_invoice_02) as form: form.alternate_payer_id = self.alternate_partner - self.out_invoice_02.post() + self.out_invoice_02._post() records = self.out_invoice | self.out_invoice_02 - action = ( + ctx = {"active_model": records._name, "active_ids": records.ids} + payments = ( self.env["account.payment"] - .with_context(active_model=records._name, active_ids=records.ids) - .action_register_payment() - ) - action = ( - self.env[action["res_model"]] - .with_context(action["context"]) + .with_context(ctx) .create( { "payment_method_id": self.payment_method_manual_out.id, "journal_id": self.bank_journal_euro.id, } ) - .create_payments() ) - payments = self.env[action["res_model"]] - if action.get("res_ids", False): - payments = payments.browse(action["res_id"]) - else: - payments = payments.search(action["domain"]) for payment in payments: self.assertEqual(payment.partner_id, self.alternate_partner) def test_06_payment_in_invoices(self): with Form(self.in_invoice) as form: form.alternate_payer_id = self.alternate_partner - self.in_invoice.post() + self.in_invoice._post() with Form(self.in_invoice_02) as form: form.alternate_payer_id = self.alternate_partner - self.in_invoice_02.post() + self.in_invoice_02._post() records = self.in_invoice | self.in_invoice_02 - action = ( + ctx = {"active_model": records._name, "active_ids": records.ids} + payments = ( self.env["account.payment"] - .with_context(active_model=records._name, active_ids=records.ids) - .action_register_payment() - ) - action = ( - self.env[action["res_model"]] - .with_context(action["context"]) + .with_context(ctx) .create( { "payment_method_id": self.payment_method_manual_out.id, "journal_id": self.bank_journal_euro.id, } ) - .create_payments() ) - payments = self.env[action["res_model"]] - if action.get("res_ids", False): - payments = payments.browse(action["res_id"]) - else: - payments = payments.search(action["domain"]) for payment in payments: self.assertEqual(payment.partner_id, self.alternate_partner) @@ -216,10 +187,10 @@ def test_07_payment_widget_in_invoices(self): ) payment_move.action_post() self.assertFalse(self.in_invoice.invoice_has_outstanding) - self.in_invoice.post() + self.in_invoice._post() self.in_invoice.refresh() self.assertTrue(self.in_invoice.invoice_has_outstanding) - self.in_invoice.write({"invoice_payment_state": "paid"}) + self.in_invoice.write({"payment_state": "paid"}) self.in_invoice.refresh() self.assertFalse(self.in_invoice.invoice_has_outstanding) @@ -257,9 +228,9 @@ def test_08_payment_widget_out_invoices(self): ) payment_move.action_post() self.assertFalse(self.out_invoice.invoice_has_outstanding) - self.out_invoice.post() + self.out_invoice._post() self.out_invoice.refresh() self.assertTrue(self.out_invoice.invoice_has_outstanding) - self.out_invoice.write({"invoice_payment_state": "paid"}) + self.out_invoice.write({"payment_state": "paid"}) self.out_invoice.refresh() self.assertFalse(self.out_invoice.invoice_has_outstanding) diff --git a/account_invoice_alternate_payer/views/account_move_views.xml b/account_invoice_alternate_payer/views/account_move_views.xml index 58c0e0368e83..b0c3eb12ad83 100644 --- a/account_invoice_alternate_payer/views/account_move_views.xml +++ b/account_invoice_alternate_payer/views/account_move_views.xml @@ -6,7 +6,7 @@ - + From 391263fdba5a654e9f1841ead5cd681de4c39a43 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Wed, 31 Aug 2022 14:14:33 +0000 Subject: [PATCH 07/13] [UPD] Update account_invoice_alternate_payer.pot --- .../i18n/account_invoice_alternate_payer.pot | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot index 4cc3eae10200..c6f1bd6d1347 100644 --- a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot +++ b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 13.0\n" +"Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -14,17 +14,31 @@ msgstr "" "Plural-Forms: \n" #. module: account_invoice_alternate_payer +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_bank_statement_line__alternate_payer_id +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__alternate_payer_id +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__alternate_payer_id #: model_terms:ir.ui.view,arch_db:account_invoice_alternate_payer.view_move_form -msgid "Alternate Payee" +msgid "Alternate Payer" msgstr "" #. module: account_invoice_alternate_payer -#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__alternate_payer_id -msgid "Alternate Payer" +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__display_name +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__display_name +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register__display_name +msgid "Display Name" +msgstr "" + +#. module: account_invoice_alternate_payer +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__id +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__id +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register__id +msgid "ID" msgstr "" #. module: account_invoice_alternate_payer +#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_bank_statement_line__alternate_payer_id #: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_move__alternate_payer_id +#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_payment__alternate_payer_id msgid "" "If set, this will be the partner that we expect to pay or to be paid by. If " "not set, the payor is by default the commercial" @@ -32,7 +46,14 @@ msgstr "" #. module: account_invoice_alternate_payer #: model:ir.model,name:account_invoice_alternate_payer.model_account_move -msgid "Journal Entries" +msgid "Journal Entry" +msgstr "" + +#. module: account_invoice_alternate_payer +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move____last_update +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment____last_update +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register____last_update +msgid "Last Modified on" msgstr "" #. module: account_invoice_alternate_payer From a9d0b46c87aa4b31f61b822c547cc372c67931d8 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 31 Aug 2022 14:21:42 +0000 Subject: [PATCH 08/13] [UPD] README.rst --- account_invoice_alternate_payer/README.rst | 10 +++++----- .../static/description/index.html | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/account_invoice_alternate_payer/README.rst b/account_invoice_alternate_payer/README.rst index ec24af360412..747824489743 100644 --- a/account_invoice_alternate_payer/README.rst +++ b/account_invoice_alternate_payer/README.rst @@ -14,13 +14,13 @@ Account Invoice Alternate Payer :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github - :target: https://github.com/OCA/account-invoicing/tree/13.0/account_invoice_alternate_payer + :target: https://github.com/OCA/account-invoicing/tree/14.0/account_invoice_alternate_payer :alt: OCA/account-invoicing .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/account-invoicing-13-0/account-invoicing-13-0-account_invoice_alternate_payer + :target: https://translation.odoo-community.org/projects/account-invoicing-14-0/account-invoicing-14-0-account_invoice_alternate_payer :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/95/13.0 + :target: https://runbot.odoo-community.org/runbot/95/14.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -47,7 +47,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -78,6 +78,6 @@ 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/account-invoicing `_ project on GitHub. +This module is part of the `OCA/account-invoicing `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_invoice_alternate_payer/static/description/index.html b/account_invoice_alternate_payer/static/description/index.html index ffa32435c024..a335c6cd3572 100644 --- a/account_invoice_alternate_payer/static/description/index.html +++ b/account_invoice_alternate_payer/static/description/index.html @@ -367,7 +367,7 @@

Account Invoice Alternate Payer

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

This module allows to enter an alternative payer in the customer invoice or vendor bill.

This allows, that we pay or expect to get paid by another partner other @@ -394,7 +394,7 @@

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.

+feedback.

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

@@ -425,7 +425,7 @@

Maintainers

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/account-invoicing project on GitHub.

+

This module is part of the OCA/account-invoicing project on GitHub.

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

From eb1ec7ebbb56cf93f9d688b07dc3fb42bf42cf38 Mon Sep 17 00:00:00 2001 From: Christopher Ormaza Date: Wed, 7 Sep 2022 08:43:36 -0500 Subject: [PATCH 09/13] [14.0][FIX] Set rigth partner on alternate invoices lines --- .../models/account_move.py | 13 ++++++ .../tests/test_account_invoice.py | 43 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/account_invoice_alternate_payer/models/account_move.py b/account_invoice_alternate_payer/models/account_move.py index 8cf1c724d534..898963b65b2f 100644 --- a/account_invoice_alternate_payer/models/account_move.py +++ b/account_invoice_alternate_payer/models/account_move.py @@ -117,3 +117,16 @@ def _compute_payments_widget_to_reconcile_info(self): info["title"] = type_payment move.invoice_outstanding_credits_debits_widget = json.dumps(info) move.invoice_has_outstanding = True + + +class AccountMoveLine(models.Model): + + _inherit = "account.move.line" + + def write(self, values): + # CHECK ME: this change to commercial partner when find difference between main partner + # https://github.com/odoo/odoo/blob/0f90852818a334d66ed8a6781f5abdc022f76ff7/addons/account/models/account_move.py#L2695 # noqa: B950 + if "partner_id" in values and len(values.keys()) == 1: + lines_to_skip = self.filtered(lambda x: x.move_id.alternate_payer_id) + return super(AccountMoveLine, self - lines_to_skip).write(values) + return super(AccountMoveLine, self).write(values) diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py index c2630426d84c..a90668284c8c 100644 --- a/account_invoice_alternate_payer/tests/test_account_invoice.py +++ b/account_invoice_alternate_payer/tests/test_account_invoice.py @@ -55,6 +55,29 @@ def test_01_onchange_out_invoice(self): self.out_invoice.bank_partner_id, self.out_invoice.company_id.partner_id ) + def test_01_1_post_out_invoice(self): + with Form(self.out_invoice) as form: + form.alternate_payer_id = self.alternate_partner + self.out_invoice_posted = form.save() + self.out_invoice_posted.action_post() + self.assertEqual( + self.out_invoice_posted.line_ids.filtered( + lambda r: r.account_id.user_type_id.type in ("receivable", "payable") + ).mapped("partner_id"), + self.alternate_partner, + ) + self.assertEqual( + self.out_invoice_posted.line_ids.filtered( + lambda r: r.account_id.user_type_id.type + not in ("receivable", "payable") + ).mapped("partner_id"), + self.out_invoice_posted.partner_id, + ) + self.assertEqual( + self.out_invoice_posted.bank_partner_id, + self.out_invoice_posted.company_id.partner_id, + ) + def test_02_onchange_in_invoice(self): with Form(self.in_invoice) as form: form.alternate_payer_id = self.alternate_partner @@ -73,6 +96,26 @@ def test_02_onchange_in_invoice(self): ) self.assertEqual(self.in_invoice.bank_partner_id, self.alternate_partner) + def test_02_1_post_in_invoice(self): + with Form(self.in_invoice) as form: + form.alternate_payer_id = self.alternate_partner + self.in_invoice_posted = form.save() + self.in_invoice_posted.action_post() + self.assertEqual( + self.in_invoice_posted.line_ids.filtered( + lambda r: r.account_id.user_type_id.type in ("receivable", "payable") + ).mapped("partner_id"), + self.alternate_partner, + ) + self.assertEqual( + self.in_invoice_posted.line_ids.filtered( + lambda r: r.account_id.user_type_id.type + not in ("receivable", "payable") + ).mapped("partner_id"), + self.out_invoice.partner_id, + ) + self.assertEqual(self.in_invoice_posted.bank_partner_id, self.alternate_partner) + def test_03_payment_out_invoice(self): with Form(self.out_invoice) as form: form.alternate_payer_id = self.alternate_partner From 51904b13dc1af12f6de5e4f464b1b3af534e3dbc Mon Sep 17 00:00:00 2001 From: oca-ci Date: Mon, 2 Jan 2023 16:35:38 +0000 Subject: [PATCH 10/13] [UPD] Update account_invoice_alternate_payer.pot --- .../i18n/account_invoice_alternate_payer.pot | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot index c6f1bd6d1347..fb5c666b026d 100644 --- a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot +++ b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot @@ -23,6 +23,7 @@ msgstr "" #. module: account_invoice_alternate_payer #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__display_name +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move_line__display_name #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__display_name #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register__display_name msgid "Display Name" @@ -30,6 +31,7 @@ msgstr "" #. module: account_invoice_alternate_payer #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__id +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move_line__id #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__id #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register__id msgid "ID" @@ -49,8 +51,14 @@ msgstr "" msgid "Journal Entry" msgstr "" +#. module: account_invoice_alternate_payer +#: model:ir.model,name:account_invoice_alternate_payer.model_account_move_line +msgid "Journal Item" +msgstr "" + #. module: account_invoice_alternate_payer #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move____last_update +#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move_line____last_update #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment____last_update #: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register____last_update msgid "Last Modified on" From 2b97dc942fa75b5ce60a18e41491a12d65ce371c Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 2 Jan 2023 16:43:50 +0000 Subject: [PATCH 11/13] account_invoice_alternate_payer 14.0.1.0.1 --- account_invoice_alternate_payer/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py index 774c768f58d1..77d93fabe824 100644 --- a/account_invoice_alternate_payer/__manifest__.py +++ b/account_invoice_alternate_payer/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Account Invoice Alternate Payer", "summary": "Set a alternate payor/payee in invoices", - "version": "14.0.1.0.0", + "version": "14.0.1.0.1", "license": "AGPL-3", "category": "Accounting", "author": "Eficent,Odoo Community Association (OCA)", From f4e2c984a8650fda0534ce1fb7374a18af079517 Mon Sep 17 00:00:00 2001 From: Ruchir Shukla Date: Sat, 4 Mar 2023 20:08:48 +0530 Subject: [PATCH 12/13] [IMP]account_invoice_alternate_payer:black, isort, prettier --- .../odoo/addons/account_invoice_alternate_payer | 1 + setup/account_invoice_alternate_payer/setup.py | 6 ++++++ 2 files changed, 7 insertions(+) create mode 120000 setup/account_invoice_alternate_payer/odoo/addons/account_invoice_alternate_payer create mode 100644 setup/account_invoice_alternate_payer/setup.py diff --git a/setup/account_invoice_alternate_payer/odoo/addons/account_invoice_alternate_payer b/setup/account_invoice_alternate_payer/odoo/addons/account_invoice_alternate_payer new file mode 120000 index 000000000000..8060f345cc40 --- /dev/null +++ b/setup/account_invoice_alternate_payer/odoo/addons/account_invoice_alternate_payer @@ -0,0 +1 @@ +../../../../account_invoice_alternate_payer \ No newline at end of file diff --git a/setup/account_invoice_alternate_payer/setup.py b/setup/account_invoice_alternate_payer/setup.py new file mode 100644 index 000000000000..28c57bb64031 --- /dev/null +++ b/setup/account_invoice_alternate_payer/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 116d46f905b7380357e4c96b71a1527e23ca6516 Mon Sep 17 00:00:00 2001 From: Ruchir Shukla Date: Sat, 4 Mar 2023 20:13:55 +0530 Subject: [PATCH 13/13] [MIG][15.0]account_invoice_alternate_payer: Migration to 15.0 --- .../__manifest__.py | 2 +- .../migrations/13.0.1.0.0/post-migration.py | 32 ------------------- .../models/account_move.py | 9 ++++-- .../tests/test_account_invoice.py | 8 ++--- 4 files changed, 11 insertions(+), 40 deletions(-) delete mode 100644 account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py index 77d93fabe824..a3f42c986c4a 100644 --- a/account_invoice_alternate_payer/__manifest__.py +++ b/account_invoice_alternate_payer/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Account Invoice Alternate Payer", "summary": "Set a alternate payor/payee in invoices", - "version": "14.0.1.0.1", + "version": "15.0.1.0.0", "license": "AGPL-3", "category": "Accounting", "author": "Eficent,Odoo Community Association (OCA)", diff --git a/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py b/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py deleted file mode 100644 index 3cd7f21532be..000000000000 --- a/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py +++ /dev/null @@ -1,32 +0,0 @@ -from openupgradelib import openupgrade - - -@openupgrade.migrate() -def migrate(env, version): - openupgrade.logged_query( - env.cr, - """ - UPDATE account_move am - SET alternate_payer_id = ai.alternate_payer_id - FROM account_invoice ai - WHERE ai.alternate_payer_id IS NOT NULL - AND ai.id = am.old_invoice_id - """, - ) - openupgrade.logged_query( - env.cr, - """ - UPDATE account_move_line aml - SET partner_id = am.alternate_payer_id - FROM - account_move am, - account_account as aa, - account_account_type as aat - WHERE am.alternate_payer_id IS NOT NULL - AND am.id = aml.move_id - AND am.state = 'draft' - AND aat.type in ('receivable', 'payable') - AND aa.id = aml.account_id - AND aat.id = aa.user_type_id - """, - ) diff --git a/account_invoice_alternate_payer/models/account_move.py b/account_invoice_alternate_payer/models/account_move.py index 898963b65b2f..ff055c51b9f1 100644 --- a/account_invoice_alternate_payer/models/account_move.py +++ b/account_invoice_alternate_payer/models/account_move.py @@ -23,29 +23,31 @@ class AccountMove(models.Model): @api.depends("commercial_partner_id", "alternate_payer_id") def _compute_bank_partner_id(self): - super( + res = super( AccountMove, self.filtered(lambda r: not r.alternate_payer_id or not r.is_outbound()), )._compute_bank_partner_id() for move in self: if move.is_outbound() and move.alternate_payer_id: move.bank_partner_id = move.alternate_payer_id + return res @api.onchange("alternate_payer_id") def _onchange_alternate_payer_id(self): return self._onchange_partner_id() def _recompute_payment_terms_lines(self): - super()._recompute_payment_terms_lines() + res = super()._recompute_payment_terms_lines() for invoice in self: if invoice.alternate_payer_id: invoice.line_ids.filtered( lambda r: r.account_id.user_type_id.type in ("receivable", "payable") ).update({"partner_id": invoice.alternate_payer_id.id}) + return res def _compute_payments_widget_to_reconcile_info(self): - super( + res = super( AccountMove, self.filtered(lambda r: not r.alternate_payer_id) )._compute_payments_widget_to_reconcile_info() for move in self: @@ -117,6 +119,7 @@ def _compute_payments_widget_to_reconcile_info(self): info["title"] = type_payment move.invoice_outstanding_credits_debits_widget = json.dumps(info) move.invoice_has_outstanding = True + return res class AccountMoveLine(models.Model): diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py index a90668284c8c..568cbe05a56c 100644 --- a/account_invoice_alternate_payer/tests/test_account_invoice.py +++ b/account_invoice_alternate_payer/tests/test_account_invoice.py @@ -124,7 +124,7 @@ def test_03_payment_out_invoice(self): ctx = {"active_model": records._name, "active_ids": records.ids} payment = ( self.env["account.payment"] - .with_context(ctx) + .with_context(**ctx) .create( { "payment_method_id": self.payment_method_manual_out.id, @@ -142,7 +142,7 @@ def test_04_payment_in_invoice(self): ctx = {"active_model": records._name, "active_ids": records.ids} payment = ( self.env["account.payment"] - .with_context(ctx) + .with_context(**ctx) .create( { "payment_method_id": self.payment_method_manual_in.id, @@ -163,7 +163,7 @@ def test_05_payment_out_invoices(self): ctx = {"active_model": records._name, "active_ids": records.ids} payments = ( self.env["account.payment"] - .with_context(ctx) + .with_context(**ctx) .create( { "payment_method_id": self.payment_method_manual_out.id, @@ -185,7 +185,7 @@ def test_06_payment_in_invoices(self): ctx = {"active_model": records._name, "active_ids": records.ids} payments = ( self.env["account.payment"] - .with_context(ctx) + .with_context(**ctx) .create( { "payment_method_id": self.payment_method_manual_out.id,