From 1fe80c2d02766afff9e30d0451bee03d5a23028c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 20 Oct 2023 17:16:54 +0530 Subject: [PATCH 1/5] refactor: gain_loss posting date fields in the allocation table (cherry picked from commit 55dbcee36a2acf4aa41c66147c263a85ef606f81) # Conflicts: # erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json --- .../payment_reconciliation_allocation.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json index a553b982d14..6aaa58aedf7 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json +++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json @@ -158,6 +158,7 @@ "fieldname": "gain_loss_posting_date", "fieldtype": "Date", "label": "Difference Posting Date" +<<<<<<< HEAD }, { "fieldname": "accounting_dimensions_section", @@ -167,12 +168,18 @@ { "fieldname": "dimension_col_break", "fieldtype": "Column Break" +======= +>>>>>>> 55dbcee36a (refactor: gain_loss posting date fields in the allocation table) } ], "is_virtual": 1, "istable": 1, "links": [], +<<<<<<< HEAD "modified": "2023-12-14 13:38:26.104150", +======= + "modified": "2023-10-23 10:44:56.066303", +>>>>>>> 55dbcee36a (refactor: gain_loss posting date fields in the allocation table) "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Allocation", From 39571d828edbfe50a689a58006e71f313fd5efdd Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 22 Oct 2023 08:59:52 +0530 Subject: [PATCH 2/5] refactor: introduce fields in popup (cherry picked from commit 5323bb7beeb6526d16bcb19fc2f3acd3a95927e6) # Conflicts: # erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js --- .../payment_reconciliation.js | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js index e0d142288e8..a5d080760b2 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js @@ -254,6 +254,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo this.data = []; const dialog = new frappe.ui.Dialog({ title: __("Select Difference Account"), + size: 'extra-large', fields: [ { fieldname: "allocation", @@ -265,6 +266,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo get_data: () => { return this.data; }, +<<<<<<< HEAD fields: [ { fieldtype: "Data", @@ -303,6 +305,48 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo read_only: 1, }, ], +======= + fields: [{ + fieldtype:'Data', + fieldname:"docname", + in_list_view: 1, + hidden: 1 + }, { + fieldtype:'Data', + fieldname:"reference_name", + label: __("Voucher No"), + in_list_view: 1, + read_only: 1 + }, { + fieldtype:'Date', + fieldname:"gain_loss_posting_date", + label: __("Posting Date"), + in_list_view: 1, + reqd: 1, + }, { + + fieldtype:'Link', + options: 'Account', + in_list_view: 1, + label: __("Difference Account"), + fieldname: 'difference_account', + reqd: 1, + get_query: () => { + return { + filters: { + company: this.frm.doc.company, + is_group: 0 + } + } + } + }, { + fieldtype:'Currency', + in_list_view: 1, + label: __("Difference Amount"), + fieldname: 'difference_amount', + read_only: 1 + }] +>>>>>>> 5323bb7bee (refactor: introduce fields in popup) }, { fieldtype: "HTML", @@ -312,6 +356,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo primary_action: () => { const args = dialog.get_values()["allocation"]; +<<<<<<< HEAD args.forEach((d) => { frappe.model.set_value( "Payment Reconciliation Allocation", @@ -319,6 +364,12 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo "difference_account", d.difference_account ); +======= + args.forEach(d => { + frappe.model.set_value("Payment Reconciliation Allocation", d.docname, + "difference_account", d.difference_account); + +>>>>>>> 5323bb7bee (refactor: introduce fields in popup) }); this.reconcile_payment_entries(); @@ -330,10 +381,18 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo this.frm.doc.allocation.forEach((d) => { if (d.difference_amount) { dialog.fields_dict.allocation.df.data.push({ +<<<<<<< HEAD docname: d.name, reference_name: d.reference_name, difference_amount: d.difference_amount, difference_account: d.difference_account, +======= + 'docname': d.name, + 'reference_name': d.reference_name, + 'difference_amount': d.difference_amount, + 'difference_account': d.difference_account, + 'gain_loss_posting_date': d.gain_loss_posting_date +>>>>>>> 5323bb7bee (refactor: introduce fields in popup) }); } }); From 125722ae4150d1d443b402119312b797c765c712 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Sun, 22 Oct 2023 20:26:45 +0530 Subject: [PATCH 3/5] refactor: pass gain loss posting date to controller (cherry picked from commit 7e600a6494d7f07c6fd2b8f1cc71857801a2573c) # Conflicts: # erpnext/accounts/utils.py --- .../payment_reconciliation/payment_reconciliation.js | 2 ++ .../payment_reconciliation/payment_reconciliation.py | 2 ++ .../payment_reconciliation_allocation.json | 1 + erpnext/accounts/utils.py | 4 ++++ erpnext/controllers/accounts_controller.py | 6 ++++-- 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js index a5d080760b2..042a6123ebd 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js @@ -368,6 +368,8 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo args.forEach(d => { frappe.model.set_value("Payment Reconciliation Allocation", d.docname, "difference_account", d.difference_account); + frappe.model.set_value("Payment Reconciliation Allocation", d.docname, + "gain_loss_posting_date", d.gain_loss_posting_date); >>>>>>> 5323bb7bee (refactor: introduce fields in popup) }); diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py index 2c4952a0c66..dcb1a16dba4 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py @@ -446,6 +446,7 @@ class PaymentReconciliation(Document): res.difference_amount = self.get_difference_amount(pay, inv, res["allocated_amount"]) res.difference_account = default_exchange_gain_loss_account res.exchange_rate = inv.get("exchange_rate") + res.update({"gain_loss_posting_date": pay.get("posting_date")}) if pay.get("amount") == 0: entries.append(res) @@ -562,6 +563,7 @@ class PaymentReconciliation(Document): "allocated_amount": flt(row.get("allocated_amount")), "difference_amount": flt(row.get("difference_amount")), "difference_account": row.get("difference_account"), + "difference_posting_date": row.get("gain_loss_posting_date"), "cost_center": row.get("cost_center"), } ) diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json index 6aaa58aedf7..c40d0ce29d3 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json +++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json @@ -19,6 +19,7 @@ "is_advance", "section_break_5", "difference_amount", + "gain_loss_posting_date", "column_break_7", "difference_account", "exchange_rate", diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 0e6c041d24d..c2653237e5a 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -726,7 +726,11 @@ def update_reference_in_payment_entry( payment_entry.set_missing_ref_details(ref_exchange_rate=d.exchange_rate or None) payment_entry.set_amounts() payment_entry.make_exchange_gain_loss_journal( +<<<<<<< HEAD frappe._dict({"difference_posting_date": d.difference_posting_date}), dimensions_dict +======= + frappe._dict({"difference_posting_date": d.difference_posting_date}) +>>>>>>> 7e600a6494 (refactor: pass gain loss posting date to controller) ) if not do_not_save: diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index fe4500a41e5..185ef4c22f0 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1360,7 +1360,9 @@ class AccountsController(TransactionBase): self.name, arg.get("referenced_row"), ): - posting_date = frappe.db.get_value(arg.voucher_type, arg.voucher_no, "posting_date") + posting_date = arg.get("difference_posting_date") or frappe.db.get_value( + arg.voucher_type, arg.voucher_no, "posting_date" + ) je = create_gain_loss_journal( self.company, posting_date, @@ -1444,7 +1446,7 @@ class AccountsController(TransactionBase): je = create_gain_loss_journal( self.company, - self.posting_date, + args.get("difference_posting_date") if args else self.posting_date, self.party_type, self.party, party_account, From fd33437d7a9ccb9ac023662654608a979376d4cd Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 23 Oct 2023 12:32:10 +0530 Subject: [PATCH 4/5] test: varying posting date for gain loss journal (cherry picked from commit 514d5434a3ae24e2c7839fbd76a115d6c0841513) --- .../tests/test_accounts_controller.py | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index 65b2696e79a..2170628361d 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -7,7 +7,7 @@ import frappe from frappe import qb from frappe.query_builder.functions import Sum from frappe.tests.utils import FrappeTestCase, change_settings -from frappe.utils import add_days, flt, nowdate +from frappe.utils import add_days, flt, getdate, nowdate from erpnext import get_default_cost_center from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry @@ -616,6 +616,73 @@ class TestAccountsController(FrappeTestCase): self.assertEqual(exc_je_for_si, []) self.assertEqual(exc_je_for_pe, []) + def test_15_gain_loss_on_different_posting_date(self): + # Invoice in Foreign Currency + si = self.create_sales_invoice( + posting_date=add_days(nowdate(), -2), qty=2, conversion_rate=80, rate=1 + ) + # Payment + pe = ( + self.create_payment_entry(posting_date=add_days(nowdate(), -1), amount=2, source_exc_rate=75) + .save() + .submit() + ) + + # There should be outstanding in both currencies + si.reload() + self.assertEqual(si.outstanding_amount, 2) + self.assert_ledger_outstanding(si.doctype, si.name, 160.0, 2.0) + + # Reconcile the remaining amount + pr = frappe.get_doc("Payment Reconciliation") + pr.company = self.company + pr.party_type = "Customer" + pr.party = self.customer + pr.receivable_payable_account = self.debit_usd + pr.get_unreconciled_entries() + self.assertEqual(len(pr.invoices), 1) + self.assertEqual(len(pr.payments), 1) + invoices = [x.as_dict() for x in pr.invoices] + payments = [x.as_dict() for x in pr.payments] + pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments})) + pr.allocation[0].gain_loss_posting_date = add_days(nowdate(), 1) + pr.reconcile() + + # Exchange Gain/Loss Journal should've been created. + exc_je_for_si = self.get_journals_for(si.doctype, si.name) + exc_je_for_pe = self.get_journals_for(pe.doctype, pe.name) + self.assertNotEqual(exc_je_for_si, []) + self.assertEqual(len(exc_je_for_si), 1) + self.assertEqual(len(exc_je_for_pe), 1) + self.assertEqual(exc_je_for_si[0], exc_je_for_pe[0]) + + self.assertEqual( + frappe.db.get_value("Journal Entry", exc_je_for_si[0].parent, "posting_date"), + getdate(add_days(nowdate(), 1)), + ) + + self.assertEqual(len(pr.invoices), 0) + self.assertEqual(len(pr.payments), 0) + + # There should be no outstanding + si.reload() + self.assertEqual(si.outstanding_amount, 0) + self.assert_ledger_outstanding(si.doctype, si.name, 0.0, 0.0) + + # Cancel Payment + pe.reload() + pe.cancel() + + si.reload() + self.assertEqual(si.outstanding_amount, 2) + self.assert_ledger_outstanding(si.doctype, si.name, 160.0, 2.0) + + # Exchange Gain/Loss Journal should've been cancelled + exc_je_for_si = self.get_journals_for(si.doctype, si.name) + exc_je_for_pe = self.get_journals_for(pe.doctype, pe.name) + self.assertEqual(exc_je_for_si, []) + self.assertEqual(exc_je_for_pe, []) + def test_20_journal_against_sales_invoice(self): # Invoice in Foreign Currency si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1) From 565bfa16f2766aa4cbbe194dc0669ec16b5e9109 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 28 Mar 2024 17:18:13 +0530 Subject: [PATCH 5/5] chore: resolve conflicts --- .../payment_reconciliation.js | 76 ++++--------------- .../payment_reconciliation_allocation.json | 7 -- erpnext/accounts/utils.py | 4 - 3 files changed, 15 insertions(+), 72 deletions(-) diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js index 042a6123ebd..cc99fe7b583 100644 --- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js +++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js @@ -254,7 +254,7 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo this.data = []; const dialog = new frappe.ui.Dialog({ title: __("Select Difference Account"), - size: 'extra-large', + size: "extra-large", fields: [ { fieldname: "allocation", @@ -266,7 +266,6 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo get_data: () => { return this.data; }, -<<<<<<< HEAD fields: [ { fieldtype: "Data", @@ -281,6 +280,13 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo in_list_view: 1, read_only: 1, }, + { + fieldtype: "Date", + fieldname: "gain_loss_posting_date", + label: __("Posting Date"), + in_list_view: 1, + reqd: 1, + }, { fieldtype: "Link", options: "Account", @@ -305,48 +311,6 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo read_only: 1, }, ], -======= - fields: [{ - fieldtype:'Data', - fieldname:"docname", - in_list_view: 1, - hidden: 1 - }, { - fieldtype:'Data', - fieldname:"reference_name", - label: __("Voucher No"), - in_list_view: 1, - read_only: 1 - }, { - fieldtype:'Date', - fieldname:"gain_loss_posting_date", - label: __("Posting Date"), - in_list_view: 1, - reqd: 1, - }, { - - fieldtype:'Link', - options: 'Account', - in_list_view: 1, - label: __("Difference Account"), - fieldname: 'difference_account', - reqd: 1, - get_query: () => { - return { - filters: { - company: this.frm.doc.company, - is_group: 0 - } - } - } - }, { - fieldtype:'Currency', - in_list_view: 1, - label: __("Difference Amount"), - fieldname: 'difference_amount', - read_only: 1 - }] ->>>>>>> 5323bb7bee (refactor: introduce fields in popup) }, { fieldtype: "HTML", @@ -356,7 +320,6 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo primary_action: () => { const args = dialog.get_values()["allocation"]; -<<<<<<< HEAD args.forEach((d) => { frappe.model.set_value( "Payment Reconciliation Allocation", @@ -364,14 +327,12 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo "difference_account", d.difference_account ); -======= - args.forEach(d => { - frappe.model.set_value("Payment Reconciliation Allocation", d.docname, - "difference_account", d.difference_account); - frappe.model.set_value("Payment Reconciliation Allocation", d.docname, - "gain_loss_posting_date", d.gain_loss_posting_date); - ->>>>>>> 5323bb7bee (refactor: introduce fields in popup) + frappe.model.set_value( + "Payment Reconciliation Allocation", + d.docname, + "gain_loss_posting_date", + d.gain_loss_posting_date + ); }); this.reconcile_payment_entries(); @@ -383,18 +344,11 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo this.frm.doc.allocation.forEach((d) => { if (d.difference_amount) { dialog.fields_dict.allocation.df.data.push({ -<<<<<<< HEAD docname: d.name, reference_name: d.reference_name, difference_amount: d.difference_amount, difference_account: d.difference_account, -======= - 'docname': d.name, - 'reference_name': d.reference_name, - 'difference_amount': d.difference_amount, - 'difference_account': d.difference_account, - 'gain_loss_posting_date': d.gain_loss_posting_date ->>>>>>> 5323bb7bee (refactor: introduce fields in popup) + gain_loss_posting_date: d.gain_loss_posting_date, }); } }); diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json index c40d0ce29d3..3f85b213500 100644 --- a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json +++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json @@ -159,7 +159,6 @@ "fieldname": "gain_loss_posting_date", "fieldtype": "Date", "label": "Difference Posting Date" -<<<<<<< HEAD }, { "fieldname": "accounting_dimensions_section", @@ -169,18 +168,12 @@ { "fieldname": "dimension_col_break", "fieldtype": "Column Break" -======= ->>>>>>> 55dbcee36a (refactor: gain_loss posting date fields in the allocation table) } ], "is_virtual": 1, "istable": 1, "links": [], -<<<<<<< HEAD "modified": "2023-12-14 13:38:26.104150", -======= - "modified": "2023-10-23 10:44:56.066303", ->>>>>>> 55dbcee36a (refactor: gain_loss posting date fields in the allocation table) "modified_by": "Administrator", "module": "Accounts", "name": "Payment Reconciliation Allocation", diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index c2653237e5a..0e6c041d24d 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -726,11 +726,7 @@ def update_reference_in_payment_entry( payment_entry.set_missing_ref_details(ref_exchange_rate=d.exchange_rate or None) payment_entry.set_amounts() payment_entry.make_exchange_gain_loss_journal( -<<<<<<< HEAD frappe._dict({"difference_posting_date": d.difference_posting_date}), dimensions_dict -======= - frappe._dict({"difference_posting_date": d.difference_posting_date}) ->>>>>>> 7e600a6494 (refactor: pass gain loss posting date to controller) ) if not do_not_save: