diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index 8f9f7ce3bea..c8bf6644a51 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -702,7 +702,50 @@ class TestPaymentEntry(FrappeTestCase): pe2.submit() # create return entry against si1 - create_sales_invoice(is_return=1, return_against=si1.name, qty=-1) + cr_note = create_sales_invoice(is_return=1, return_against=si1.name, qty=-1) + si1_outstanding = frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount") + + # create JE(credit note) manually against si1 and cr_note + je = frappe.get_doc( + { + "doctype": "Journal Entry", + "company": si1.company, + "voucher_type": "Credit Note", + "posting_date": nowdate(), + } + ) + je.append( + "accounts", + { + "account": si1.debit_to, + "party_type": "Customer", + "party": si1.customer, + "debit": 0, + "credit": 100, + "debit_in_account_currency": 0, + "credit_in_account_currency": 100, + "reference_type": si1.doctype, + "reference_name": si1.name, + "cost_center": si1.items[0].cost_center, + }, + ) + je.append( + "accounts", + { + "account": cr_note.debit_to, + "party_type": "Customer", + "party": cr_note.customer, + "debit": 100, + "credit": 0, + "debit_in_account_currency": 100, + "credit_in_account_currency": 0, + "reference_type": cr_note.doctype, + "reference_name": cr_note.name, + "cost_center": cr_note.items[0].cost_center, + }, + ) + je.save().submit() + si1_outstanding = frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount") self.assertEqual(si1_outstanding, -100) diff --git a/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py b/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py index fc6dbba7e7f..ce9579ed613 100644 --- a/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py +++ b/erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py @@ -294,7 +294,7 @@ class TestPaymentLedgerEntry(FrappeTestCase): cr_note1.return_against = si3.name cr_note1 = cr_note1.save().submit() - pl_entries = ( + pl_entries_si3 = ( qb.from_(ple) .select( ple.voucher_type, @@ -309,7 +309,24 @@ class TestPaymentLedgerEntry(FrappeTestCase): .run(as_dict=True) ) - expected_values = [ + pl_entries_cr_note1 = ( + qb.from_(ple) + .select( + ple.voucher_type, + ple.voucher_no, + ple.against_voucher_type, + ple.against_voucher_no, + ple.amount, + ple.delinked, + ) + .where( + (ple.against_voucher_type == cr_note1.doctype) & (ple.against_voucher_no == cr_note1.name) + ) + .orderby(ple.creation) + .run(as_dict=True) + ) + + expected_values_for_si3 = [ { "voucher_type": si3.doctype, "voucher_no": si3.name, @@ -317,18 +334,21 @@ class TestPaymentLedgerEntry(FrappeTestCase): "against_voucher_no": si3.name, "amount": amount, "delinked": 0, - }, + } + ] + # credit/debit notes post ledger entries against itself + expected_values_for_cr_note1 = [ { "voucher_type": cr_note1.doctype, "voucher_no": cr_note1.name, - "against_voucher_type": si3.doctype, - "against_voucher_no": si3.name, + "against_voucher_type": cr_note1.doctype, + "against_voucher_no": cr_note1.name, "amount": -amount, "delinked": 0, }, ] - self.assertEqual(pl_entries[0], expected_values[0]) - self.assertEqual(pl_entries[1], expected_values[1]) + self.assertEqual(pl_entries_si3, expected_values_for_si3) + self.assertEqual(pl_entries_cr_note1, expected_values_for_cr_note1) def test_je_against_inv_and_note(self): ple = self.ple diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index 07b46a48078..7ef5278d252 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -186,15 +186,12 @@ class PaymentReconciliation(Document): self.common_filter_conditions.append(ple.account == self.receivable_payable_account) self.get_return_invoices() - return_invoices = [ - x for x in self.return_invoices if x.return_against == None or x.return_against == "" - ] outstanding_dr_or_cr = [] - if return_invoices: + if self.return_invoices: ple_query = QueryPaymentLedger() return_outstanding = ple_query.get_voucher_outstandings( - vouchers=return_invoices, + vouchers=self.return_invoices, common_filter=self.common_filter_conditions, posting_date=self.ple_posting_date_filter, min_outstanding=-(self.minimum_payment_amount) if self.minimum_payment_amount else None, diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 66438a7efab..efe97415a55 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -86,8 +86,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying. } } - if(doc.docstatus == 1 && doc.outstanding_amount != 0 - && !(doc.is_return && doc.return_against) && !doc.on_hold) { + if(doc.docstatus == 1 && doc.outstanding_amount != 0 && !doc.on_hold) { this.frm.add_custom_button( __('Payment'), () => this.make_payment_entry(), diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index f33439989a8..9f1224d65e8 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -628,9 +628,7 @@ class PurchaseInvoice(BuyingController): "credit_in_account_currency": base_grand_total if self.party_account_currency == self.company_currency else grand_total, - "against_voucher": self.return_against - if cint(self.is_return) and self.return_against - else self.name, + "against_voucher": self.name, "against_voucher_type": self.doctype, "project": self.project, "cost_center": self.cost_center, @@ -1644,12 +1642,8 @@ class PurchaseInvoice(BuyingController): elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(): self.status = "Unpaid" # Check if outstanding amount is 0 due to debit note issued against invoice - elif ( - outstanding_amount <= 0 - and self.is_return == 0 - and frappe.db.get_value( - "Purchase Invoice", {"is_return": 1, "return_against": self.name, "docstatus": 1} - ) + elif self.is_return == 0 and frappe.db.get_value( + "Purchase Invoice", {"is_return": 1, "return_against": self.name, "docstatus": 1} ): self.status = "Debit Note Issued" elif self.is_return == 1: diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index a4bcdb41db5..642e99cd58a 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -98,8 +98,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e erpnext.accounts.ledger_preview.show_stock_ledger_preview(this.frm); } - if (doc.docstatus == 1 && doc.outstanding_amount!=0 - && !(cint(doc.is_return) && doc.return_against)) { + if (doc.docstatus == 1 && doc.outstanding_amount!=0) { this.frm.add_custom_button( __('Payment'), () => this.make_payment_entry(), diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 0bc5aa2ed2d..fba2fa7552e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1104,9 +1104,7 @@ class SalesInvoice(SellingController): "debit_in_account_currency": base_grand_total if self.party_account_currency == self.company_currency else grand_total, - "against_voucher": self.return_against - if cint(self.is_return) and self.return_against - else self.name, + "against_voucher": self.name, "against_voucher_type": self.doctype, "cost_center": self.cost_center, "project": self.project, @@ -1732,12 +1730,8 @@ class SalesInvoice(SellingController): elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(): self.status = "Unpaid" # Check if outstanding amount is 0 due to credit note issued against invoice - elif ( - outstanding_amount <= 0 - and self.is_return == 0 - and frappe.db.get_value( - "Sales Invoice", {"is_return": 1, "return_against": self.name, "docstatus": 1} - ) + elif self.is_return == 0 and frappe.db.get_value( + "Sales Invoice", {"is_return": 1, "return_against": self.name, "docstatus": 1} ): self.status = "Credit Note Issued" elif self.is_return == 1: diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index f9cfe5a9200..21b39d73120 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1500,8 +1500,8 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(party_credited, 1000) # Check outstanding amount - self.assertFalse(si1.outstanding_amount) - self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500) + self.assertEqual(frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount"), -1000) + self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 2500) def test_gle_made_when_asset_is_returned(self): create_asset_data()