From 7b0882600a29ddd641115c062e961cedc84477dd Mon Sep 17 00:00:00 2001 From: Bhavan23 Date: Thu, 20 Mar 2025 19:20:41 +0530 Subject: [PATCH] test: add unit test to validate outstanding amount for update_outstanding_for_self checkbox enabled --- .../sales_invoice/test_sales_invoice.py | 29 +++++ .../test_accounts_receivable.py | 106 +++++++++++++++++- 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 85bd9e052bf..e27dbb052c4 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -4354,6 +4354,35 @@ class TestSalesInvoice(IntegrationTestCase): pos_return = make_sales_return(pos.name) self.assertEqual(abs(pos_return.payments[0].amount), pos.payments[0].amount) + def test_create_return_invoice_for_self_update(self): + from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + from erpnext.controllers.sales_and_purchase_return import make_return_doc + + invoice = create_sales_invoice() + + payment_entry = get_payment_entry(dt=invoice.doctype, dn=invoice.name) + payment_entry.reference_no = "test001" + payment_entry.reference_date = getdate() + + payment_entry.save() + payment_entry.submit() + + r_invoice = make_return_doc(invoice.doctype, invoice.name) + + r_invoice.update_outstanding_for_self = 0 + r_invoice.save() + + self.assertEqual(r_invoice.update_outstanding_for_self, 1) + + r_invoice.submit() + + self.assertNotEqual(r_invoice.outstanding_amount, 0) + + invoice.reload() + + self.assertEqual(invoice.outstanding_amount, 0) + def test_prevents_fully_returned_invoice_with_zero_quantity(self): from erpnext.controllers.sales_and_purchase_return import StockOverReturnError, make_return_doc diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index 88c7909154d..2fc9a33f615 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -21,7 +21,7 @@ class TestAccountsReceivable(AccountsTestMixin, IntegrationTestCase): def tearDown(self): frappe.db.rollback() - def create_sales_invoice(self, no_payment_schedule=False, do_not_submit=False): + def create_sales_invoice(self, no_payment_schedule=False, do_not_submit=False, **args): frappe.set_user("Administrator") si = create_sales_invoice( item=self.item, @@ -34,6 +34,7 @@ class TestAccountsReceivable(AccountsTestMixin, IntegrationTestCase): rate=100, price_list_rate=100, do_not_save=1, + **args, ) if not no_payment_schedule: si.append( @@ -108,7 +109,7 @@ class TestAccountsReceivable(AccountsTestMixin, IntegrationTestCase): self.assertEqual(expected_data[0], [row.invoiced, row.paid, row.credit_note]) pos_inv.cancel() - def test_accounts_receivable(self): + def test_accounts_receivable_with_payment(self): filters = { "company": self.company, "based_on_payment_terms": 1, @@ -145,11 +146,15 @@ class TestAccountsReceivable(AccountsTestMixin, IntegrationTestCase): cr_note = self.create_credit_note(si.name, do_not_submit=True) cr_note.update_outstanding_for_self = False cr_note.save().submit() + + # as the invoice partially paid and returning the full amount so the outstanding amount should be True + self.assertEqual(cr_note.update_outstanding_for_self, True) + report = execute(filters) - expected_data_after_credit_note = [100, 0, 0, 40, -40, self.debit_to] + expected_data_after_credit_note = [0, 0, 100, 0, -100, self.debit_to] - row = report[1][0] + row = report[1][-1] self.assertEqual( expected_data_after_credit_note, [ @@ -162,6 +167,99 @@ class TestAccountsReceivable(AccountsTestMixin, IntegrationTestCase): ], ) + def test_accounts_receivable_without_payment(self): + filters = { + "company": self.company, + "based_on_payment_terms": 1, + "report_date": today(), + "range": "30, 60, 90, 120", + "show_remarks": True, + } + + # check invoice grand total and invoiced column's value for 3 payment terms + si = self.create_sales_invoice() + + report = execute(filters) + + expected_data = [[100, 30, "No Remarks"], [100, 50, "No Remarks"], [100, 20, "No Remarks"]] + + for i in range(3): + row = report[1][i - 1] + self.assertEqual(expected_data[i - 1], [row.invoice_grand_total, row.invoiced, row.remarks]) + + # check invoice grand total, invoiced, paid and outstanding column's value after credit note + cr_note = self.create_credit_note(si.name, do_not_submit=True) + cr_note.update_outstanding_for_self = False + cr_note.save().submit() + + self.assertEqual(cr_note.update_outstanding_for_self, False) + + report = execute(filters) + + row = report[1] + self.assertTrue(len(row) == 0) + + def test_accounts_receivable_with_partial_payment(self): + filters = { + "company": self.company, + "based_on_payment_terms": 1, + "report_date": today(), + "range": "30, 60, 90, 120", + "show_remarks": True, + } + + # check invoice grand total and invoiced column's value for 3 payment terms + si = self.create_sales_invoice(qty=2) + + report = execute(filters) + + expected_data = [[200, 60, "No Remarks"], [200, 100, "No Remarks"], [200, 40, "No Remarks"]] + + for i in range(3): + row = report[1][i - 1] + self.assertEqual(expected_data[i - 1], [row.invoice_grand_total, row.invoiced, row.remarks]) + + # check invoice grand total, invoiced, paid and outstanding column's value after payment + self.create_payment_entry(si.name) + report = execute(filters) + + expected_data_after_payment = [[200, 60, 40, 20], [200, 100, 0, 100], [200, 40, 0, 40]] + + for i in range(3): + row = report[1][i - 1] + self.assertEqual( + expected_data_after_payment[i - 1], + [row.invoice_grand_total, row.invoiced, row.paid, row.outstanding], + ) + + # check invoice grand total, invoiced, paid and outstanding column's value after credit note + cr_note = self.create_credit_note(si.name, do_not_submit=True) + cr_note.update_outstanding_for_self = False + cr_note.save().submit() + + self.assertFalse(cr_note.update_outstanding_for_self) + + report = execute(filters) + + expected_data_after_credit_note = [ + [200, 100, 0, 80, 20, self.debit_to], + [200, 40, 0, 0, 40, self.debit_to], + ] + + for i in range(2): + row = report[1][i - 1] + self.assertEqual( + expected_data_after_credit_note[i - 1], + [ + row.invoice_grand_total, + row.invoiced, + row.paid, + row.credit_note, + row.outstanding, + row.party_account, + ], + ) + def test_cr_note_flag_to_update_self(self): filters = { "company": self.company,