From 80907169f4d0ea82f40506675c3c97c80d848cac Mon Sep 17 00:00:00 2001 From: Christopher Ormaza Date: Thu, 7 Apr 2022 15:17:19 -0500 Subject: [PATCH] [14.0][ADD] account_move_transfer_partner --- account_move_transfer_partner/README.rst | 91 ++++ account_move_transfer_partner/__init__.py | 4 + account_move_transfer_partner/__manifest__.py | 20 + .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 1 + .../readme/USAGE.rst | 1 + .../security/ir.model.access.csv | 2 + .../static/description/index.html | 432 ++++++++++++++++++ .../tests/__init__.py | 1 + .../test_account_move_transfer_partner.py | 334 ++++++++++++++ .../wizard/__init__.py | 1 + .../wizard_account_move_transfer_partner.py | 188 ++++++++ ...ard_account_move_transfer_partner_view.xml | 98 ++++ .../odoo/addons/account_move_transfer_partner | 1 + setup/account_move_transfer_partner/setup.py | 6 + 15 files changed, 1181 insertions(+) create mode 100644 account_move_transfer_partner/README.rst create mode 100644 account_move_transfer_partner/__init__.py create mode 100644 account_move_transfer_partner/__manifest__.py create mode 100644 account_move_transfer_partner/readme/CONTRIBUTORS.rst create mode 100644 account_move_transfer_partner/readme/DESCRIPTION.rst create mode 100644 account_move_transfer_partner/readme/USAGE.rst create mode 100644 account_move_transfer_partner/security/ir.model.access.csv create mode 100644 account_move_transfer_partner/static/description/index.html create mode 100644 account_move_transfer_partner/tests/__init__.py create mode 100644 account_move_transfer_partner/tests/test_account_move_transfer_partner.py create mode 100644 account_move_transfer_partner/wizard/__init__.py create mode 100644 account_move_transfer_partner/wizard/wizard_account_move_transfer_partner.py create mode 100644 account_move_transfer_partner/wizard/wizard_account_move_transfer_partner_view.xml create mode 120000 setup/account_move_transfer_partner/odoo/addons/account_move_transfer_partner create mode 100644 setup/account_move_transfer_partner/setup.py diff --git a/account_move_transfer_partner/README.rst b/account_move_transfer_partner/README.rst new file mode 100644 index 000000000..72357ad90 --- /dev/null +++ b/account_move_transfer_partner/README.rst @@ -0,0 +1,91 @@ +============================= +Account Move Transfer Partner +============================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |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--financial--tools-lightgray.png?logo=github + :target: https://github.com/OCA/account-financial-tools/tree/14.0/account_move_transfer_partner + :alt: OCA/account-financial-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-financial-tools-14-0/account-financial-tools-14-0-account_move_transfer_partner + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/92/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Add wizard to make transfer amount due from invoice / refund documents to specific partner + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +This wizard just can be used on invoice / refund documents + +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 +~~~~~~~ + +* ForgeFlow S.L. + +Contributors +~~~~~~~~~~~~ + +* Christopher Ormaza + +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. + +.. |maintainer-ChrisOForgeFlow| image:: https://github.com/ChrisOForgeFlow.png?size=40px + :target: https://github.com/ChrisOForgeFlow + :alt: ChrisOForgeFlow + +Current `maintainer `__: + +|maintainer-ChrisOForgeFlow| + +This module is part of the `OCA/account-financial-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_move_transfer_partner/__init__.py b/account_move_transfer_partner/__init__.py new file mode 100644 index 000000000..5343bab38 --- /dev/null +++ b/account_move_transfer_partner/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2022 ForgeFlow S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import wizard diff --git a/account_move_transfer_partner/__manifest__.py b/account_move_transfer_partner/__manifest__.py new file mode 100644 index 000000000..a2ee715de --- /dev/null +++ b/account_move_transfer_partner/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2022 ForgeFlow S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "Account Move Transfer Partner", + "summary": "Automation to translate amount due from many partners to one partner", + "version": "14.0.1.0.0", + "author": "ForgeFlow S.L., " "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-financial-tools", + "category": "Generic", + "depends": ["account"], + "license": "AGPL-3", + "data": [ + "security/ir.model.access.csv", + "wizard/wizard_account_move_transfer_partner_view.xml", + ], + "installable": True, + "development_status": "Alpha", + "maintainers": ["ChrisOForgeFlow"], +} diff --git a/account_move_transfer_partner/readme/CONTRIBUTORS.rst b/account_move_transfer_partner/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..b647a292e --- /dev/null +++ b/account_move_transfer_partner/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Christopher Ormaza diff --git a/account_move_transfer_partner/readme/DESCRIPTION.rst b/account_move_transfer_partner/readme/DESCRIPTION.rst new file mode 100644 index 000000000..328a29c41 --- /dev/null +++ b/account_move_transfer_partner/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Add wizard to make transfer amount due from invoice / refund documents to specific partner diff --git a/account_move_transfer_partner/readme/USAGE.rst b/account_move_transfer_partner/readme/USAGE.rst new file mode 100644 index 000000000..f8cb706f9 --- /dev/null +++ b/account_move_transfer_partner/readme/USAGE.rst @@ -0,0 +1 @@ +This wizard just can be used on invoice / refund documents diff --git a/account_move_transfer_partner/security/ir.model.access.csv b/account_move_transfer_partner/security/ir.model.access.csv new file mode 100644 index 000000000..8591f32c0 --- /dev/null +++ b/account_move_transfer_partner/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_wizard_account_move_transfer_partner_all,access_wizard_account_move_transfer_partner_all,model_wizard_account_move_transfer_partner,,1,1,1,1 diff --git a/account_move_transfer_partner/static/description/index.html b/account_move_transfer_partner/static/description/index.html new file mode 100644 index 000000000..8ea815edb --- /dev/null +++ b/account_move_transfer_partner/static/description/index.html @@ -0,0 +1,432 @@ + + + + + + +Account Move Transfer Partner + + + +
+

Account Move Transfer Partner

+ + +

Alpha License: AGPL-3 OCA/account-financial-tools Translate me on Weblate Try me on Runbot

+

Add wizard to make transfer amount due from invoice / refund documents to specific partner

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Usage

+

This wizard just can be used on invoice / refund documents

+
+
+

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

+
    +
  • ForgeFlow S.L.
  • +
+
+
+

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.

+

Current maintainer:

+

ChrisOForgeFlow

+

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

+

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

+
+
+
+ + diff --git a/account_move_transfer_partner/tests/__init__.py b/account_move_transfer_partner/tests/__init__.py new file mode 100644 index 000000000..a895df890 --- /dev/null +++ b/account_move_transfer_partner/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_move_transfer_partner diff --git a/account_move_transfer_partner/tests/test_account_move_transfer_partner.py b/account_move_transfer_partner/tests/test_account_move_transfer_partner.py new file mode 100644 index 000000000..772bb13f3 --- /dev/null +++ b/account_move_transfer_partner/tests/test_account_move_transfer_partner.py @@ -0,0 +1,334 @@ +# Copyright 2022 ForgeFlow S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import _, fields +from odoo.exceptions import ValidationError +from odoo.tests.common import Form, TransactionCase + +CURRENCY_RATE = 0.5 + + +class TestAccountMoveTransferPartner(TransactionCase): + def setUp(self): + super().setUp() + self.company = self.env.ref("base.main_company") + self.partner_1 = self.env.ref("base.res_partner_1") + self.partner_2 = self.env.ref("base.res_partner_2") + self.partner_3 = self.env.ref("base.res_partner_3") + self.today = fields.Date.today() + + self.AccountJournal = self.env["account.journal"] + self.wizard_model = self.env["wizard.account.move.transfer.partner"] + self.sale_journal = self.AccountJournal.create( + { + "name": "Sale journal", + "code": "SALE", + "type": "sale", + } + ) + self.purchase_journal = self.AccountJournal.create( + { + "name": "Purchase journal", + "code": "PURCHASE", + "type": "purchase", + } + ) + self.general_journal = self.AccountJournal.create( + { + "name": "General journal", + "code": "GENERAL", + "type": "general", + } + ) + + self.ProductProduct = self.env["product.product"] + self.product = self.ProductProduct.create( + {"name": "Product", "price": 100.0, "standard_price": 100.0} + ) + charts = self.env["account.chart.template"].search([]) + if charts: + self.chart = charts[0] + else: + raise ValidationError(_("No Chart of Account Template has been defined !")) + self.AccountMove = self.env["account.move"] + with Form( + self.AccountMove.with_context(default_move_type="out_invoice") + ) as invoice_form: + invoice_form.invoice_date = self.today + invoice_form.partner_id = self.partner_2 + invoice_form.journal_id = self.sale_journal + with invoice_form.invoice_line_ids.new() as line_form: + line_form.product_id = self.product + self.invoice_1 = invoice_form.save() + self.invoice_2 = self.invoice_1.copy() + self.invoice_3 = self.invoice_1.copy() + invoice_form = Form(self.invoice_3) + invoice_form.partner_id = self.partner_2 + self.invoice_3 = invoice_form.save() + self.invoice_1.action_post() + self.invoice_2.action_post() + self.invoice_3.action_post() + + with Form( + self.AccountMove.with_context(default_move_type="in_invoice") + ) as invoice_form: + invoice_form.invoice_date = self.today + invoice_form.partner_id = self.partner_1 + invoice_form.journal_id = self.purchase_journal + with invoice_form.invoice_line_ids.new() as line_form: + line_form.product_id = self.product + self.in_invoice = invoice_form.save() + self.in_invoice.action_post() + + with Form( + self.AccountMove.with_context(default_move_type="out_refund") + ) as invoice_form: + invoice_form.invoice_date = self.today + invoice_form.partner_id = self.partner_1 + invoice_form.journal_id = self.sale_journal + with invoice_form.invoice_line_ids.new() as line_form: + line_form.product_id = self.product + self.out_refund = invoice_form.save() + self.out_refund.action_post() + with Form( + self.AccountMove.with_context(default_move_type="in_refund") + ) as invoice_form: + invoice_form.invoice_date = self.today + invoice_form.partner_id = self.partner_1 + invoice_form.journal_id = self.purchase_journal + with invoice_form.invoice_line_ids.new() as line_form: + line_form.product_id = self.product + self.in_refund = invoice_form.save() + self.in_refund.action_post() + + self.general_move = self.AccountMove.create( + { + "journal_id": self.general_journal.id, + "ref": "sample move", + "line_ids": [ + ( + 0, + 0, + { + "debit": 100.0, + "credit": 0, + "account_id": self.env["account.account"] + .search([("user_type_id.type", "=", "other")], limit=1) + .id, + }, + ), + ( + 0, + 0, + { + "debit": 0.0, + "credit": 100.0, + "account_id": self.env["account.account"] + .search([("user_type_id.type", "=", "other")], limit=1) + .id, + }, + ), + ], + } + ) + self.general_move.action_post() + self.payment_term = self.env["account.payment.term"].create( + { + "name": "Pay in 2 installments", + "line_ids": [ + # Pay 50% immediately + ( + 0, + 0, + { + "value": "percent", + "value_amount": 50, + }, + ), + # Pay the rest after 14 days + ( + 0, + 0, + { + "value": "balance", + "days": 14, + }, + ), + ], + } + ) + self.currency_2 = self.env["res.currency"].create( + { + "name": "test", + "symbol": "TEST", + "rate_ids": [ + ( + 0, + 0, + { + "name": fields.Date.today(), + "rate": CURRENCY_RATE, + }, + ) + ], + } + ) + self.AccountMoveReversal = self.env["account.move.reversal"] + + def test_01_account_move_transfer_partner(self): + self.assertEqual(self.invoice_1.payment_state, "not_paid") + self.assertEqual(self.invoice_2.payment_state, "not_paid") + self.assertEqual(self.invoice_3.payment_state, "not_paid") + all_invoices = self.invoice_1 + self.invoice_2 + self.invoice_3 + total_residual = sum(i.amount_residual for i in all_invoices) + wizard_form = Form( + self.wizard_model.with_context({"active_ids": self.invoice_1.ids}) + ) + self.assertTrue(wizard_form.allow_edit_amount_to_transfer) + wizard_form.amount_to_transfer = self.invoice_1.amount_residual + 1 + wizard_form.destination_partner_id = self.partner_3 + wizard = wizard_form.save() + with self.assertRaises(ValidationError): + wizard.action_create_move() + wizard.write( + { + "amount_to_transfer": 0, + } + ) + with self.assertRaises(ValidationError): + wizard.action_create_move() + wizard_form = Form( + self.wizard_model.with_context({"active_ids": all_invoices.ids}) + ) + with self.assertRaises(AssertionError): + wizard_form.amount_to_transfer = total_residual + 1 + wizard_form.destination_partner_id = self.partner_3 + self.assertFalse(wizard_form.allow_edit_amount_to_transfer) + wizard = wizard_form.save() + action = wizard.action_create_move() + self.assertEqual(self.invoice_1.payment_state, "paid") + self.assertEqual(self.invoice_2.payment_state, "paid") + self.assertEqual(self.invoice_3.payment_state, "paid") + new_moves = action.get("domain", []) and self.AccountMove.browse( + action.get("domain", [])[0][2] + ) + unreconciled_lines = new_moves.mapped("line_ids").filtered( + lambda x: not x.reconciled + ) + self.assertEqual( + unreconciled_lines.mapped("partner_id").ids, self.partner_3.ids + ) + + def test_02_account_move_transfer_partner(self): + wizard_form = Form( + self.wizard_model.with_context({"active_ids": self.in_invoice.ids}) + ) + self.assertTrue(wizard_form.allow_edit_amount_to_transfer) + current_residual_amount = self.invoice_1.amount_residual + wizard_form.amount_to_transfer = current_residual_amount - 1 + wizard_form.destination_partner_id = self.partner_3 + wizard = wizard_form.save() + action = wizard.action_create_move() + self.assertEqual(self.in_invoice.amount_residual, 1.0) + new_moves = action.get("domain", []) and self.AccountMove.browse( + action.get("domain", [])[0][2] + ) + partner_1_aml = new_moves.mapped("line_ids").filtered( + lambda x: x.partner_id.id == self.partner_1.id + ) + self.assertEqual(abs(partner_1_aml.amount_residual), 0.0) + partner_3_aml = new_moves.mapped("line_ids").filtered( + lambda x: x.partner_id.id == self.partner_3.id + ) + self.assertEqual( + abs(partner_3_aml.amount_residual), current_residual_amount - 1 + ) + + def test_03_account_move_transfer_partner(self): + wizard_form = Form( + self.wizard_model.with_context({"active_ids": self.out_refund.ids}) + ) + self.assertTrue(wizard_form.allow_edit_amount_to_transfer) + wizard_form.destination_partner_id = self.partner_3 + wizard = wizard_form.save() + wizard.action_create_move() + self.assertEqual(self.out_refund.amount_residual, 0.0) + + def test_04_account_move_transfer_partner(self): + wizard_form = Form( + self.wizard_model.with_context({"active_ids": self.in_refund.ids}) + ) + self.assertTrue(wizard_form.allow_edit_amount_to_transfer) + wizard_form.destination_partner_id = self.partner_3 + wizard = wizard_form.save() + wizard.action_create_move() + self.assertEqual(self.in_refund.amount_residual, 0.0) + + def test_05_account_move_transfer_partner(self): + wizard_form = Form( + self.wizard_model.with_context({"active_ids": self.general_move.ids}) + ) + self.assertTrue(wizard_form.allow_edit_amount_to_transfer) + self.assertTrue(wizard_form.no_invoice_documents) + wizard_form.destination_partner_id = self.partner_3 + wizard = wizard_form.save() + with self.assertRaises(ValidationError): + wizard.action_create_move() + + def test_06_account_move_transfer_partner(self): + with Form( + self.AccountMove.with_context(default_move_type="out_invoice") + ) as invoice_form: + invoice_form.invoice_date = self.today + invoice_form.partner_id = self.partner_2 + invoice_form.journal_id = self.sale_journal + invoice_form.currency_id = self.currency_2 + with invoice_form.invoice_line_ids.new() as line_form: + line_form.product_id = self.product + self.invoice_with_payment_term = invoice_form.save() + self.invoice_with_payment_term.action_post() + wizard_form = Form( + self.wizard_model.with_context( + {"active_ids": self.invoice_with_payment_term.ids} + ) + ) + self.assertTrue(wizard_form.allow_edit_amount_to_transfer) + wizard_form.destination_partner_id = self.partner_3 + self.assertEqual( + wizard_form.total_amount_due, + self.invoice_with_payment_term.currency_id.compute( + self.invoice_with_payment_term.amount_residual, + self.env.company.currency_id, + ), + ) + wizard_form.currency_id = self.currency_2 + self.assertEqual( + wizard_form.total_amount_due, + self.invoice_with_payment_term.amount_residual, + ) + + def test_07_account_move_transfer_partner(self): + with Form( + self.AccountMove.with_context(default_move_type="out_invoice") + ) as invoice_form: + invoice_form.invoice_date = self.today + invoice_form.partner_id = self.partner_2 + invoice_form.journal_id = self.sale_journal + invoice_form.invoice_payment_term_id = self.payment_term + with invoice_form.invoice_line_ids.new() as line_form: + line_form.product_id = self.product + self.invoice_with_payment_term = invoice_form.save() + self.invoice_with_payment_term.action_post() + wizard_form = Form( + self.wizard_model.with_context( + {"active_ids": self.invoice_with_payment_term.ids} + ) + ) + self.assertTrue(wizard_form.allow_edit_amount_to_transfer) + wizard_form.destination_partner_id = self.partner_3 + wizard = wizard_form.save() + action = wizard.action_create_move() + self.assertEqual(self.invoice_with_payment_term.amount_residual, 0.0) + new_moves = action.get("domain", []) and self.AccountMove.browse( + action.get("domain", [])[0][2] + ) + self.assertEqual(len(new_moves.mapped("line_ids")), 4) diff --git a/account_move_transfer_partner/wizard/__init__.py b/account_move_transfer_partner/wizard/__init__.py new file mode 100644 index 000000000..4d833f77d --- /dev/null +++ b/account_move_transfer_partner/wizard/__init__.py @@ -0,0 +1 @@ +from . import wizard_account_move_transfer_partner diff --git a/account_move_transfer_partner/wizard/wizard_account_move_transfer_partner.py b/account_move_transfer_partner/wizard/wizard_account_move_transfer_partner.py new file mode 100644 index 000000000..4e1ba189c --- /dev/null +++ b/account_move_transfer_partner/wizard/wizard_account_move_transfer_partner.py @@ -0,0 +1,188 @@ +# Copyright 2022 ForgeFlow S.L. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError +from odoo.tools import float_compare + + +class WizardAccountMoveTransferPartner(models.TransientModel): + + _name = "wizard.account.move.transfer.partner" + _description = "Wizard to transfer due amount to another partner" + + origin_partner_ids = fields.Many2many( + comodel_name="res.partner", string="Origin Partner", readonly=True + ) + currency_id = fields.Many2one( + comodel_name="res.currency", + string="Currency", + default=lambda self: self.env.company.currency_id.id, + ) + move_ids = fields.Many2many( + comodel_name="account.move", string="Moves Selected", readonly=True + ) + destination_partner_id = fields.Many2one( + comodel_name="res.partner", string="Destination partner", required=True + ) + journal_id = fields.Many2one( + comodel_name="account.journal", + string="Journal", + required=True, + domain=[("type", "=", "general")], + default=lambda self: self.env["account.journal"] + .search([("type", "=", "general")], limit=1) + .id, + ) + account_date = fields.Date( + string="Account date", required=True, default=fields.Date.today() + ) + total_amount_due = fields.Monetary( + string="Total Amount Due", + readonly=True, + currency_field="currency_id", + ) + allow_edit_amount_to_transfer = fields.Boolean( + string="Allow edit amount to transfer?", + readonly=True, + ) + no_invoice_documents = fields.Boolean(string="No invoice documents?", readonly=True) + amount_to_transfer = fields.Monetary( + string="Amount to transfer", + required=True, + currency_field="currency_id", + ) + + @api.onchange("currency_id", "account_date") + def _onchange_currency_id(self): + if self.currency_id: + total_amount_due = 0 + for move in self.move_ids: + if move._origin: + invoice = move._origin + else: + invoice = move + total_amount_due += invoice.currency_id.with_context( + date=self.account_date or fields.Date.today() + ).compute(invoice.amount_residual, self.currency_id) + self.total_amount_due = total_amount_due + self.amount_to_transfer = self.total_amount_due + + @api.model + def default_get(self, fields_list): + values = super(WizardAccountMoveTransferPartner, self).default_get(fields_list) + moves = ( + self.env["account.move"] + .browse(self.env.context.get("active_ids")) + .filtered(lambda x: x.state == "posted") + ) + values["origin_partner_ids"] = moves.mapped("partner_id").ids + values["move_ids"] = moves.filtered(lambda x: x.is_invoice()).ids + values["no_invoice_documents"] = ( + len(moves.filtered(lambda x: not x.is_invoice())) >= 1 + ) + due_amount = abs(sum(moves.mapped("amount_residual"))) + values["total_amount_due"] = due_amount + values["amount_to_transfer"] = due_amount + values["allow_edit_amount_to_transfer"] = len(moves) == 1 + return values + + def action_create_move(self): + am_model = self.env["account.move"] + aml_model = self.env["account.move.line"].with_context( + check_move_validity=False + ) + if self.amount_to_transfer <= 0: + raise ValidationError(_("Amount to transfer should be bigger than zero")) + if ( + float_compare( + self.amount_to_transfer, + self.total_amount_due, + precision_rounding=self.env.company.currency_id.rounding or 0.01, + ) + == 1 + ): + raise ValidationError( + _( + "Amount to transfer %s should be equal or lower than total amount due %s" + ) + % (self.amount_to_transfer, self.total_amount_due) + ) + new_moves = am_model.browse() + for move in self.move_ids: + new_move = am_model.create( + { + "date": self.account_date, + "journal_id": self.journal_id.id, + "ref": _("Transfer amount due from %s") % (move.display_name), + "state": "draft", + "move_type": "entry", + } + ) + reconcilable_account = move.line_ids.mapped("account_id").filtered( + lambda x: x.user_type_id.type in ("receivable", "payable") + ) + lines = move.line_ids.filtered( + lambda line: line.account_id == reconcilable_account + and not line.reconciled + ) + common_data = { + "account_id": reconcilable_account.id, + "move_id": new_move.id, + "currency_id": self.currency_id.id, + "ref": _("Transfer due amount from %s") % move.display_name, + } + amount_to_apply = ( + self.allow_edit_amount_to_transfer + and self.amount_to_transfer + or move.amount_residual + ) + credit_aml = aml_model.browse() + debit_aml = aml_model.browse() + for line in lines: + amount = min(amount_to_apply, abs(line.amount_residual)) + amount_to_apply -= amount + amount_currency = ( + move.currency_id.id != self.currency_id.id and amount or 0.0 + ) + amount = self.currency_id.with_context(date=self.account_date).compute( + amount, move.currency_id + ) + credit_line_data = common_data.copy() + debit_line_data = common_data.copy() + credit_line_data.update( + { + "partner_id": move.is_inbound() + and move.partner_id.id + or move.is_outbound() + and self.destination_partner_id.id, + "credit": amount, + "debit": 0.0, + "amount_currency": -amount_currency, + "date_maturity": line.date_maturity, + } + ) + debit_line_data.update( + { + "partner_id": move.is_inbound() + and self.destination_partner_id.id + or move.is_outbound() + and move.partner_id.id, + "credit": 0.0, + "debit": amount, + "amount_currency": amount_currency, + "date_maturity": line.date_maturity, + } + ) + credit_aml += aml_model.create(credit_line_data) + debit_aml += aml_model.create(debit_line_data) + new_move.action_post() + if move.is_inbound(): + for aml in credit_aml: + move.js_assign_outstanding_line(aml.id) + if move.is_outbound(): + for aml in debit_aml: + move.js_assign_outstanding_line(aml.id) + new_moves |= new_move + action = self.env.ref("account.action_move_journal_line").read()[0] + action.update({"domain": [("id", "in", new_moves.ids)]}) + return action diff --git a/account_move_transfer_partner/wizard/wizard_account_move_transfer_partner_view.xml b/account_move_transfer_partner/wizard/wizard_account_move_transfer_partner_view.xml new file mode 100644 index 000000000..a9462e891 --- /dev/null +++ b/account_move_transfer_partner/wizard/wizard_account_move_transfer_partner_view.xml @@ -0,0 +1,98 @@ + + + + + + wizard_account_move_transfer_partner_view_form + wizard.account.move.transfer.partner + +
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + + Transfer amount due to another partner + ir.actions.act_window + wizard.account.move.transfer.partner + form + new + + + +
+
diff --git a/setup/account_move_transfer_partner/odoo/addons/account_move_transfer_partner b/setup/account_move_transfer_partner/odoo/addons/account_move_transfer_partner new file mode 120000 index 000000000..ae059f9e4 --- /dev/null +++ b/setup/account_move_transfer_partner/odoo/addons/account_move_transfer_partner @@ -0,0 +1 @@ +../../../../account_move_transfer_partner \ No newline at end of file diff --git a/setup/account_move_transfer_partner/setup.py b/setup/account_move_transfer_partner/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/account_move_transfer_partner/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)