From 070e2d4d26cc3154d869bb65669b1776e0d5e454 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 16 May 2024 11:40:50 +0530 Subject: [PATCH 1/4] refactor: advance payments, allow configurable reconciliation date --- .../doctype/payment_entry/payment_entry.json | 12 +++++++++++- .../doctype/payment_entry/payment_entry.py | 15 +++++++++------ erpnext/setup/doctype/company/company.json | 10 +++++++++- erpnext/setup/doctype/company/company.py | 1 + 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index e27a1f79b8e..3eef9814ae3 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -20,6 +20,7 @@ "party", "party_name", "book_advance_payments_in_separate_party_account", + "reconcile_on_advance_payment_date", "column_break_11", "bank_account", "party_bank_account", @@ -766,6 +767,15 @@ "label": "In Words", "print_hide": 1, "read_only": 1 + }, + { + "default": "0", + "fetch_from": "company.reconcile_on_advance_payment_date", + "fieldname": "reconcile_on_advance_payment_date", + "fieldtype": "Check", + "hidden": 1, + "label": "Reconcile on Advance Payment Date", + "read_only": 1 } ], "index_web_pages_for_search": 1, @@ -779,7 +789,7 @@ "table_fieldname": "payment_entries" } ], - "modified": "2024-04-11 11:25:07.366347", + "modified": "2024-05-16 11:50:19.394918", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 8daa13d6165..4e05afa6be9 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1344,13 +1344,16 @@ class PaymentEntry(AccountsController): "voucher_detail_no": invoice.name, } - date_field = "posting_date" - if invoice.reference_doctype in ["Sales Order", "Purchase Order"]: - date_field = "transaction_date" - posting_date = frappe.db.get_value(invoice.reference_doctype, invoice.reference_name, date_field) - - if getdate(posting_date) < getdate(self.posting_date): + if self.reconcile_on_advance_payment_date: posting_date = self.posting_date + else: + date_field = "posting_date" + if invoice.reference_doctype in ["Sales Order", "Purchase Order"]: + date_field = "transaction_date" + posting_date = frappe.db.get_value(invoice.reference_doctype, invoice.reference_name, date_field) + + if getdate(posting_date) < getdate(self.posting_date): + posting_date = self.posting_date dr_or_cr, account = self.get_dr_and_account_for_advances(invoice) args_dict["account"] = account diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 8c5a34ef804..af25fb49b47 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -67,6 +67,7 @@ "default_finance_book", "advance_payments_section", "book_advance_payments_in_separate_party_account", + "reconcile_on_advance_payment_date", "column_break_fwcf", "default_advance_received_account", "default_advance_paid_account", @@ -763,6 +764,13 @@ "fieldtype": "Tab Break", "label": "Dashboard", "show_dashboard": 1 + }, + { + "default": "0", + "depends_on": "eval: doc.book_advance_payments_in_separate_party_account", + "fieldname": "reconcile_on_advance_payment_date", + "fieldtype": "Check", + "label": "Reconcile on Advance Payment Date" } ], "icon": "fa fa-building", @@ -770,7 +778,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2024-04-23 12:38:33.173938", + "modified": "2024-05-16 11:52:13.067003", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index f2d9bb74b92..44800dd5c3e 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -85,6 +85,7 @@ class Company(NestedSet): parent_company: DF.Link | None payment_terms: DF.Link | None phone_no: DF.Data | None + reconcile_on_advance_payment_date: DF.Check registration_details: DF.Code | None rgt: DF.Int round_off_account: DF.Link | None From 000c1b49dc6182a1b5a2394495e86f3a050dd666 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 16 May 2024 12:33:14 +0530 Subject: [PATCH 2/4] chore: better description --- erpnext/setup/doctype/company/company.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index af25fb49b47..7b552d8a061 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -768,6 +768,7 @@ { "default": "0", "depends_on": "eval: doc.book_advance_payments_in_separate_party_account", + "description": "If Enabled - Reconciliation happens on the Advance Payment posting date
\nIf Disabled - Reconciliation happens on oldest of 2 Dates: Invoice Date or the Advance Payment posting date
\n", "fieldname": "reconcile_on_advance_payment_date", "fieldtype": "Check", "label": "Reconcile on Advance Payment Date" @@ -778,7 +779,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2024-05-16 11:52:13.067003", + "modified": "2024-05-16 12:39:54.694232", "modified_by": "Administrator", "module": "Setup", "name": "Company", From cafa2f52e5811cbc973ea01c7a4ab635dc827483 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 17 May 2024 10:21:16 +0530 Subject: [PATCH 3/4] refactor: enable no-copy on advance payment flags --- erpnext/accounts/doctype/payment_entry/payment_entry.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index 3eef9814ae3..f911352c884 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -752,6 +752,7 @@ "fieldtype": "Check", "hidden": 1, "label": "Book Advance Payments in Separate Party Account", + "no_copy": 1, "read_only": 1 }, { @@ -775,6 +776,7 @@ "fieldtype": "Check", "hidden": 1, "label": "Reconcile on Advance Payment Date", + "no_copy": 1, "read_only": 1 } ], @@ -789,7 +791,7 @@ "table_fieldname": "payment_entries" } ], - "modified": "2024-05-16 11:50:19.394918", + "modified": "2024-05-17 10:21:11.199445", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", From 30aa4e031d7da5d0a16e8921acbe7b8861adf773 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 20 May 2024 14:42:41 +0530 Subject: [PATCH 4/4] test: reconciliation date for advance payments --- .../test_payment_reconciliation.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py index 0a3a0678084..53f69a47e75 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py @@ -1525,6 +1525,55 @@ class TestPaymentReconciliation(FrappeTestCase): ] 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 make_customer(customer_name, currency=None): if not frappe.db.exists("Customer", customer_name):