diff --git a/account_cash_discount_write_off/README.rst b/account_cash_discount_write_off/README.rst index 45099ec99232..2ccbafa6d0b1 100644 --- a/account_cash_discount_write_off/README.rst +++ b/account_cash_discount_write_off/README.rst @@ -7,7 +7,7 @@ Account Cash Discount Write Off !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:3ae5bbdcc58337eb64bdf7024a5e2ab36e9e6f14bea534d1ee9fb55cc48dd2bd + !! source digest: sha256:61f70659fb0fd989c1c0715b2f373de6e43663c174eb0359143cea741e3c862c !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -17,13 +17,13 @@ Account Cash Discount Write Off :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--payment-lightgray.png?logo=github - :target: https://github.com/OCA/account-payment/tree/14.0/account_cash_discount_write_off + :target: https://github.com/OCA/account-payment/tree/16.0/account_cash_discount_write_off :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_discount_write_off + :target: https://translation.odoo-community.org/projects/account-payment-16-0/account-payment-16-0-account_cash_discount_write_off :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| @@ -57,7 +57,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. @@ -89,6 +89,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_discount_write_off/__manifest__.py b/account_cash_discount_write_off/__manifest__.py index b1ad5106bd76..1468b5a9e6ce 100644 --- a/account_cash_discount_write_off/__manifest__.py +++ b/account_cash_discount_write_off/__manifest__.py @@ -6,7 +6,7 @@ "summary": """ Create an automatic writeoff for payment with discount on the payment order confirmation""", - "version": "14.0.1.0.0", + "version": "16.0.1.0.0", "license": "AGPL-3", "author": "ACSONE SA/NV, Odoo Community Association (OCA)", "website": "https://github.com/OCA/account-payment", diff --git a/account_cash_discount_write_off/static/description/index.html b/account_cash_discount_write_off/static/description/index.html index ec845f9bb419..0a67f6b6792c 100644 --- a/account_cash_discount_write_off/static/description/index.html +++ b/account_cash_discount_write_off/static/description/index.html @@ -367,9 +367,9 @@

Account Cash Discount Write Off

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:3ae5bbdcc58337eb64bdf7024a5e2ab36e9e6f14bea534d1ee9fb55cc48dd2bd +!! source digest: sha256:61f70659fb0fd989c1c0715b2f373de6e43663c174eb0359143cea741e3c862c !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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

Create an automatic write-off for payment with discount on the payment order confirmation. If the cash discount amount is computed based on the total amount, the created write-off will also contains tax adjustments. This @@ -405,7 +405,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.

@@ -431,7 +431,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_discount_write_off/tests/test_account_cash_discount_write_off.py b/account_cash_discount_write_off/tests/test_account_cash_discount_write_off.py index 5df9d2f83b88..0641a387f9cc 100644 --- a/account_cash_discount_write_off/tests/test_account_cash_discount_write_off.py +++ b/account_cash_discount_write_off/tests/test_account_cash_discount_write_off.py @@ -1,6 +1,7 @@ # Copyright 2018 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import Command from odoo.exceptions import UserError from odoo.fields import Date from odoo.tests.common import Form @@ -11,14 +12,40 @@ class TestAccountCashDiscountWriteOff(TestAccountCashDiscountPaymentCommon): + def create_payment_order(self, invoice_date, invoice): + payment_order = self.PaymentOrder.create( + { + "payment_mode_id": self.payment_mode_out.id, + "payment_type": "outbound", + "journal_id": self.bank_ing_journal.id, + } + ) + payment_line_wizard = self.PaymentLineCreate.with_context( + active_model=payment_order._name, + active_id=payment_order.id, + ).create( + { + "cash_discount_date": invoice_date, + "date_type": "discount_due_date", + "target_move": "posted", + "journal_ids": [(6, 0, [invoice.journal_id.id])], + } + ) + self.assertEqual(payment_line_wizard.order_id, payment_order) + + payment_line_wizard.populate() + payment_line_wizard.create_payment_lines() + + return payment_order + @classmethod def setUpClass(cls): - super(TestAccountCashDiscountWriteOff, cls).setUpClass() + super().setUpClass() cls.cash_discount_writeoff_account = cls.Account.create( { "name": "Cash Discount Write-Off", - "code": "CD-W", - "user_type_id": cls.inc_account_type.id, + "code": "CDW", + "account_type": "income_other", } ) @@ -29,11 +56,31 @@ def setUpClass(cls): def test_cash_discount_with_write_off(self): payment_mode = self.payment_mode_out payment_mode.post_move = True - discount_due_date = Date.today() + invoice_date = Date.today() + + payment_term = self.env["account.payment.term"].create( + { + "name": "10% discount 5 days", + "line_ids": [ + Command.create( + { + "value": "balance", + "value_amount": 0.0, + "months": 0, + "end_month": False, + "discount_percentage": 10, + "discount_days": 5, + } + ) + ], + } + ) invoice = self.create_supplier_invoice( - discount_due_date, payment_mode, 1000, 10, [] + invoice_date, self.payment_mode_out, 1000, False, payment_term ) + invoice._onchange_discount_delay() + invoice.ref = "test ref" invoice.action_post() payment_order = self.PaymentOrder.create( @@ -49,9 +96,9 @@ def test_cash_discount_with_write_off(self): active_id=payment_order.id, ).create( { - "cash_discount_date": discount_due_date, + "cash_discount_date": invoice_date, "date_type": "discount_due_date", - "journal_ids": [(6, 0, [self.purchase_journal.id])], + "journal_ids": [(6, 0, [invoice.journal_id.id])], } ) @@ -123,11 +170,45 @@ def test_cash_discount_with_write_off_with_taxes(self): payment_mode = self.payment_mode_out payment_mode.post_move = True - discount_due_date = Date.today() + invoice_date = Date.today() + + payment_term = self.env["account.payment.term"].create( + { + "name": "10% discount 5 days", + "line_ids": [ + Command.create( + { + "value": "balance", + "value_amount": 0.0, + "months": 0, + "end_month": False, + "discount_percentage": 10, + "discount_days": 5, + } + ) + ], + } + ) invoice = self.create_supplier_invoice( - discount_due_date, payment_mode, 1000, 10, [self.tax_10_p, self.tax_15_p] + invoice_date, self.payment_mode_out, 1000, self.tax_10_p, payment_term ) + + # add one tax + inv_form = Form( + invoice.with_context( + default_move_type="in_invoice", + default_company_id=self.company.id, + default_payment_mode_id=payment_mode.id, + ) + ) + with inv_form.invoice_line_ids.edit(0) as line: + line.tax_ids.add(self.tax_15_p) + + invoice = inv_form.save() + + invoice._onchange_discount_delay() + invoice.ref = "test ref" invoice.action_post() payment_order = self.PaymentOrder.create( @@ -143,9 +224,9 @@ def test_cash_discount_with_write_off_with_taxes(self): active_id=payment_order.id, ).create( { - "cash_discount_date": discount_due_date, + "cash_discount_date": invoice_date, "date_type": "discount_due_date", - "journal_ids": [(6, 0, [self.purchase_journal.id])], + "journal_ids": [(6, 0, [invoice.journal_id.id])], } ) @@ -194,18 +275,44 @@ def test_cash_discount_with_refund(self): payment_mode = self.payment_mode_out payment_mode.post_move = True - discount_due_date = Date.today() + invoice_date = Date.today() + + payment_term = self.env["account.payment.term"].create( + { + "name": "2% discount 5 days", + "line_ids": [ + Command.create( + { + "value": "balance", + "value_amount": 0.0, + "months": 0, + "end_month": False, + "discount_percentage": 2, + "discount_days": 5, + } + ) + ], + } + ) invoice = self.create_supplier_invoice( - discount_due_date, payment_mode, 100, 2, [self.tax_17_p] + invoice_date, self.payment_mode_out, 100, self.tax_17_p, payment_term ) + invoice._onchange_discount_delay() + invoice.ref = "test ref" invoice.action_post() self.assertAlmostEqual(invoice.amount_residual, 117) self.assertAlmostEqual(invoice.residual_with_discount, 114.66) move_reversal = self.AccountMoveReversal.with_context( active_model=invoice._name, active_ids=invoice.ids - ).create({"reason": "no reason", "refund_method": "refund"}) + ).create( + { + "reason": "no reason", + "refund_method": "refund", + "journal_id": invoice.journal_id.id, + } + ) reversal = move_reversal.reverse_moves() refund = self.env["account.move"].browse(reversal["res_id"]) @@ -215,7 +322,7 @@ def test_cash_discount_with_refund(self): refund_line.price_unit = 10 refund_form.save() - refund.write({"discount_due_date": discount_due_date, "discount_percent": 2}) + refund.write({"discount_due_date": invoice_date, "discount_percent": 2}) refund.action_post() credit_aml_id = self.AccountMoveLine.search( [("move_id", "=", refund.id), ("debit", ">", 0)], limit=1 @@ -239,9 +346,9 @@ def test_cash_discount_with_refund(self): active_id=payment_order.id, ).create( { - "cash_discount_date": discount_due_date, + "cash_discount_date": invoice_date, "date_type": "discount_due_date", - "journal_ids": [(6, 0, [self.purchase_journal.id])], + "journal_ids": [(6, 0, [invoice.journal_id.id])], } ) @@ -256,3 +363,565 @@ def test_cash_discount_with_refund(self): payment_order.generated2uploaded() self.assertEqual(invoice.payment_state, "paid") + + def test_invoice_with_discount_1(self): + """ + Discount: Tax included + Invoice: + Amount without Tax: 1500 + Tax: 20% (300) + Total on invoice: 1800 + Discount: 2% (36) + Total with discount: 1764 + """ + invoice_date = Date.today() + woff_account = self.cash_discount_writeoff_account + woff_journal = self.cash_discount_writeoff_journal + payment_mode = self.payment_mode_out + payment_mode.post_move = True + self.company.write( + { + "default_cash_discount_writeoff_account_id": woff_account.id, + "default_cash_discount_writeoff_journal_id": woff_journal.id, + "cash_discount_base_amount_type": "total", + } + ) + invoice = self.create_supplier_invoice( + invoice_date, + self.payment_mode_out, + 1500, + self.tax_20_p, + self.payment_term_2_p_discount_7d, + ) + invoice._onchange_discount_delay() + self.assertTrue(invoice.has_discount) + self.assertRecordValues( + invoice, + [ + { + "amount_untaxed": 1500.0, + "amount_tax": 300.0, + "amount_total": 1800.0, + "discount_amount": 36.0, + "discount_percent": 2.0, + "amount_total_with_discount": 1764.0, + } + ], + ) + invoice.ref = "test ref" + invoice.action_post() + + payment_order = self.create_payment_order(invoice_date, invoice) + + self.assertEqual(len(payment_order.payment_line_ids), 1) + payment_line = payment_order.payment_line_ids[0] + self.assertTrue(payment_line.pay_with_discount) + self.assertAlmostEqual(payment_line.amount_currency, 1764.0) + self.assertTrue(payment_line.pay_with_discount) + + payment_order.draft2open() + payment_order.open2generated() + payment_order.generated2uploaded() + + self.assertEqual(len(payment_order.move_ids), 1) + + self.assertEqual(invoice.payment_state, "paid") + + domain_reconlied_line = payment_order.move_ids.open_reconcile_view()["domain"] + reconciled_line_ids = self.env["account.move.line"].search( + domain_reconlied_line + ) + + self.assertRecordValues( + reconciled_line_ids.sorted(lambda r: r.balance), + [ + { + "balance": -1800.0, + }, + { + "balance": 36.0, + "name": "Cash Discount Write-Off", + }, + { + "balance": 1764.0, + "name": "test ref", + }, + ], + ) + + write_off_move = reconciled_line_ids.filtered( + lambda r: r.journal_id == woff_journal + ).move_id + + self.assertRecordValues( + write_off_move.line_ids.sorted(lambda r: r.balance), + [ + { + "balance": -30.0, # Not Tax + }, + { + "balance": -6.0, # Tax + }, + { + "balance": 36.0, + }, + ], + ) + + def test_invoice_with_discount_2(self): + """ + Discount: Tax excluded + Invoice: + Amount without Tax: 1500 + Tax: 20% (300) + Total on invoice: 1800 + Discount: 2% (30) + Total with discount: 1770 + """ + invoice_date = Date.today() + woff_account = self.cash_discount_writeoff_account + woff_journal = self.cash_discount_writeoff_journal + payment_mode = self.payment_mode_out + payment_mode.post_move = True + self.company.write( + { + "default_cash_discount_writeoff_account_id": woff_account.id, + "default_cash_discount_writeoff_journal_id": woff_journal.id, + "cash_discount_base_amount_type": "untaxed", + } + ) + invoice = self.create_supplier_invoice( + invoice_date, + self.payment_mode_out, + 1500, + self.tax_20_p, + self.payment_term_2_p_discount_7d, + ) + invoice._onchange_discount_delay() + self.assertTrue(invoice.has_discount) + self.assertRecordValues( + invoice, + [ + { + "amount_untaxed": 1500.0, + "amount_tax": 300.0, + "amount_total": 1800.0, + "discount_amount": 30.0, + "discount_percent": 2.0, + "amount_total_with_discount": 1770.0, + } + ], + ) + invoice.ref = "test ref" + invoice.action_post() + + payment_order = self.create_payment_order(invoice_date, invoice) + + self.assertEqual(len(payment_order.payment_line_ids), 1) + payment_line = payment_order.payment_line_ids[0] + self.assertTrue(payment_line.pay_with_discount) + self.assertAlmostEqual(payment_line.amount_currency, 1770.0) + self.assertTrue(payment_line.pay_with_discount) + + payment_order.draft2open() + payment_order.open2generated() + payment_order.generated2uploaded() + + self.assertEqual(len(payment_order.move_ids), 1) + + self.assertEqual(invoice.payment_state, "paid") + + domain_reconlied_line = payment_order.move_ids.open_reconcile_view()["domain"] + reconciled_line_ids = self.env["account.move.line"].search( + domain_reconlied_line + ) + + self.assertRecordValues( + reconciled_line_ids.sorted(lambda r: r.balance), + [ + { + "balance": -1800.0, + }, + { + "balance": 30.0, + "name": "Cash Discount Write-Off", + }, + { + "balance": 1770.0, + "name": "test ref", + }, + ], + ) + + write_off_move = reconciled_line_ids.filtered( + lambda r: r.journal_id == woff_journal + ).move_id + + self.assertRecordValues( + write_off_move.line_ids.sorted(lambda r: r.balance), + [ + { + "balance": -30.0, # Not Tax + }, + { + "balance": 30.0, + }, + ], + ) + + def test_invoice_with_discount_with_cn_1(self): + """ + Discount: Tax included + Invoice: + Amount without Tax: 1500 + Tax: 20% (300) + Total on invoice: 1800 + Discount: 2% (36) + + Credit Note: + Amount without Tax: 500 + Tax: 20% (100) + Total on invoice: 600 + Discount: 2% (12) + + Total with discount: 1176 + """ + invoice_date = Date.today() + woff_account = self.cash_discount_writeoff_account + woff_journal = self.cash_discount_writeoff_journal + payment_mode = self.payment_mode_out + payment_mode.post_move = True + self.company.write( + { + "default_cash_discount_writeoff_account_id": woff_account.id, + "default_cash_discount_writeoff_journal_id": woff_journal.id, + "cash_discount_base_amount_type": "total", + } + ) + invoice = self.create_supplier_invoice( + invoice_date, + self.payment_mode_out, + 1500, + self.tax_20_p, + self.payment_term_2_p_discount_7d, + ) + invoice._onchange_discount_delay() + self.assertTrue(invoice.has_discount) + self.assertRecordValues( + invoice, + [ + { + "amount_untaxed": 1500.0, + "amount_tax": 300.0, + "amount_total": 1800.0, + "discount_amount": 36.0, + "discount_percent": 2.0, + "amount_total_with_discount": 1764.0, + "real_discount_amount": 36.0, + "refunds_discount_amount": 0.0, + "residual_with_discount": 1764.0, + "invoice_payment_term_id": self.payment_term_2_p_discount_7d.id, + } + ], + ) + invoice.ref = "test ref" + invoice.action_post() + + move_reversal = ( + self.env["account.move.reversal"] + .with_context(active_model="account.move", active_ids=invoice.ids) + .create( + { + "refund_method": "refund", + "journal_id": invoice.journal_id.id, + } + ) + ) + reversal = move_reversal.reverse_moves() + reversed_move = self.env["account.move"].browse(reversal["res_id"]) + reversed_move.write( + { + "invoice_line_ids": [ + Command.update( + reversed_move.invoice_line_ids.id, {"price_unit": 500} + ), + ], + } + ) + reversed_move.action_post() + self.assertRecordValues( + reversed_move, + [ + { + "amount_untaxed": 500.0, + "amount_tax": 100.0, + "amount_total": 600.0, + "discount_amount": 12.0, + "discount_percent": 2.0, + "amount_total_with_discount": 588.0, + "invoice_payment_term_id": self.payment_term_2_p_discount_7d.id, + } + ], + ) + + (invoice + reversed_move).line_ids.filtered( + lambda line: line.account_type in ("asset_receivable", "liability_payable") + ).reconcile() + + self.assertRecordValues( + invoice, + [ + { + "amount_untaxed": 1500.0, + "amount_tax": 300.0, + "amount_total": 1800.0, + "discount_amount": 36.0, + "discount_percent": 2.0, + "amount_total_with_discount": 1764.0, + "real_discount_amount": 24.0, + "refunds_discount_amount": 12.0, + "residual_with_discount": 1176.0, + "invoice_payment_term_id": self.payment_term_2_p_discount_7d.id, + } + ], + ) + + payment_order = self.create_payment_order(invoice_date, invoice) + + self.assertEqual(len(payment_order.payment_line_ids), 1) + payment_line = payment_order.payment_line_ids[0] + self.assertTrue(payment_line.pay_with_discount) + self.assertAlmostEqual(payment_line.amount_currency, 1176.0) + self.assertTrue(payment_line.pay_with_discount) + + payment_order.draft2open() + payment_order.open2generated() + payment_order.generated2uploaded() + + self.assertEqual(len(payment_order.move_ids), 1) + + self.assertEqual(invoice.payment_state, "paid") + + domain_reconlied_line = payment_order.move_ids.open_reconcile_view()["domain"] + reconciled_line_ids = self.env["account.move.line"].search( + domain_reconlied_line + ) + + self.assertRecordValues( + reconciled_line_ids.sorted(lambda r: r.balance), + [ + { + "balance": -1800.0, + }, + { + "balance": 24.0, + "name": "Cash Discount Write-Off", + }, + { + "balance": 600.0, # Credit note + }, + { + "balance": 1176.0, + "name": "test ref", + }, + ], + ) + + write_off_move = reconciled_line_ids.filtered( + lambda r: r.journal_id == woff_journal + ).move_id + + self.assertRecordValues( + write_off_move.line_ids.sorted(lambda r: r.balance), + [ + { + "balance": -30.0, # Not Tax + }, + { + "balance": -6.0, # Tax + }, + { + "balance": 2.0, # Tax Credit Note + }, + { + "balance": 10.0, # Credit Note + }, + { + "balance": 24.0, + }, + ], + ) + + def test_invoice_with_discount_with_cn_2(self): + """ + Discount: Tax excluded + Invoice: + Amount without Tax: 1500 + Tax: 20% (300) + Total on invoice: 1800 + Discount: 2% (20) + + Credit Note: + Amount without Tax: 500 + Tax: 20% (100) + Total on invoice: 600 + Discount: 2% (10) + + Total with discount: 1180 + """ + invoice_date = Date.today() + woff_account = self.cash_discount_writeoff_account + woff_journal = self.cash_discount_writeoff_journal + payment_mode = self.payment_mode_out + payment_mode.post_move = True + self.company.write( + { + "default_cash_discount_writeoff_account_id": woff_account.id, + "default_cash_discount_writeoff_journal_id": woff_journal.id, + "cash_discount_base_amount_type": "untaxed", + } + ) + invoice = self.create_supplier_invoice( + invoice_date, + self.payment_mode_out, + 1500, + self.tax_20_p, + self.payment_term_2_p_discount_7d, + ) + invoice._onchange_discount_delay() + self.assertTrue(invoice.has_discount) + self.assertRecordValues( + invoice, + [ + { + "amount_untaxed": 1500.0, + "amount_tax": 300.0, + "amount_total": 1800.0, + "discount_amount": 30.0, + "discount_percent": 2.0, + "amount_total_with_discount": 1770.0, + "real_discount_amount": 30.0, + "refunds_discount_amount": 0.0, + "residual_with_discount": 1770.0, + "invoice_payment_term_id": self.payment_term_2_p_discount_7d.id, + } + ], + ) + invoice.ref = "test ref" + invoice.action_post() + + move_reversal = ( + self.env["account.move.reversal"] + .with_context(active_model="account.move", active_ids=invoice.ids) + .create( + { + "refund_method": "refund", + "journal_id": invoice.journal_id.id, + } + ) + ) + reversal = move_reversal.reverse_moves() + reversed_move = self.env["account.move"].browse(reversal["res_id"]) + reversed_move.write( + { + "invoice_line_ids": [ + Command.update( + reversed_move.invoice_line_ids.id, {"price_unit": 500} + ), + ], + } + ) + reversed_move.action_post() + self.assertRecordValues( + reversed_move, + [ + { + "amount_untaxed": 500.0, + "amount_tax": 100.0, + "amount_total": 600.0, + "discount_amount": 10.0, + "discount_percent": 2.0, + "amount_total_with_discount": 590.0, + "invoice_payment_term_id": self.payment_term_2_p_discount_7d.id, + } + ], + ) + + (invoice + reversed_move).line_ids.filtered( + lambda line: line.account_type in ("asset_receivable", "liability_payable") + ).reconcile() + + self.assertRecordValues( + invoice, + [ + { + "amount_untaxed": 1500.0, + "amount_tax": 300.0, + "amount_total": 1800.0, + "discount_amount": 30.0, + "discount_percent": 2.0, + "amount_total_with_discount": 1770.0, + "real_discount_amount": 20.0, + "refunds_discount_amount": 10.0, + "residual_with_discount": 1180.0, + "invoice_payment_term_id": self.payment_term_2_p_discount_7d.id, + } + ], + ) + + payment_order = self.create_payment_order(invoice_date, invoice) + + self.assertEqual(len(payment_order.payment_line_ids), 1) + payment_line = payment_order.payment_line_ids[0] + self.assertTrue(payment_line.pay_with_discount) + self.assertAlmostEqual(payment_line.amount_currency, 1180.0) + self.assertTrue(payment_line.pay_with_discount) + + payment_order.draft2open() + payment_order.open2generated() + payment_order.generated2uploaded() + + self.assertEqual(len(payment_order.move_ids), 1) + + self.assertEqual(invoice.payment_state, "paid") + + domain_reconlied_line = payment_order.move_ids.open_reconcile_view()["domain"] + reconciled_line_ids = self.env["account.move.line"].search( + domain_reconlied_line + ) + + self.assertRecordValues( + reconciled_line_ids.sorted(lambda r: r.balance), + [ + { + "balance": -1800.0, + }, + { + "balance": 20.0, + "name": "Cash Discount Write-Off", + }, + { + "balance": 600.0, # Credit Note + }, + { + "balance": 1180.0, + "name": "test ref", + }, + ], + ) + + write_off_move = reconciled_line_ids.filtered( + lambda r: r.journal_id == woff_journal + ).move_id + + self.assertRecordValues( + write_off_move.line_ids.sorted(lambda r: r.balance), + [ + { + "balance": -20.0, # Not Tax + }, + { + "balance": 20.0, + }, + ], + ) diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000000..7c50ec06848a --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +odoo-addon-account-cash-discount-base @ git+https://github.com/OCA/account-payment.git@refs/pull/706/head#subdirectory=setup/account_cash_discount_base +odoo-addon-account-cash-discount-payment @ git+https://github.com/OCA/account-payment.git@refs/pull/707/head#subdirectory=setup/account_cash_discount_payment