From 90ee21f86897c7ec647195929b39f72a52ef00b0 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 17 Jul 2024 15:27:58 +0530 Subject: [PATCH 1/3] fix: missing cr/dr notes on payment reconciliation (cherry picked from commit a30af68e9e71752f8317e23c9865d0f38d18512e) --- .../doctype/payment_reconciliation/payment_reconciliation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index b0347514905..9480aeb7746 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -200,6 +200,7 @@ class PaymentReconciliation(Document): conditions.append(doc.docstatus == 1) conditions.append(doc[frappe.scrub(self.party_type)] == self.party) conditions.append(doc.is_return == 1) + conditions.append(doc.outstanding_amount != 0) if self.payment_name: conditions.append(doc.name.like(f"%{self.payment_name}%")) From 3109efaf099a916d25bcd35b44c06cbb60c51a07 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 17 Jul 2024 17:51:11 +0530 Subject: [PATCH 2/3] test: payment filter should not affect dr/cr notes (cherry picked from commit 2d686c06ea213cbd6e7a5cf7173a5a4bddbcc67b) # Conflicts: # erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py --- .../test_payment_reconciliation.py | 497 ++++++++++++++++++ 1 file changed, 497 insertions(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py index 22f05957a79..623230fd486 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py @@ -1335,6 +1335,503 @@ class TestPaymentReconciliation(FrappeTestCase): # Should not raise frappe.exceptions.ValidationError: Payment Entry has been modified after you pulled it. Please pull it again. pr.reconcile() +<<<<<<< HEAD +======= + def test_reverse_payment_against_payment_for_supplier(self): + """ + Reconcile a payment against a reverse payment, for a supplier. + """ + self.supplier = "_Test Supplier" + amount = 4000 + + pe = self.create_payment_entry(amount=amount) + pe.party_type = "Supplier" + pe.party = self.supplier + pe.payment_type = "Pay" + pe.paid_from = self.cash + pe.paid_to = self.creditors + pe.save().submit() + + reverse_pe = self.create_payment_entry(amount=amount) + reverse_pe.party_type = "Supplier" + reverse_pe.party = self.supplier + reverse_pe.payment_type = "Receive" + reverse_pe.paid_from = self.creditors + reverse_pe.paid_to = self.cash + reverse_pe.save().submit() + + pr = self.create_payment_reconciliation(party_is_customer=False) + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + self.assertEqual(pr.invoices[0].invoice_number, reverse_pe.name) + self.assertEqual(pr.payments[0].reference_name, pe.name) + + invoices = [invoice.as_dict() for invoice in pr.invoices] + payments = [payment.as_dict() for payment in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + + pe.reload() + self.assertEqual(len(pe.references), 1) + self.assertEqual(pe.references[0].exchange_rate, 1) + # There should not be any Exc Gain/Loss + self.assertEqual(pe.references[0].exchange_gain_loss, 0) + self.assertEqual(pe.references[0].reference_name, reverse_pe.name) + + journals = frappe.db.get_all( + "Journal Entry", + filters={ + "voucher_type": "Exchange Gain Or Loss", + "reference_type": "Payment Entry", + "reference_name": ("in", [pe.name, reverse_pe.name]), + }, + ) + # There should be no Exchange Gain/Loss created + self.assertEqual(journals, []) + + def test_advance_reverse_payment_against_payment_for_supplier(self): + """ + Reconcile an Advance payment against reverse payment, for a supplier. + """ + frappe.db.set_value( + "Company", + self.company, + { + "book_advance_payments_in_separate_party_account": 1, + "default_advance_paid_account": self.advance_payable_account, + }, + ) + + self.supplier = "_Test Supplier" + amount = 4000 + + pe = self.create_payment_entry(amount=amount) + pe.party_type = "Supplier" + pe.party = self.supplier + pe.payment_type = "Pay" + pe.paid_from = self.cash + pe.paid_to = self.advance_payable_account + pe.save().submit() + + reverse_pe = self.create_payment_entry(amount=amount) + reverse_pe.party_type = "Supplier" + reverse_pe.party = self.supplier + reverse_pe.payment_type = "Receive" + reverse_pe.paid_from = self.advance_payable_account + reverse_pe.paid_to = self.cash + reverse_pe.save().submit() + + pr = self.create_payment_reconciliation(party_is_customer=False) + pr.default_advance_account = self.advance_payable_account + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + self.assertEqual(pr.invoices[0].invoice_number, reverse_pe.name) + self.assertEqual(pr.payments[0].reference_name, pe.name) + + invoices = [invoice.as_dict() for invoice in pr.invoices] + payments = [payment.as_dict() for payment in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + + pe.reload() + self.assertEqual(len(pe.references), 1) + self.assertEqual(pe.references[0].exchange_rate, 1) + # There should not be any Exc Gain/Loss + self.assertEqual(pe.references[0].exchange_gain_loss, 0) + self.assertEqual(pe.references[0].reference_name, reverse_pe.name) + + journals = frappe.db.get_all( + "Journal Entry", + filters={ + "voucher_type": "Exchange Gain Or Loss", + "reference_type": "Payment Entry", + "reference_name": ("in", [pe.name, reverse_pe.name]), + }, + ) + # There should be no Exchange Gain/Loss created + self.assertEqual(journals, []) + + # Assert Ledger Entries + gl_entries = frappe.db.get_all( + "GL Entry", + filters={"voucher_no": pe.name}, + fields=["account", "voucher_no", "against_voucher", "debit", "credit"], + order_by="account, against_voucher, debit", + ) + expected_gle = [ + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher": pe.name, + "debit": 0.0, + "credit": amount, + }, + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher": pe.name, + "debit": amount, + "credit": 0.0, + }, + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher": reverse_pe.name, + "debit": amount, + "credit": 0.0, + }, + { + "account": "Cash - _PR", + "voucher_no": pe.name, + "against_voucher": None, + "debit": 0.0, + "credit": amount, + }, + ] + self.assertEqual(gl_entries, expected_gle) + pl_entries = frappe.db.get_all( + "Payment Ledger Entry", + filters={"voucher_no": pe.name}, + fields=["account", "voucher_no", "against_voucher_no", "amount"], + order_by="account, against_voucher_no, amount", + ) + expected_ple = [ + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": -amount, + }, + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": amount, + }, + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher_no": reverse_pe.name, + "amount": -amount, + }, + ] + self.assertEqual(pl_entries, expected_ple) + + def test_advance_payment_reconciliation_date(self): + frappe.db.set_value( + "Company", + self.company, + { + "book_advance_payments_in_separate_party_account": 1, + "default_advance_paid_account": self.advance_payable_account, + "reconcile_on_advance_payment_date": 1, + }, + ) + + self.supplier = "_Test Supplier" + amount = 1500 + + pe = self.create_payment_entry(amount=amount) + pe.posting_date = add_days(nowdate(), -1) + pe.party_type = "Supplier" + pe.party = self.supplier + pe.payment_type = "Pay" + pe.paid_from = self.cash + pe.paid_to = self.advance_payable_account + pe.save().submit() + + pi = self.create_purchase_invoice(qty=10, rate=100) + self.assertNotEqual(pe.posting_date, pi.posting_date) + + pr = self.create_payment_reconciliation(party_is_customer=False) + pr.default_advance_account = self.advance_payable_account + pr.from_payment_date = pe.posting_date + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + invoices = [invoice.as_dict() for invoice in pr.invoices] + payments = [payment.as_dict() for payment in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + + # Assert Ledger Entries + gl_entries = frappe.db.get_all( + "GL Entry", + filters={"voucher_no": pe.name, "is_cancelled": 0, "posting_date": pe.posting_date}, + ) + self.assertEqual(len(gl_entries), 4) + pl_entries = frappe.db.get_all( + "Payment Ledger Entry", + filters={"voucher_no": pe.name, "delinked": 0, "posting_date": pe.posting_date}, + ) + self.assertEqual(len(pl_entries), 3) + + def test_advance_payment_reconciliation_against_journal_for_customer(self): + frappe.db.set_value( + "Company", + self.company, + { + "book_advance_payments_in_separate_party_account": 1, + "default_advance_received_account": self.advance_receivable_account, + "reconcile_on_advance_payment_date": 0, + }, + ) + amount = 200.0 + je = self.create_journal_entry(self.debit_to, self.bank, amount) + je.accounts[0].cost_center = self.main_cc.name + je.accounts[0].party_type = "Customer" + je.accounts[0].party = self.customer + je.accounts[1].cost_center = self.main_cc.name + je = je.save().submit() + + pe = self.create_payment_entry(amount=amount).save().submit() + + pr = self.create_payment_reconciliation() + pr.default_advance_account = self.advance_receivable_account + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + invoices = [invoice.as_dict() for invoice in pr.invoices] + payments = [payment.as_dict() for payment in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + + # Assert Ledger Entries + gl_entries = frappe.db.get_all( + "GL Entry", + filters={"voucher_no": pe.name, "is_cancelled": 0}, + ) + self.assertEqual(len(gl_entries), 4) + pl_entries = frappe.db.get_all( + "Payment Ledger Entry", + filters={"voucher_no": pe.name, "delinked": 0}, + ) + self.assertEqual(len(pl_entries), 3) + + gl_entries = frappe.db.get_all( + "GL Entry", + filters={"voucher_no": pe.name, "is_cancelled": 0}, + fields=["account", "voucher_no", "against_voucher", "debit", "credit"], + order_by="account, against_voucher, debit", + ) + expected_gle = [ + { + "account": self.advance_receivable_account, + "voucher_no": pe.name, + "against_voucher": pe.name, + "debit": 0.0, + "credit": amount, + }, + { + "account": self.advance_receivable_account, + "voucher_no": pe.name, + "against_voucher": pe.name, + "debit": amount, + "credit": 0.0, + }, + { + "account": self.debit_to, + "voucher_no": pe.name, + "against_voucher": je.name, + "debit": 0.0, + "credit": amount, + }, + { + "account": self.bank, + "voucher_no": pe.name, + "against_voucher": None, + "debit": amount, + "credit": 0.0, + }, + ] + self.assertEqual(gl_entries, expected_gle) + + pl_entries = frappe.db.get_all( + "Payment Ledger Entry", + filters={"voucher_no": pe.name}, + fields=["account", "voucher_no", "against_voucher_no", "amount"], + order_by="account, against_voucher_no, amount", + ) + expected_ple = [ + { + "account": self.advance_receivable_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": -amount, + }, + { + "account": self.advance_receivable_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": amount, + }, + { + "account": self.debit_to, + "voucher_no": pe.name, + "against_voucher_no": je.name, + "amount": -amount, + }, + ] + self.assertEqual(pl_entries, expected_ple) + + def test_advance_payment_reconciliation_against_journal_for_supplier(self): + self.supplier = make_supplier("_Test Supplier") + frappe.db.set_value( + "Company", + self.company, + { + "book_advance_payments_in_separate_party_account": 1, + "default_advance_paid_account": self.advance_payable_account, + "reconcile_on_advance_payment_date": 0, + }, + ) + amount = 200.0 + je = self.create_journal_entry(self.creditors, self.bank, -amount) + je.accounts[0].cost_center = self.main_cc.name + je.accounts[0].party_type = "Supplier" + je.accounts[0].party = self.supplier + je.accounts[1].cost_center = self.main_cc.name + je = je.save().submit() + + pe = self.create_payment_entry(amount=amount) + pe.payment_type = "Pay" + pe.party_type = "Supplier" + pe.paid_from = self.bank + pe.paid_to = self.creditors + pe.party = self.supplier + pe.save().submit() + + pr = self.create_payment_reconciliation(party_is_customer=False) + pr.default_advance_account = self.advance_payable_account + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + invoices = [invoice.as_dict() for invoice in pr.invoices] + payments = [payment.as_dict() for payment in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + + # Assert Ledger Entries + gl_entries = frappe.db.get_all( + "GL Entry", + filters={"voucher_no": pe.name, "is_cancelled": 0}, + ) + self.assertEqual(len(gl_entries), 4) + pl_entries = frappe.db.get_all( + "Payment Ledger Entry", + filters={"voucher_no": pe.name, "delinked": 0}, + ) + self.assertEqual(len(pl_entries), 3) + + gl_entries = frappe.db.get_all( + "GL Entry", + filters={"voucher_no": pe.name, "is_cancelled": 0}, + fields=["account", "voucher_no", "against_voucher", "debit", "credit"], + order_by="account, against_voucher, debit", + ) + expected_gle = [ + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher": pe.name, + "debit": 0.0, + "credit": amount, + }, + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher": pe.name, + "debit": amount, + "credit": 0.0, + }, + { + "account": self.creditors, + "voucher_no": pe.name, + "against_voucher": je.name, + "debit": amount, + "credit": 0.0, + }, + { + "account": self.bank, + "voucher_no": pe.name, + "against_voucher": None, + "debit": 0.0, + "credit": amount, + }, + ] + self.assertEqual(gl_entries, expected_gle) + + pl_entries = frappe.db.get_all( + "Payment Ledger Entry", + filters={"voucher_no": pe.name}, + fields=["account", "voucher_no", "against_voucher_no", "amount"], + order_by="account, against_voucher_no, amount", + ) + expected_ple = [ + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": -amount, + }, + { + "account": self.advance_payable_account, + "voucher_no": pe.name, + "against_voucher_no": pe.name, + "amount": amount, + }, + { + "account": self.creditors, + "voucher_no": pe.name, + "against_voucher_no": je.name, + "amount": -amount, + }, + ] + self.assertEqual(pl_entries, expected_ple) + + def test_cr_note_payment_limit_filter(self): + transaction_date = nowdate() + amount = 100 + + for _ in range(6): + self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date) + cr_note = self.create_sales_invoice( + qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True + ) + cr_note.is_return = 1 + cr_note = cr_note.save().submit() + + pr = self.create_payment_reconciliation() + + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 6) + self.assertEqual(len(pr.payments), 6) + invoices = [x.as_dict() for x in pr.get("invoices")] + payments = [x.as_dict() for x in pr.get("payments")] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.reconcile() + + pr.get_unreconciled_entries() + self.assertEqual(pr.get("invoices"), []) + self.assertEqual(pr.get("payments"), []) + + self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date) + cr_note = self.create_sales_invoice( + qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True + ) + cr_note.is_return = 1 + cr_note = cr_note.save().submit() + + # Limit should not affect in fetching the unallocated cr_note + pr.invoice_limit = 5 + pr.payment_limit = 5 + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + +>>>>>>> 2d686c06ea (test: payment filter should not affect dr/cr notes) def make_customer(customer_name, currency=None): if not frappe.db.exists("Customer", customer_name): From fac22e93d008d6e22b5003b244b2480e03a04a5e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 18 Jul 2024 12:44:34 +0530 Subject: [PATCH 3/3] chore: resolve conflict --- .../test_payment_reconciliation.py | 457 ------------------ 1 file changed, 457 deletions(-) diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py index 623230fd486..b25f7b6b4d9 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py @@ -1335,462 +1335,6 @@ class TestPaymentReconciliation(FrappeTestCase): # Should not raise frappe.exceptions.ValidationError: Payment Entry has been modified after you pulled it. Please pull it again. pr.reconcile() -<<<<<<< HEAD -======= - def test_reverse_payment_against_payment_for_supplier(self): - """ - Reconcile a payment against a reverse payment, for a supplier. - """ - self.supplier = "_Test Supplier" - amount = 4000 - - pe = self.create_payment_entry(amount=amount) - pe.party_type = "Supplier" - pe.party = self.supplier - pe.payment_type = "Pay" - pe.paid_from = self.cash - pe.paid_to = self.creditors - pe.save().submit() - - reverse_pe = self.create_payment_entry(amount=amount) - reverse_pe.party_type = "Supplier" - reverse_pe.party = self.supplier - reverse_pe.payment_type = "Receive" - reverse_pe.paid_from = self.creditors - reverse_pe.paid_to = self.cash - reverse_pe.save().submit() - - pr = self.create_payment_reconciliation(party_is_customer=False) - pr.get_unreconciled_entries() - self.assertEqual(len(pr.invoices), 1) - self.assertEqual(len(pr.payments), 1) - self.assertEqual(pr.invoices[0].invoice_number, reverse_pe.name) - self.assertEqual(pr.payments[0].reference_name, pe.name) - - invoices = [invoice.as_dict() for invoice in pr.invoices] - payments = [payment.as_dict() for payment in pr.payments] - pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) - pr.reconcile() - - pe.reload() - self.assertEqual(len(pe.references), 1) - self.assertEqual(pe.references[0].exchange_rate, 1) - # There should not be any Exc Gain/Loss - self.assertEqual(pe.references[0].exchange_gain_loss, 0) - self.assertEqual(pe.references[0].reference_name, reverse_pe.name) - - journals = frappe.db.get_all( - "Journal Entry", - filters={ - "voucher_type": "Exchange Gain Or Loss", - "reference_type": "Payment Entry", - "reference_name": ("in", [pe.name, reverse_pe.name]), - }, - ) - # There should be no Exchange Gain/Loss created - self.assertEqual(journals, []) - - def test_advance_reverse_payment_against_payment_for_supplier(self): - """ - Reconcile an Advance payment against reverse payment, for a supplier. - """ - frappe.db.set_value( - "Company", - self.company, - { - "book_advance_payments_in_separate_party_account": 1, - "default_advance_paid_account": self.advance_payable_account, - }, - ) - - self.supplier = "_Test Supplier" - amount = 4000 - - pe = self.create_payment_entry(amount=amount) - pe.party_type = "Supplier" - pe.party = self.supplier - pe.payment_type = "Pay" - pe.paid_from = self.cash - pe.paid_to = self.advance_payable_account - pe.save().submit() - - reverse_pe = self.create_payment_entry(amount=amount) - reverse_pe.party_type = "Supplier" - reverse_pe.party = self.supplier - reverse_pe.payment_type = "Receive" - reverse_pe.paid_from = self.advance_payable_account - reverse_pe.paid_to = self.cash - reverse_pe.save().submit() - - pr = self.create_payment_reconciliation(party_is_customer=False) - pr.default_advance_account = self.advance_payable_account - pr.get_unreconciled_entries() - self.assertEqual(len(pr.invoices), 1) - self.assertEqual(len(pr.payments), 1) - self.assertEqual(pr.invoices[0].invoice_number, reverse_pe.name) - self.assertEqual(pr.payments[0].reference_name, pe.name) - - invoices = [invoice.as_dict() for invoice in pr.invoices] - payments = [payment.as_dict() for payment in pr.payments] - pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) - pr.reconcile() - - pe.reload() - self.assertEqual(len(pe.references), 1) - self.assertEqual(pe.references[0].exchange_rate, 1) - # There should not be any Exc Gain/Loss - self.assertEqual(pe.references[0].exchange_gain_loss, 0) - self.assertEqual(pe.references[0].reference_name, reverse_pe.name) - - journals = frappe.db.get_all( - "Journal Entry", - filters={ - "voucher_type": "Exchange Gain Or Loss", - "reference_type": "Payment Entry", - "reference_name": ("in", [pe.name, reverse_pe.name]), - }, - ) - # There should be no Exchange Gain/Loss created - self.assertEqual(journals, []) - - # Assert Ledger Entries - gl_entries = frappe.db.get_all( - "GL Entry", - filters={"voucher_no": pe.name}, - fields=["account", "voucher_no", "against_voucher", "debit", "credit"], - order_by="account, against_voucher, debit", - ) - expected_gle = [ - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher": pe.name, - "debit": 0.0, - "credit": amount, - }, - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher": pe.name, - "debit": amount, - "credit": 0.0, - }, - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher": reverse_pe.name, - "debit": amount, - "credit": 0.0, - }, - { - "account": "Cash - _PR", - "voucher_no": pe.name, - "against_voucher": None, - "debit": 0.0, - "credit": amount, - }, - ] - self.assertEqual(gl_entries, expected_gle) - pl_entries = frappe.db.get_all( - "Payment Ledger Entry", - filters={"voucher_no": pe.name}, - fields=["account", "voucher_no", "against_voucher_no", "amount"], - order_by="account, against_voucher_no, amount", - ) - expected_ple = [ - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher_no": pe.name, - "amount": -amount, - }, - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher_no": pe.name, - "amount": amount, - }, - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher_no": reverse_pe.name, - "amount": -amount, - }, - ] - self.assertEqual(pl_entries, expected_ple) - - def test_advance_payment_reconciliation_date(self): - frappe.db.set_value( - "Company", - self.company, - { - "book_advance_payments_in_separate_party_account": 1, - "default_advance_paid_account": self.advance_payable_account, - "reconcile_on_advance_payment_date": 1, - }, - ) - - self.supplier = "_Test Supplier" - amount = 1500 - - pe = self.create_payment_entry(amount=amount) - pe.posting_date = add_days(nowdate(), -1) - pe.party_type = "Supplier" - pe.party = self.supplier - pe.payment_type = "Pay" - pe.paid_from = self.cash - pe.paid_to = self.advance_payable_account - pe.save().submit() - - pi = self.create_purchase_invoice(qty=10, rate=100) - self.assertNotEqual(pe.posting_date, pi.posting_date) - - pr = self.create_payment_reconciliation(party_is_customer=False) - pr.default_advance_account = self.advance_payable_account - pr.from_payment_date = pe.posting_date - pr.get_unreconciled_entries() - self.assertEqual(len(pr.invoices), 1) - self.assertEqual(len(pr.payments), 1) - invoices = [invoice.as_dict() for invoice in pr.invoices] - payments = [payment.as_dict() for payment in pr.payments] - pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) - pr.reconcile() - - # Assert Ledger Entries - gl_entries = frappe.db.get_all( - "GL Entry", - filters={"voucher_no": pe.name, "is_cancelled": 0, "posting_date": pe.posting_date}, - ) - self.assertEqual(len(gl_entries), 4) - pl_entries = frappe.db.get_all( - "Payment Ledger Entry", - filters={"voucher_no": pe.name, "delinked": 0, "posting_date": pe.posting_date}, - ) - self.assertEqual(len(pl_entries), 3) - - def test_advance_payment_reconciliation_against_journal_for_customer(self): - frappe.db.set_value( - "Company", - self.company, - { - "book_advance_payments_in_separate_party_account": 1, - "default_advance_received_account": self.advance_receivable_account, - "reconcile_on_advance_payment_date": 0, - }, - ) - amount = 200.0 - je = self.create_journal_entry(self.debit_to, self.bank, amount) - je.accounts[0].cost_center = self.main_cc.name - je.accounts[0].party_type = "Customer" - je.accounts[0].party = self.customer - je.accounts[1].cost_center = self.main_cc.name - je = je.save().submit() - - pe = self.create_payment_entry(amount=amount).save().submit() - - pr = self.create_payment_reconciliation() - pr.default_advance_account = self.advance_receivable_account - pr.get_unreconciled_entries() - self.assertEqual(len(pr.invoices), 1) - self.assertEqual(len(pr.payments), 1) - invoices = [invoice.as_dict() for invoice in pr.invoices] - payments = [payment.as_dict() for payment in pr.payments] - pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) - pr.reconcile() - - # Assert Ledger Entries - gl_entries = frappe.db.get_all( - "GL Entry", - filters={"voucher_no": pe.name, "is_cancelled": 0}, - ) - self.assertEqual(len(gl_entries), 4) - pl_entries = frappe.db.get_all( - "Payment Ledger Entry", - filters={"voucher_no": pe.name, "delinked": 0}, - ) - self.assertEqual(len(pl_entries), 3) - - gl_entries = frappe.db.get_all( - "GL Entry", - filters={"voucher_no": pe.name, "is_cancelled": 0}, - fields=["account", "voucher_no", "against_voucher", "debit", "credit"], - order_by="account, against_voucher, debit", - ) - expected_gle = [ - { - "account": self.advance_receivable_account, - "voucher_no": pe.name, - "against_voucher": pe.name, - "debit": 0.0, - "credit": amount, - }, - { - "account": self.advance_receivable_account, - "voucher_no": pe.name, - "against_voucher": pe.name, - "debit": amount, - "credit": 0.0, - }, - { - "account": self.debit_to, - "voucher_no": pe.name, - "against_voucher": je.name, - "debit": 0.0, - "credit": amount, - }, - { - "account": self.bank, - "voucher_no": pe.name, - "against_voucher": None, - "debit": amount, - "credit": 0.0, - }, - ] - self.assertEqual(gl_entries, expected_gle) - - pl_entries = frappe.db.get_all( - "Payment Ledger Entry", - filters={"voucher_no": pe.name}, - fields=["account", "voucher_no", "against_voucher_no", "amount"], - order_by="account, against_voucher_no, amount", - ) - expected_ple = [ - { - "account": self.advance_receivable_account, - "voucher_no": pe.name, - "against_voucher_no": pe.name, - "amount": -amount, - }, - { - "account": self.advance_receivable_account, - "voucher_no": pe.name, - "against_voucher_no": pe.name, - "amount": amount, - }, - { - "account": self.debit_to, - "voucher_no": pe.name, - "against_voucher_no": je.name, - "amount": -amount, - }, - ] - self.assertEqual(pl_entries, expected_ple) - - def test_advance_payment_reconciliation_against_journal_for_supplier(self): - self.supplier = make_supplier("_Test Supplier") - frappe.db.set_value( - "Company", - self.company, - { - "book_advance_payments_in_separate_party_account": 1, - "default_advance_paid_account": self.advance_payable_account, - "reconcile_on_advance_payment_date": 0, - }, - ) - amount = 200.0 - je = self.create_journal_entry(self.creditors, self.bank, -amount) - je.accounts[0].cost_center = self.main_cc.name - je.accounts[0].party_type = "Supplier" - je.accounts[0].party = self.supplier - je.accounts[1].cost_center = self.main_cc.name - je = je.save().submit() - - pe = self.create_payment_entry(amount=amount) - pe.payment_type = "Pay" - pe.party_type = "Supplier" - pe.paid_from = self.bank - pe.paid_to = self.creditors - pe.party = self.supplier - pe.save().submit() - - pr = self.create_payment_reconciliation(party_is_customer=False) - pr.default_advance_account = self.advance_payable_account - pr.get_unreconciled_entries() - self.assertEqual(len(pr.invoices), 1) - self.assertEqual(len(pr.payments), 1) - invoices = [invoice.as_dict() for invoice in pr.invoices] - payments = [payment.as_dict() for payment in pr.payments] - pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) - pr.reconcile() - - # Assert Ledger Entries - gl_entries = frappe.db.get_all( - "GL Entry", - filters={"voucher_no": pe.name, "is_cancelled": 0}, - ) - self.assertEqual(len(gl_entries), 4) - pl_entries = frappe.db.get_all( - "Payment Ledger Entry", - filters={"voucher_no": pe.name, "delinked": 0}, - ) - self.assertEqual(len(pl_entries), 3) - - gl_entries = frappe.db.get_all( - "GL Entry", - filters={"voucher_no": pe.name, "is_cancelled": 0}, - fields=["account", "voucher_no", "against_voucher", "debit", "credit"], - order_by="account, against_voucher, debit", - ) - expected_gle = [ - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher": pe.name, - "debit": 0.0, - "credit": amount, - }, - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher": pe.name, - "debit": amount, - "credit": 0.0, - }, - { - "account": self.creditors, - "voucher_no": pe.name, - "against_voucher": je.name, - "debit": amount, - "credit": 0.0, - }, - { - "account": self.bank, - "voucher_no": pe.name, - "against_voucher": None, - "debit": 0.0, - "credit": amount, - }, - ] - self.assertEqual(gl_entries, expected_gle) - - pl_entries = frappe.db.get_all( - "Payment Ledger Entry", - filters={"voucher_no": pe.name}, - fields=["account", "voucher_no", "against_voucher_no", "amount"], - order_by="account, against_voucher_no, amount", - ) - expected_ple = [ - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher_no": pe.name, - "amount": -amount, - }, - { - "account": self.advance_payable_account, - "voucher_no": pe.name, - "against_voucher_no": pe.name, - "amount": amount, - }, - { - "account": self.creditors, - "voucher_no": pe.name, - "against_voucher_no": je.name, - "amount": -amount, - }, - ] - self.assertEqual(pl_entries, expected_ple) - def test_cr_note_payment_limit_filter(self): transaction_date = nowdate() amount = 100 @@ -1831,7 +1375,6 @@ class TestPaymentReconciliation(FrappeTestCase): self.assertEqual(len(pr.invoices), 1) self.assertEqual(len(pr.payments), 1) ->>>>>>> 2d686c06ea (test: payment filter should not affect dr/cr notes) def make_customer(customer_name, currency=None): if not frappe.db.exists("Customer", customer_name):