From 824b2ffaa940d1f2a1550c3b89a2d860dff88008 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Mon, 1 Jul 2024 13:29:26 -0500 Subject: [PATCH] [MIG] account_cash_invoice: Migration to 16.0 --- account_cash_invoice/README.rst | 25 ++-- account_cash_invoice/__manifest__.py | 6 +- account_cash_invoice/models/__init__.py | 2 +- .../models/account_bank_statement.py | 20 ---- account_cash_invoice/models/account_move.py | 23 ++++ account_cash_invoice/readme/CONTRIBUTORS.rst | 3 + account_cash_invoice/readme/ROADMAP.rst | 1 + account_cash_invoice/readme/USAGE.rst | 11 +- .../security/ir.model.access.csv | 3 +- .../static/description/index.html | 38 +++--- .../tests/test_pay_invoice.py | 51 ++++---- .../views/account_journal_dashboard_view.xml | 24 ++++ account_cash_invoice/wizard/__init__.py | 3 +- .../wizard/cash_invoice_in.py | 102 ---------------- .../wizard/cash_invoice_out.py | 110 ------------------ .../wizard/cash_invoice_out.xml | 58 --------- .../wizard/cash_pay_invoice.py | 108 +++++++++++++++++ ...sh_invoice_in.xml => cash_pay_invoice.xml} | 27 ++--- 18 files changed, 241 insertions(+), 374 deletions(-) delete mode 100644 account_cash_invoice/models/account_bank_statement.py create mode 100644 account_cash_invoice/models/account_move.py create mode 100644 account_cash_invoice/views/account_journal_dashboard_view.xml delete mode 100644 account_cash_invoice/wizard/cash_invoice_in.py delete mode 100644 account_cash_invoice/wizard/cash_invoice_out.py delete mode 100644 account_cash_invoice/wizard/cash_invoice_out.xml create mode 100644 account_cash_invoice/wizard/cash_pay_invoice.py rename account_cash_invoice/wizard/{cash_invoice_in.xml => cash_pay_invoice.xml} (59%) diff --git a/account_cash_invoice/README.rst b/account_cash_invoice/README.rst index 39e25df7d267..ed233db5fda1 100644 --- a/account_cash_invoice/README.rst +++ b/account_cash_invoice/README.rst @@ -17,13 +17,13 @@ Account cash invoice :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--payment-lightgray.png?logo=github - :target: https://github.com/OCA/account-payment/tree/14.0/account_cash_invoice + :target: https://github.com/OCA/account-payment/tree/16.0/account_cash_invoice :alt: OCA/account-payment .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/account-payment-14-0/account-payment-14-0-account_cash_invoice + :target: https://translation.odoo-community.org/projects/account-payment-16-0/account-payment-16-0-account_cash_invoice :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/account-payment&target_branch=14.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/account-payment&target_branch=16.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -42,13 +42,10 @@ Usage #. Go to *Settings* and activate the developer mode. #. Go to *Settings / Users & Companies / Users* and set the flag 'Show Full Accounting Features'. -#. Go to *Invoicing / Dashboard* and create and/or open an existing - Cash Statement from a Cash Journal. -#. Press the button **Pay Invoice** to pay a Supplier Invoice or a Customer - Refund. You will need to select the expected Journal -#. Select **Collect Payment from Invoice** in to receive a payment of an - existing Customer Invoice or a Supplier Refund. -#. Press **Validate** on the statement. The payment will then be reconciled +#. Go to *Invoicing / Dashboard* from a Cash Journal. +#. On the Additional options, Press the button **Pay Invoice** to pay a Supplier a Customer Invoice/Refund. +#. Select the invoice type and select invoice to pay. +#. Press **Pay invoice** on the statement. The payment will then be reconciled with the invoice. Known issues / Roadmap @@ -56,6 +53,7 @@ Known issues / Roadmap * Cannot pay invoices in a different currency than that defined in the journal associated to the payment method used to pay/collect payment. +* Cannot select a specific journal item on invoice with some lines(i.e. when use Payment terms) Bug Tracker =========== @@ -63,7 +61,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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -82,6 +80,9 @@ Contributors * Jordi Ballester * Jaime Arroyo * Manuel Alejandro +* `Tecnativa `_: + + * Carlos Lopez Maintainers ~~~~~~~~~~~ @@ -96,6 +97,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-payment `_ project on GitHub. +This module is part of the `OCA/account-payment `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_cash_invoice/__manifest__.py b/account_cash_invoice/__manifest__.py index b5e0b45ad84a..6c0c417e4435 100644 --- a/account_cash_invoice/__manifest__.py +++ b/account_cash_invoice/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Account cash invoice", - "version": "14.0.1.3.0", + "version": "16.0.1.0.0", "category": "Accounting", "author": "Creu Blanca,Odoo Community Association (OCA)", "website": "https://github.com/OCA/account-payment", @@ -12,7 +12,7 @@ "depends": ["account"], "data": [ "security/ir.model.access.csv", - "wizard/cash_invoice_out.xml", - "wizard/cash_invoice_in.xml", + "wizard/cash_pay_invoice.xml", + "views/account_journal_dashboard_view.xml", ], } diff --git a/account_cash_invoice/models/__init__.py b/account_cash_invoice/models/__init__.py index 206ced1c0c4c..f74bf16363ce 100644 --- a/account_cash_invoice/models/__init__.py +++ b/account_cash_invoice/models/__init__.py @@ -1,4 +1,4 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). from . import account_bank_statement_line -from . import account_bank_statement +from . import account_move diff --git a/account_cash_invoice/models/account_bank_statement.py b/account_cash_invoice/models/account_bank_statement.py deleted file mode 100644 index 4726d43fb945..000000000000 --- a/account_cash_invoice/models/account_bank_statement.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2021 Creu Blanca -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import models - - -class AccountBankStatement(models.Model): - - _inherit = "account.bank.statement" - - def button_post(self): - lines_of_moves_to_reconcile = self.line_ids.filtered( - lambda line: line.move_id.state != "posted" and line.invoice_id - ) - result = super(AccountBankStatement, self).button_post() - for line in lines_of_moves_to_reconcile: - (line.invoice_id.line_ids | line.move_id.line_ids).filtered( - lambda l: l.account_internal_type in ("receivable", "payable") - ).reconcile() - return result diff --git a/account_cash_invoice/models/account_move.py b/account_cash_invoice/models/account_move.py new file mode 100644 index 000000000000..f22ac81c4d28 --- /dev/null +++ b/account_cash_invoice/models/account_move.py @@ -0,0 +1,23 @@ +# Copyright 2021 Creu Blanca +# Copyright (C) 2024 Tecnativa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models + + +class AccountMove(models.Model): + _inherit = "account.move" + + def _post(self, soft=True): + statement_lines_to_reconcile = self.filtered( + lambda move: move.state != "posted" and move.statement_line_id.invoice_id + ).mapped("statement_line_id") + result = super()._post(soft=soft) + for statement_line in statement_lines_to_reconcile: + ( + statement_line.invoice_id.line_ids | statement_line.move_id.line_ids + ).filtered( + lambda l: l.account_id.account_type + in ("asset_receivable", "liability_payable") + ).reconcile() + return result diff --git a/account_cash_invoice/readme/CONTRIBUTORS.rst b/account_cash_invoice/readme/CONTRIBUTORS.rst index b92554265171..e8688b86ed7f 100644 --- a/account_cash_invoice/readme/CONTRIBUTORS.rst +++ b/account_cash_invoice/readme/CONTRIBUTORS.rst @@ -2,3 +2,6 @@ * Jordi Ballester * Jaime Arroyo * Manuel Alejandro +* `Tecnativa `_: + + * Carlos Lopez \ No newline at end of file diff --git a/account_cash_invoice/readme/ROADMAP.rst b/account_cash_invoice/readme/ROADMAP.rst index 83dd2652f0af..4fc2ad4b05a4 100644 --- a/account_cash_invoice/readme/ROADMAP.rst +++ b/account_cash_invoice/readme/ROADMAP.rst @@ -1,2 +1,3 @@ * Cannot pay invoices in a different currency than that defined in the journal associated to the payment method used to pay/collect payment. +* Cannot select a specific journal item on invoice with some lines(i.e. when use Payment terms) diff --git a/account_cash_invoice/readme/USAGE.rst b/account_cash_invoice/readme/USAGE.rst index 1d3734f7826a..169e45af6975 100644 --- a/account_cash_invoice/readme/USAGE.rst +++ b/account_cash_invoice/readme/USAGE.rst @@ -1,11 +1,8 @@ #. Go to *Settings* and activate the developer mode. #. Go to *Settings / Users & Companies / Users* and set the flag 'Show Full Accounting Features'. -#. Go to *Invoicing / Dashboard* and create and/or open an existing - Cash Statement from a Cash Journal. -#. Press the button **Pay Invoice** to pay a Supplier Invoice or a Customer - Refund. You will need to select the expected Journal -#. Select **Collect Payment from Invoice** in to receive a payment of an - existing Customer Invoice or a Supplier Refund. -#. Press **Validate** on the statement. The payment will then be reconciled +#. Go to *Invoicing / Dashboard* from a Cash Journal. +#. On the Additional options, Press the button **Pay Invoice** to pay a Supplier a Customer Invoice/Refund. +#. Select the invoice type and select invoice to pay. +#. Press **Pay invoice** on the statement. The payment will then be reconciled with the invoice. diff --git a/account_cash_invoice/security/ir.model.access.csv b/account_cash_invoice/security/ir.model.access.csv index a3882b03957a..bf5e867732a1 100644 --- a/account_cash_invoice/security/ir.model.access.csv +++ b/account_cash_invoice/security/ir.model.access.csv @@ -1,3 +1,2 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_cash_invoice_in,access_cash_invoice_in,model_cash_invoice_in,base.group_user,1,1,1,1 -access_cash_invoice_out,access_cash_invoice_out,model_cash_invoice_out,base.group_user,1,1,1,1 +access_cash_pay_invoice,access_cash_pay_invoice,model_cash_pay_invoice,base.group_user,1,1,1,1 diff --git a/account_cash_invoice/static/description/index.html b/account_cash_invoice/static/description/index.html index 30f62e6bd406..dfd80ed6d22e 100644 --- a/account_cash_invoice/static/description/index.html +++ b/account_cash_invoice/static/description/index.html @@ -1,4 +1,3 @@ - @@ -369,7 +368,7 @@

Account cash invoice

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:3c80cda9cf12062ae728ee9d546c9363dc87f09fba3248d8ed5867f63ca777e3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: LGPL-3 OCA/account-payment Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/account-payment Translate me on Weblate Try me on Runboat

This modules allows to pay an existing Supplier Invoice / Customer Refund, or to collect payment for an existing Customer Invoice from a Cash Statement.

Table of contents

@@ -392,13 +391,10 @@

Usage

  • Go to Settings and activate the developer mode.
  • Go to Settings / Users & Companies / Users and set the flag ‘Show Full Accounting Features’.
  • -
  • Go to Invoicing / Dashboard and create and/or open an existing -Cash Statement from a Cash Journal.
  • -
  • Press the button Pay Invoice to pay a Supplier Invoice or a Customer -Refund. You will need to select the expected Journal
  • -
  • Select Collect Payment from Invoice in to receive a payment of an -existing Customer Invoice or a Supplier Refund.
  • -
  • Press Validate on the statement. The payment will then be reconciled +
  • Go to Invoicing / Dashboard from a Cash Journal.
  • +
  • On the Additional options, Press the button Pay Invoice to pay a Supplier a Customer Invoice/Refund.
  • +
  • Select the invoice type and select invoice to pay.
  • +
  • Press Pay invoice on the statement. The payment will then be reconciled with the invoice.
  • @@ -407,6 +403,7 @@

    Known issues / Roadmap

    • Cannot pay invoices in a different currency than that defined in the journal associated to the payment method used to pay/collect payment.
    • +
    • Cannot select a specific journal item on invoice with some lines(i.e. when use Payment terms)
    @@ -414,7 +411,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 to smash it by providing a detailed and welcomed -feedback.

    +feedback.

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

    @@ -427,11 +424,22 @@

    Authors

    Contributors

    +
    @@ -441,7 +449,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-payment project on GitHub.

    +

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

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

    diff --git a/account_cash_invoice/tests/test_pay_invoice.py b/account_cash_invoice/tests/test_pay_invoice.py index 0d674ca337ca..7eb545d1a57c 100644 --- a/account_cash_invoice/tests/test_pay_invoice.py +++ b/account_cash_invoice/tests/test_pay_invoice.py @@ -1,10 +1,15 @@ # Copyright 2017-2021 Creu Blanca +# Copyright (C) 2024 Tecnativa # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from odoo.tests.common import Form, SavepointCase +from odoo.tests import tagged +from odoo.tests.common import Form +from odoo.addons.base.tests.common import BaseCommon -class TestSessionPayInvoice(SavepointCase): + +@tagged("post_install", "-at_install") +class TestSessionPayInvoice(BaseCommon): @classmethod def setUpClass(cls): super().setUpClass() @@ -15,10 +20,10 @@ def setUpClass(cls): cls.product = cls.env.ref("product.product_delivery_02") account = cls.env["account.account"].create( { - "code": "test_cash_pay_invoice", + "code": "449000", "company_id": cls.company.id, "name": "Test", - "user_type_id": cls.env.ref("account.data_account_type_revenue").id, + "account_type": "income", "reconcile": True, } ) @@ -38,12 +43,12 @@ def setUpClass(cls): "name": "Producto de prueba", "quantity": 1.0, "price_unit": 100.0, + "tax_ids": [], }, ) ], } ) - cls.invoice_out._onchange_invoice_line_ids() cls.invoice_out.action_post() cls.invoice_out.name = "2999/99999" cls.invoice_in = cls.AccountMove.create( @@ -63,12 +68,12 @@ def setUpClass(cls): "account_id": account.id, "quantity": 1.0, "price_unit": 100.0, + "tax_ids": [], }, ) ], } ) - cls.invoice_in._onchange_invoice_line_ids() cls.invoice_in.action_post() cls.invoice_in.name = "2999/99999" cls.journal = ( @@ -80,38 +85,32 @@ def setUpClass(cls): ) def test_bank_statement(self): - statement = self.env["account.bank.statement"].create( - {"name": "Statement", "journal_id": self.journal.id} - ) - invoice_in_obj = self.env["cash.invoice.in"].with_context( - active_ids=statement.ids, active_model=statement._name + invoice_in_obj = self.env["cash.pay.invoice"].with_context( + active_ids=self.journal.ids, active_model=self.journal._name ) with Form(invoice_in_obj) as in_invoice: + in_invoice.invoice_type = "vendor" in_invoice.invoice_id = self.invoice_in self.assertEqual(-100, in_invoice.amount) - self.assertEqual(in_invoice.journal_count, 1) - invoice_in_obj.browse(in_invoice.id).run() + self.assertEqual(in_invoice.journal_id, self.journal) + invoice_in_obj.browse(in_invoice.id).action_pay_invoice() - invoice_out_obj = self.env["cash.invoice.out"].with_context( - active_ids=statement.ids, active_model=statement._name + invoice_out_obj = self.env["cash.pay.invoice"].with_context( + active_ids=self.journal.ids, active_model=self.journal._name ) with Form(invoice_out_obj) as out_invoice: + out_invoice.invoice_type = "customer" out_invoice.invoice_id = self.invoice_out self.assertEqual(100, out_invoice.amount) - self.assertEqual(out_invoice.journal_count, 1) - invoice_out_obj.browse(out_invoice.id).run() - statement.balance_end_real = statement.balance_start - statement.button_post() + self.assertEqual(in_invoice.journal_id, self.journal) + invoice_out_obj.browse(out_invoice.id).action_pay_invoice() inv_lines = self.invoice_in.line_ids.filtered( - lambda line: line.account_id.user_type_id.type in ("receivable", "payable") + lambda line: line.account_id.account_type + in ("asset_receivable", "liability_payable") ) inv_lines |= self.invoice_out.line_ids.filtered( - lambda line: line.account_id.user_type_id.type in ("receivable", "payable") + lambda line: line.account_id.account_type + in ("asset_receivable", "liability_payable") ) - statement.button_validate() - self.invoice_out.flush() - self.invoice_out.refresh() self.assertEqual(self.invoice_out.amount_residual, 0.0) - self.invoice_in.flush() - self.invoice_in.refresh() self.assertEqual(self.invoice_in.amount_residual, 0.0) diff --git a/account_cash_invoice/views/account_journal_dashboard_view.xml b/account_cash_invoice/views/account_journal_dashboard_view.xml new file mode 100644 index 000000000000..e0b870077e6d --- /dev/null +++ b/account_cash_invoice/views/account_journal_dashboard_view.xml @@ -0,0 +1,24 @@ + + + + account.journal.dashboard.kanban + account.journal + + + + + + + + + diff --git a/account_cash_invoice/wizard/__init__.py b/account_cash_invoice/wizard/__init__.py index 953231dad1fd..178f63b75fae 100644 --- a/account_cash_invoice/wizard/__init__.py +++ b/account_cash_invoice/wizard/__init__.py @@ -1,4 +1,3 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -from . import cash_invoice_in -from . import cash_invoice_out +from . import cash_pay_invoice diff --git a/account_cash_invoice/wizard/cash_invoice_in.py b/account_cash_invoice/wizard/cash_invoice_in.py deleted file mode 100644 index 7997ef78b785..000000000000 --- a/account_cash_invoice/wizard/cash_invoice_in.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright (C) 2017-2021 Creu Blanca -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). - -from odoo import api, fields, models - - -class CashInvoiceIn(models.TransientModel): - _name = "cash.invoice.in" - _inherit = "cash.box.out" - _description = "Cash invoice in" - - def _default_value(self, default_function): - active_model = self.env.context.get("active_model", False) - if active_model: - active_ids = self.env.context.get("active_ids", False) - return default_function(active_model, active_ids) - return None - - def _default_company(self): - return self._default_value(self.default_company) - - def _default_currency(self): - return self._default_value(self.default_currency) - - def _default_journals(self): - return self._default_value(self.default_journals) - - def _default_journal(self): - journals = self._default_journals() - if journals and len(journals.ids) > 0: - return self.env["account.journal"].browse(journals.ids[0]).ensure_one() - - def _default_journal_count(self): - return len(self._default_journals().ids) - - invoice_id = fields.Many2one( - comodel_name="account.move", - string="Invoice", - required=True, - ) - name = fields.Char(related="invoice_id.name", readonly=True) - company_id = fields.Many2one( - comodel_name="res.company", - default=lambda self: self._default_company(), - required=True, - readonly=True, - ) - currency_id = fields.Many2one( - comodel_name="res.currency", - default=lambda self: self._default_currency(), - required=True, - readonly=True, - ) - journal_ids = fields.Many2many( - comodel_name="account.journal", - default=lambda self: self._default_journals(), - required=True, - readonly=True, - string="Journals", - ) - journal_id = fields.Many2one( - comodel_name="account.journal", - required=True, - default=lambda self: self._default_journal(), - string="Journal", - ) - journal_count = fields.Integer( - default=lambda self: self._default_journal_count(), - readonly=True, - ) - - def default_company(self, active_model, active_ids): - return fields.first(self.env[active_model].browse(active_ids)).company_id - - def default_currency(self, active_model, active_ids): - return self.default_company(active_model, active_ids).currency_id - - def default_journals(self, active_model, active_ids): - return fields.first(self.env[active_model].browse(active_ids)).journal_id - - @api.onchange("journal_ids") - def compute_journal_count(self): - self.journal_count = len(self.journal_ids) - - @api.onchange("invoice_id") - def _onchange_invoice(self): - if self.invoice_id: - self.amount = self.invoice_id.amount_residual_signed - - def _calculate_values_for_statement_line(self, record): - res = super()._calculate_values_for_statement_line(record) - res.update( - { - "invoice_id": self.invoice_id.id, - "ref": self.invoice_id.name, - "partner_id": self.invoice_id.partner_id.id, - "counterpart_account_id": self.invoice_id.line_ids.filtered( - lambda l: l.account_internal_type in ("receivable", "payable") - ).account_id.id, - } - ) - return res diff --git a/account_cash_invoice/wizard/cash_invoice_out.py b/account_cash_invoice/wizard/cash_invoice_out.py deleted file mode 100644 index b8320826421d..000000000000 --- a/account_cash_invoice/wizard/cash_invoice_out.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright (C) 2017-2021 Creu Blanca -# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). - -from odoo import api, fields, models - - -class CashInvoiceOut(models.TransientModel): - _name = "cash.invoice.out" - _inherit = "cash.box.out" - _description = "Cash invoice out" - - def _default_value(self, default_function): - active_model = self.env.context.get("active_model", False) - if active_model: - active_ids = self.env.context.get("active_ids", False) - return default_function(active_model, active_ids) - return None - - def _default_company(self): - return self._default_value(self.default_company) - - def _default_currency(self): - return self._default_value(self.default_currency) - - def _default_journals(self): - return self._default_value(self.default_journals) - - def _default_journal(self): - journals = self._default_journals() - if journals and len(journals) > 0: - return fields.first(journals).ensure_one() - - def _default_journal_count(self): - return len(self._default_journals()) - - invoice_id = fields.Many2one( - comodel_name="account.move", - string="Invoice", - required=True, - domain=[("payment_state", "in", ["not_paid", "partial"])], - ) - name = fields.Char( - related="invoice_id.name", - ) - company_id = fields.Many2one( - comodel_name="res.company", - default=lambda self: self._default_company(), - required=True, - readonly=True, - ) - currency_id = fields.Many2one( - comodel_name="res.currency", - default=lambda self: self._default_currency(), - required=True, - readonly=True, - ) - journal_ids = fields.Many2many( - comodel_name="account.journal", - default=lambda self: self._default_journals(), - required=True, - readonly=True, - string="Journals", - ) - journal_id = fields.Many2one( - comodel_name="account.journal", - required=True, - default=lambda self: self._default_journal(), - string="Journal", - ) - journal_count = fields.Integer( - default=lambda self: self._default_journal_count(), readonly=True - ) - - def default_company(self, active_model, active_ids): - return fields.first(self.env[active_model].browse(active_ids)).company_id - - def default_currency(self, active_model, active_ids): - return self.default_company(active_model, active_ids).currency_id - - def default_journals(self, active_model, active_ids): - return fields.first(self.env[active_model].browse(active_ids)).journal_id - - @api.onchange("journal_ids") - def compute_journal_count(self): - self.journal_count = len(self.journal_ids) - - @api.onchange("journal_id") - def _onchange_journal(self): - self.currency_id = ( - self.journal_id.currency_id or self.journal_id.company_id.currency_id - ) - - @api.onchange("invoice_id") - def _onchange_invoice(self): - if self.invoice_id: - self.amount = self.invoice_id.amount_residual_signed - - def _calculate_values_for_statement_line(self, record): - res = super()._calculate_values_for_statement_line(record) - res.update( - { - "invoice_id": self.invoice_id.id, - "ref": self.invoice_id.name, - "partner_id": self.invoice_id.partner_id.id, - "counterpart_account_id": self.invoice_id.line_ids.filtered( - lambda l: l.account_internal_type in ("receivable", "payable") - ).account_id.id, - } - ) - return res diff --git a/account_cash_invoice/wizard/cash_invoice_out.xml b/account_cash_invoice/wizard/cash_invoice_out.xml deleted file mode 100644 index 2309eb865ba4..000000000000 --- a/account_cash_invoice/wizard/cash_invoice_out.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - cash_invoice_out_form - cash.invoice.out - -
    - - - - - - - -
    -
    -
    -
    -
    - - - Collect Payment from Invoice - cash.invoice.out - form - new - - form,list - -
    diff --git a/account_cash_invoice/wizard/cash_pay_invoice.py b/account_cash_invoice/wizard/cash_pay_invoice.py new file mode 100644 index 000000000000..ecc5cf3ba653 --- /dev/null +++ b/account_cash_invoice/wizard/cash_pay_invoice.py @@ -0,0 +1,108 @@ +# Copyright (C) 2017-2021 Creu Blanca +# Copyright (C) 2024 Tecnativa +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class CashPayInvoice(models.TransientModel): + _name = "cash.pay.invoice" + _description = "Cash Pay invoice from bank statement" + + def _default_company(self): + active_ids = self.env.context.get("active_ids") + journal = self.env["account.journal"].browse(active_ids) + return journal.company_id + + def _default_currency(self): + active_ids = self.env.context.get("active_ids") + journal = self.env["account.journal"].browse(active_ids) + return journal.currency_id or journal.company_id.currency_id + + invoice_id = fields.Many2one( + comodel_name="account.move", + string="Invoice", + required=True, + ) + name = fields.Char(related="invoice_id.name", readonly=True) + company_id = fields.Many2one( + comodel_name="res.company", + default=lambda self: self._default_company(), + required=True, + readonly=True, + ) + currency_id = fields.Many2one( + comodel_name="res.currency", + default=lambda self: self._default_currency(), + required=True, + readonly=True, + ) + journal_id = fields.Many2one( + comodel_name="account.journal", + required=True, + readonly=True, + default=lambda self: self.env.context.get("active_ids")[0], + string="Journal", + ) + amount = fields.Monetary() + invoice_type = fields.Selection( + [ + ("customer", "Customer"), + ("vendor", "Vendor"), + ], + ) + invoice_domain = fields.Binary(compute="_compute_invoice_domain") + + @api.depends("company_id", "currency_id", "invoice_type") + def _compute_invoice_domain(self): + for wizard in self: + invoice_domain = [ + ("company_id", "=", wizard.company_id.id), + ("currency_id", "=", wizard.currency_id.id), + ("state", "=", "posted"), + ("payment_state", "!=", "paid"), + ] + if wizard.invoice_type: + move_type = ( + ["out_invoice", "in_refund"] + if wizard.invoice_type == "customer" + else ["in_invoice", "out_refund"] + ) + invoice_domain.append(("move_type", "in", move_type)) + else: + # to avoid select invoice if invoice_type is not set + invoice_domain.append(("move_type", "in", [])) + wizard.invoice_domain = invoice_domain + + @api.onchange("invoice_type") + def _onchange_invoice_type(self): + self.invoice_id = False + + @api.onchange("invoice_id") + def _onchange_invoice(self): + if self.invoice_id: + self.amount = self.invoice_id.amount_residual_signed + + def action_pay_invoice(self): + BankStatementLine = self.env["account.bank.statement.line"] + statement_line_vals = self._prepare_values_for_statement_line(self) + BankStatementLine.create(statement_line_vals) + return {"type": "ir.actions.act_window_close"} + + def _prepare_values_for_statement_line(self, record): + counterpart_move_line = self.invoice_id.line_ids.filtered( + lambda l: l.account_id.account_type + in ("asset_receivable", "liability_payable") + and not l.reconciled + ) + statement_line_vals = { + "date": fields.Date.context_today(self), + "journal_id": self.journal_id.id, + "amount": self.amount, + "payment_ref": self.name, + "invoice_id": self.invoice_id.id, + "ref": self.invoice_id.name, + "partner_id": self.invoice_id.partner_id.id, + "counterpart_account_id": counterpart_move_line.account_id.id, + } + return statement_line_vals diff --git a/account_cash_invoice/wizard/cash_invoice_in.xml b/account_cash_invoice/wizard/cash_pay_invoice.xml similarity index 59% rename from account_cash_invoice/wizard/cash_invoice_in.xml rename to account_cash_invoice/wizard/cash_pay_invoice.xml index 8ead2cd03e2b..1c8e9c740a4c 100644 --- a/account_cash_invoice/wizard/cash_invoice_in.xml +++ b/account_cash_invoice/wizard/cash_pay_invoice.xml @@ -1,28 +1,24 @@ - - cash_invoice_in_form - cash.invoice.in + + cash.pay.invoice.form + cash.pay.invoice
    - - + + +