From 17535095e23f0b4859c6dd813be4e317b4683093 Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 12:07:20 +0530 Subject: [PATCH 1/6] feat: add difference_posting_date field (cherry picked from commit 225e56cbcae5c30172b52aa2e6cbc04a5ec01d43) # Conflicts: # erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json # erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py # erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json # erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py --- .../purchase_invoice_advance.json | 18 ++++++++++--- .../purchase_invoice_advance.py | 25 +++++++++++++++++++ .../sales_invoice_advance.json | 18 ++++++++++--- .../sales_invoice_advance.py | 25 +++++++++++++++++++ 4 files changed, 80 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json index 9fcbf5c6339..2f6d30c0922 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json @@ -14,7 +14,8 @@ "advance_amount", "allocated_amount", "exchange_gain_loss", - "ref_exchange_rate" + "ref_exchange_rate", + "difference_posting_date" ], "fields": [ { @@ -30,7 +31,7 @@ "width": "180px" }, { - "columns": 3, + "columns": 2, "fieldname": "reference_name", "fieldtype": "Dynamic Link", "in_list_view": 1, @@ -40,7 +41,7 @@ "read_only": 1 }, { - "columns": 3, + "columns": 2, "fieldname": "remarks", "fieldtype": "Text", "in_list_view": 1, @@ -111,13 +112,24 @@ "label": "Reference Exchange Rate", "non_negative": 1, "read_only": 1 + }, + { + "columns": 2, + "fieldname": "difference_posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Difference Posting Date" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], +<<<<<<< HEAD "modified": "2021-09-26 15:47:28.167371", +======= + "modified": "2024-12-20 12:04:46.729972", +>>>>>>> 225e56cbca (feat: add difference_posting_date field) "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Advance", diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py index 44e1f6d5685..6f8971c12f4 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py @@ -6,4 +6,29 @@ from frappe.model.document import Document class PurchaseInvoiceAdvance(Document): +<<<<<<< HEAD +======= + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + advance_amount: DF.Currency + allocated_amount: DF.Currency + difference_posting_date: DF.Date | None + exchange_gain_loss: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + ref_exchange_rate: DF.Float + reference_name: DF.DynamicLink | None + reference_row: DF.Data | None + reference_type: DF.Link | None + remarks: DF.Text | None + # end: auto-generated types + +>>>>>>> 225e56cbca (feat: add difference_posting_date field) pass diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json index f92b57a45e1..19336f84342 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json @@ -14,7 +14,8 @@ "advance_amount", "allocated_amount", "exchange_gain_loss", - "ref_exchange_rate" + "ref_exchange_rate", + "difference_posting_date" ], "fields": [ { @@ -30,7 +31,7 @@ "width": "250px" }, { - "columns": 3, + "columns": 2, "fieldname": "reference_name", "fieldtype": "Dynamic Link", "in_list_view": 1, @@ -41,7 +42,7 @@ "read_only": 1 }, { - "columns": 3, + "columns": 2, "fieldname": "remarks", "fieldtype": "Text", "in_list_view": 1, @@ -112,13 +113,24 @@ "label": "Reference Exchange Rate", "non_negative": 1, "read_only": 1 + }, + { + "columns": 2, + "fieldname": "difference_posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Difference Posting Date" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], +<<<<<<< HEAD "modified": "2021-09-26 15:47:46.911595", +======= + "modified": "2024-12-20 11:58:28.962370", +>>>>>>> 225e56cbca (feat: add difference_posting_date field) "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Advance", diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py index 6d4bd4633c3..edfa42e5eb7 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py @@ -6,4 +6,29 @@ from frappe.model.document import Document class SalesInvoiceAdvance(Document): +<<<<<<< HEAD +======= + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + advance_amount: DF.Currency + allocated_amount: DF.Currency + difference_posting_date: DF.Date | None + exchange_gain_loss: DF.Currency + parent: DF.Data + parentfield: DF.Data + parenttype: DF.Data + ref_exchange_rate: DF.Float + reference_name: DF.DynamicLink | None + reference_row: DF.Data | None + reference_type: DF.Link | None + remarks: DF.Text | None + # end: auto-generated types + +>>>>>>> 225e56cbca (feat: add difference_posting_date field) pass From 0fdd6817a6e1c966244bfcac0cc348421ca2a156 Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 12:10:08 +0530 Subject: [PATCH 2/6] feat: use difference_posting_date for journal entry posting_date (cherry picked from commit ff1d040a6e1aa80c3b93835395db31a222dd5568) --- erpnext/controllers/accounts_controller.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index fa26fea3bf0..f2dab6beffc 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1082,6 +1082,7 @@ class AccountsController(TransactionBase): "advance_amount": flt(d.amount), "allocated_amount": allocated_amount, "ref_exchange_rate": flt(d.exchange_rate), # exchange_rate of advance entry + "difference_posting_date": self.posting_date, } self.append("advances", advance_row) @@ -1332,7 +1333,6 @@ class AccountsController(TransactionBase): gain_loss_account = frappe.get_cached_value( "Company", self.company, "exchange_gain_loss_account" ) - je = create_gain_loss_journal( self.company, args.get("difference_posting_date") if args else self.posting_date, @@ -1445,6 +1445,7 @@ class AccountsController(TransactionBase): "Company", self.company, "exchange_gain_loss_account" ), "exchange_gain_loss": flt(d.get("exchange_gain_loss")), + "difference_posting_date": d.get("difference_posting_date"), } ) lst.append(args) From 52309fe0b639b2beeb40a7b5a37dbfeefa2a3af9 Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 12:13:35 +0530 Subject: [PATCH 3/6] test: add unit test to validate journal entry posting date (cherry picked from commit c14a2d73bf10fd910e319bc62c2d8e117cce73f1) # Conflicts: # erpnext/controllers/tests/test_accounts_controller.py --- .../tests/test_accounts_controller.py | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index 4ada8e60d9b..029a5cb9659 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -2,6 +2,8 @@ # For license information, please see license.txt +from datetime import datetime + import frappe from frappe import qb from frappe.query_builder.functions import Sum @@ -1737,3 +1739,217 @@ class TestAccountsController(FrappeTestCase): # Exchange Gain/Loss Journal should've been cancelled exc_je_for_je1 = self.get_journals_for(je1.doctype, je1.name) self.assertEqual(exc_je_for_je1, []) +<<<<<<< HEAD +======= + + def test_70_advance_payment_against_sales_invoice_in_foreign_currency(self): + """ + Customer advance booked under Liability + """ + self.setup_advance_accounts_in_party_master() + + adv = self.create_payment_entry(amount=1, source_exc_rate=83) + adv.save() # explicit 'save' is needed to trigger set_liability_account() + self.assertEqual(adv.paid_from, self.advance_received_usd) + adv.submit() + + si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) + si.debit_to = self.debtors_usd + si.save().submit() + self.assert_ledger_outstanding(si.doctype, si.name, 80.0, 1.0) + + pr = self.create_payment_reconciliation() + pr.receivable_payable_account = self.debtors_usd + pr.default_advance_account = self.advance_received_usd + pr.get_unreconciled_entries() + self.assertEqual(pr.invoices[0].invoice_number, si.name) + self.assertEqual(pr.payments[0].reference_name, adv.name) + + # Allocate and Reconcile + 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.reconcile() + self.assertEqual(len(pr.invoices), 0) + self.assertEqual(len(pr.payments), 0) + self.assert_ledger_outstanding(si.doctype, si.name, 0.0, 0.0) + + # Exc Gain/Loss journal should've been creatad + exc_je_for_si = self.get_journals_for(si.doctype, si.name) + exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) + self.assertEqual(len(exc_je_for_si), 1) + self.assertEqual(len(exc_je_for_adv), 1) + self.assertEqual(exc_je_for_si, exc_je_for_adv) + + adv.reload() + adv.cancel() + si.reload() + self.assert_ledger_outstanding(si.doctype, si.name, 80.0, 1.0) + # Exc Gain/Loss journal should've been cancelled + exc_je_for_si = self.get_journals_for(si.doctype, si.name) + exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) + self.assertEqual(len(exc_je_for_si), 0) + self.assertEqual(len(exc_je_for_adv), 0) + + self.remove_advance_accounts_from_party_master() + + def test_71_advance_payment_against_purchase_invoice_in_foreign_currency(self): + """ + Supplier advance booked under Asset + """ + self.setup_advance_accounts_in_party_master() + + usd_amount = 1 + inr_amount = 85 + exc_rate = 85 + adv = create_payment_entry( + company=self.company, + payment_type="Pay", + party_type="Supplier", + party=self.supplier, + paid_from=self.cash, + paid_to=self.advance_paid_usd, + paid_amount=inr_amount, + ) + adv.source_exchange_rate = 1 + adv.target_exchange_rate = exc_rate + adv.received_amount = usd_amount + adv.paid_amount = exc_rate * usd_amount + adv.posting_date = nowdate() + adv.save() + # Make sure that advance account is still set + self.assertEqual(adv.paid_to, self.advance_paid_usd) + adv.submit() + + pi = self.create_purchase_invoice(qty=1, conversion_rate=83, rate=1) + self.assertEqual(pi.credit_to, self.creditors_usd) + self.assert_ledger_outstanding(pi.doctype, pi.name, 83.0, 1.0) + + pr = self.create_payment_reconciliation() + pr.party_type = "Supplier" + pr.party = self.supplier + pr.receivable_payable_account = self.creditors_usd + pr.default_advance_account = self.advance_paid_usd + pr.get_unreconciled_entries() + self.assertEqual(pr.invoices[0].invoice_number, pi.name) + self.assertEqual(pr.payments[0].reference_name, adv.name) + + # Allocate and Reconcile + 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.reconcile() + self.assertEqual(len(pr.invoices), 0) + self.assertEqual(len(pr.payments), 0) + self.assert_ledger_outstanding(pi.doctype, pi.name, 0.0, 0.0) + + # Exc Gain/Loss journal should've been creatad + exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name) + exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) + self.assertEqual(len(exc_je_for_pi), 1) + self.assertEqual(len(exc_je_for_adv), 1) + self.assertEqual(exc_je_for_pi, exc_je_for_adv) + + adv.reload() + adv.cancel() + pi.reload() + self.assert_ledger_outstanding(pi.doctype, pi.name, 83.0, 1.0) + # Exc Gain/Loss journal should've been cancelled + exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name) + exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) + self.assertEqual(len(exc_je_for_pi), 0) + self.assertEqual(len(exc_je_for_adv), 0) + + self.remove_advance_accounts_from_party_master() + + def test_difference_posting_date_in_pi_and_si(self): + self.setup_advance_accounts_in_party_master() + + # create payment entry for customer + adv = self.create_payment_entry(amount=1, source_exc_rate=83) + adv.save() + self.assertEqual(adv.paid_from, self.advance_received_usd) + adv.submit() + + # create sales invoice with advance received + si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) + si.debit_to = self.debtors_usd + si.append( + "advances", + { + "reference_type": "Payment Entry", + "reference_name": "ACC-PAY-2024-00001", + "remarks": "Amount INR 1 received from _Test MC Customer USD\nTransaction reference no Test001 dated 2024-12-19", + "advance_amount": 1.0, + "allocated_amount": 1.0, + "exchange_gain_loss": 3.0, + "ref_exchange_rate": 83.0, + "difference_posting_date": add_days(nowdate(), -2), + }, + ) + si.save().submit() + + # exc Gain/Loss journal should've been creatad + exc_je_for_si = self.get_journals_for(si.doctype, si.name) + exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) + self.assertEqual(len(exc_je_for_si), 1) + self.assertEqual(len(exc_je_for_adv), 1) + self.assertEqual(exc_je_for_si, exc_je_for_adv) + + # check jv created with difference_posting_date in sales invoice + jv = frappe.get_doc("Journal Entry", exc_je_for_si[0].parent) + sales_invoice = frappe.get_doc("Sales Invoice", si.name) + self.assertEqual(sales_invoice.advances[0].difference_posting_date, jv.posting_date) + + # create payment entry for supplier + usd_amount = 1 + inr_amount = 85 + exc_rate = 85 + adv = create_payment_entry( + company=self.company, + payment_type="Pay", + party_type="Supplier", + party=self.supplier, + paid_from=self.cash, + paid_to=self.advance_paid_usd, + paid_amount=inr_amount, + ) + adv.source_exchange_rate = 1 + adv.target_exchange_rate = exc_rate + adv.received_amount = usd_amount + adv.paid_amount = exc_rate * usd_amount + adv.posting_date = nowdate() + adv.save() + self.assertEqual(adv.paid_to, self.advance_paid_usd) + adv.submit() + + # create purchase invoice with advance paid + pi = self.create_purchase_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) + pi.append( + "advances", + { + "reference_type": "Payment Entry", + "reference_name": "ACC-PAY-2024-00002", + "remarks": "Amount INR 1 paid to _Test MC Supplier USD\nTransaction reference no Test001 dated 2024-12-20", + "advance_amount": 1.0, + "allocated_amount": 1.0, + "exchange_gain_loss": 5.0, + "ref_exchange_rate": 85.0, + "difference_posting_date": add_days(nowdate(), -2), + }, + ) + pi.save().submit() + self.assertEqual(pi.credit_to, self.creditors_usd) + + # exc Gain/Loss journal should've been creatad + exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name) + exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) + self.assertEqual(len(exc_je_for_pi), 1) + self.assertEqual(len(exc_je_for_adv), 1) + self.assertEqual(exc_je_for_pi, exc_je_for_adv) + + # check jv created with difference_posting_date in purchase invoice + journal_voucher = frappe.get_doc("Journal Entry", exc_je_for_pi[0].parent) + purchase_invoice = frappe.get_doc("Purchase Invoice", pi.name) + self.assertEqual(purchase_invoice.advances[0].difference_posting_date, journal_voucher.posting_date) +>>>>>>> c14a2d73bf (test: add unit test to validate journal entry posting date) From 33a1da8194ca6d471373c81bcec9510bd4a5780b Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 12:42:47 +0530 Subject: [PATCH 4/6] refactor: convert sql query to query builder (cherry picked from commit 2d58e845e633943bae2d481f66d200b16ab91bdf) --- erpnext/controllers/accounts_controller.py | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index f2dab6beffc..e3d5ebf7fa1 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -346,13 +346,14 @@ class AccountsController(TransactionBase): == 1 ) ).run() - frappe.db.sql( - "delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s", (self.doctype, self.name) - ) - frappe.db.sql( - "delete from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s", - (self.doctype, self.name), - ) + gle = frappe.qb.DocType("GL Entry") + frappe.qb.from_(gle).delete().where( + (gle.voucher_type == self.doctype) & (gle.voucher_no == self.name) + ).run() + sle = frappe.qb.DocType("Stock Ledger Entry") + frappe.qb.from_(gle).delete().where( + (sle.voucher_type == self.doctype) & (sle.voucher_no == self.name) + ).run() def validate_return_against_account(self): if self.doctype in ["Sales Invoice", "Purchase Invoice"] and self.is_return and self.return_against: @@ -1027,11 +1028,12 @@ class AccountsController(TransactionBase): def clear_unallocated_advances(self, childtype, parentfield): self.set(parentfield, self.get(parentfield, {"allocated_amount": ["not in", [0, None, ""]]})) - frappe.db.sql( - """delete from `tab{}` where parentfield={} and parent = {} - and allocated_amount = 0""".format(childtype, "%s", "%s"), - (parentfield, self.name), - ) + doctype = frappe.qb.DocType(childtype) + frappe.qb.from_(doctype).delete().where( + (doctype.parentfield == parentfield) + & (doctype.parent == self.name) + & (doctype.allocated_amount == 0) + ).run() @frappe.whitelist() def apply_shipping_rule(self): @@ -1972,11 +1974,9 @@ class AccountsController(TransactionBase): for adv in self.advances: consider_for_total_advance = True if adv.reference_name == linked_doc_name: - frappe.db.sql( - f"""delete from `tab{self.doctype} Advance` - where name = %s""", - adv.name, - ) + doctype = frappe.qb.DocType(self.doctype + " Advance") + frappe.qb.from_(doctype).delete().where(doctype.name == adv.name).run() + consider_for_total_advance = False if consider_for_total_advance: From 49e3865265477a718564c6c92ff6be5c8b472fed Mon Sep 17 00:00:00 2001 From: rs-rethik Date: Fri, 20 Dec 2024 14:00:54 +0530 Subject: [PATCH 5/6] fix: update query (cherry picked from commit 854e37c05c454ad2d93ec0f4a70600f2ca7d5eec) --- erpnext/controllers/accounts_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index e3d5ebf7fa1..ecbf1177ee4 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -351,7 +351,7 @@ class AccountsController(TransactionBase): (gle.voucher_type == self.doctype) & (gle.voucher_no == self.name) ).run() sle = frappe.qb.DocType("Stock Ledger Entry") - frappe.qb.from_(gle).delete().where( + frappe.qb.from_(sle).delete().where( (sle.voucher_type == self.doctype) & (sle.voucher_no == self.name) ).run() From 8764a321c73c124019dbfde72aa43efc32424fe6 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 21 Jan 2025 12:57:10 +0530 Subject: [PATCH 6/6] chore: resolve conflicts --- .../purchase_invoice_advance.json | 4 - .../purchase_invoice_advance.py | 25 -- .../sales_invoice_advance.json | 4 - .../sales_invoice_advance.py | 25 -- .../tests/test_accounts_controller.py | 214 ------------------ 5 files changed, 272 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json index 2f6d30c0922..ebd309bfb67 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json @@ -125,11 +125,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], -<<<<<<< HEAD - "modified": "2021-09-26 15:47:28.167371", -======= "modified": "2024-12-20 12:04:46.729972", ->>>>>>> 225e56cbca (feat: add difference_posting_date field) "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Advance", diff --git a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py index 6f8971c12f4..44e1f6d5685 100644 --- a/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py +++ b/erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.py @@ -6,29 +6,4 @@ from frappe.model.document import Document class PurchaseInvoiceAdvance(Document): -<<<<<<< HEAD -======= - # begin: auto-generated types - # This code is auto-generated. Do not modify anything in this block. - - from typing import TYPE_CHECKING - - if TYPE_CHECKING: - from frappe.types import DF - - advance_amount: DF.Currency - allocated_amount: DF.Currency - difference_posting_date: DF.Date | None - exchange_gain_loss: DF.Currency - parent: DF.Data - parentfield: DF.Data - parenttype: DF.Data - ref_exchange_rate: DF.Float - reference_name: DF.DynamicLink | None - reference_row: DF.Data | None - reference_type: DF.Link | None - remarks: DF.Text | None - # end: auto-generated types - ->>>>>>> 225e56cbca (feat: add difference_posting_date field) pass diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json index 19336f84342..d4e3b9d896c 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json @@ -126,11 +126,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], -<<<<<<< HEAD - "modified": "2021-09-26 15:47:46.911595", -======= "modified": "2024-12-20 11:58:28.962370", ->>>>>>> 225e56cbca (feat: add difference_posting_date field) "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Advance", diff --git a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py index edfa42e5eb7..6d4bd4633c3 100644 --- a/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py +++ b/erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.py @@ -6,29 +6,4 @@ from frappe.model.document import Document class SalesInvoiceAdvance(Document): -<<<<<<< HEAD -======= - # begin: auto-generated types - # This code is auto-generated. Do not modify anything in this block. - - from typing import TYPE_CHECKING - - if TYPE_CHECKING: - from frappe.types import DF - - advance_amount: DF.Currency - allocated_amount: DF.Currency - difference_posting_date: DF.Date | None - exchange_gain_loss: DF.Currency - parent: DF.Data - parentfield: DF.Data - parenttype: DF.Data - ref_exchange_rate: DF.Float - reference_name: DF.DynamicLink | None - reference_row: DF.Data | None - reference_type: DF.Link | None - remarks: DF.Text | None - # end: auto-generated types - ->>>>>>> 225e56cbca (feat: add difference_posting_date field) pass diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py index 029a5cb9659..a184009b1e1 100644 --- a/erpnext/controllers/tests/test_accounts_controller.py +++ b/erpnext/controllers/tests/test_accounts_controller.py @@ -1739,217 +1739,3 @@ class TestAccountsController(FrappeTestCase): # Exchange Gain/Loss Journal should've been cancelled exc_je_for_je1 = self.get_journals_for(je1.doctype, je1.name) self.assertEqual(exc_je_for_je1, []) -<<<<<<< HEAD -======= - - def test_70_advance_payment_against_sales_invoice_in_foreign_currency(self): - """ - Customer advance booked under Liability - """ - self.setup_advance_accounts_in_party_master() - - adv = self.create_payment_entry(amount=1, source_exc_rate=83) - adv.save() # explicit 'save' is needed to trigger set_liability_account() - self.assertEqual(adv.paid_from, self.advance_received_usd) - adv.submit() - - si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) - si.debit_to = self.debtors_usd - si.save().submit() - self.assert_ledger_outstanding(si.doctype, si.name, 80.0, 1.0) - - pr = self.create_payment_reconciliation() - pr.receivable_payable_account = self.debtors_usd - pr.default_advance_account = self.advance_received_usd - pr.get_unreconciled_entries() - self.assertEqual(pr.invoices[0].invoice_number, si.name) - self.assertEqual(pr.payments[0].reference_name, adv.name) - - # Allocate and Reconcile - 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.reconcile() - self.assertEqual(len(pr.invoices), 0) - self.assertEqual(len(pr.payments), 0) - self.assert_ledger_outstanding(si.doctype, si.name, 0.0, 0.0) - - # Exc Gain/Loss journal should've been creatad - exc_je_for_si = self.get_journals_for(si.doctype, si.name) - exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) - self.assertEqual(len(exc_je_for_si), 1) - self.assertEqual(len(exc_je_for_adv), 1) - self.assertEqual(exc_je_for_si, exc_je_for_adv) - - adv.reload() - adv.cancel() - si.reload() - self.assert_ledger_outstanding(si.doctype, si.name, 80.0, 1.0) - # Exc Gain/Loss journal should've been cancelled - exc_je_for_si = self.get_journals_for(si.doctype, si.name) - exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) - self.assertEqual(len(exc_je_for_si), 0) - self.assertEqual(len(exc_je_for_adv), 0) - - self.remove_advance_accounts_from_party_master() - - def test_71_advance_payment_against_purchase_invoice_in_foreign_currency(self): - """ - Supplier advance booked under Asset - """ - self.setup_advance_accounts_in_party_master() - - usd_amount = 1 - inr_amount = 85 - exc_rate = 85 - adv = create_payment_entry( - company=self.company, - payment_type="Pay", - party_type="Supplier", - party=self.supplier, - paid_from=self.cash, - paid_to=self.advance_paid_usd, - paid_amount=inr_amount, - ) - adv.source_exchange_rate = 1 - adv.target_exchange_rate = exc_rate - adv.received_amount = usd_amount - adv.paid_amount = exc_rate * usd_amount - adv.posting_date = nowdate() - adv.save() - # Make sure that advance account is still set - self.assertEqual(adv.paid_to, self.advance_paid_usd) - adv.submit() - - pi = self.create_purchase_invoice(qty=1, conversion_rate=83, rate=1) - self.assertEqual(pi.credit_to, self.creditors_usd) - self.assert_ledger_outstanding(pi.doctype, pi.name, 83.0, 1.0) - - pr = self.create_payment_reconciliation() - pr.party_type = "Supplier" - pr.party = self.supplier - pr.receivable_payable_account = self.creditors_usd - pr.default_advance_account = self.advance_paid_usd - pr.get_unreconciled_entries() - self.assertEqual(pr.invoices[0].invoice_number, pi.name) - self.assertEqual(pr.payments[0].reference_name, adv.name) - - # Allocate and Reconcile - 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.reconcile() - self.assertEqual(len(pr.invoices), 0) - self.assertEqual(len(pr.payments), 0) - self.assert_ledger_outstanding(pi.doctype, pi.name, 0.0, 0.0) - - # Exc Gain/Loss journal should've been creatad - exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name) - exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) - self.assertEqual(len(exc_je_for_pi), 1) - self.assertEqual(len(exc_je_for_adv), 1) - self.assertEqual(exc_je_for_pi, exc_je_for_adv) - - adv.reload() - adv.cancel() - pi.reload() - self.assert_ledger_outstanding(pi.doctype, pi.name, 83.0, 1.0) - # Exc Gain/Loss journal should've been cancelled - exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name) - exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) - self.assertEqual(len(exc_je_for_pi), 0) - self.assertEqual(len(exc_je_for_adv), 0) - - self.remove_advance_accounts_from_party_master() - - def test_difference_posting_date_in_pi_and_si(self): - self.setup_advance_accounts_in_party_master() - - # create payment entry for customer - adv = self.create_payment_entry(amount=1, source_exc_rate=83) - adv.save() - self.assertEqual(adv.paid_from, self.advance_received_usd) - adv.submit() - - # create sales invoice with advance received - si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) - si.debit_to = self.debtors_usd - si.append( - "advances", - { - "reference_type": "Payment Entry", - "reference_name": "ACC-PAY-2024-00001", - "remarks": "Amount INR 1 received from _Test MC Customer USD\nTransaction reference no Test001 dated 2024-12-19", - "advance_amount": 1.0, - "allocated_amount": 1.0, - "exchange_gain_loss": 3.0, - "ref_exchange_rate": 83.0, - "difference_posting_date": add_days(nowdate(), -2), - }, - ) - si.save().submit() - - # exc Gain/Loss journal should've been creatad - exc_je_for_si = self.get_journals_for(si.doctype, si.name) - exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) - self.assertEqual(len(exc_je_for_si), 1) - self.assertEqual(len(exc_je_for_adv), 1) - self.assertEqual(exc_je_for_si, exc_je_for_adv) - - # check jv created with difference_posting_date in sales invoice - jv = frappe.get_doc("Journal Entry", exc_je_for_si[0].parent) - sales_invoice = frappe.get_doc("Sales Invoice", si.name) - self.assertEqual(sales_invoice.advances[0].difference_posting_date, jv.posting_date) - - # create payment entry for supplier - usd_amount = 1 - inr_amount = 85 - exc_rate = 85 - adv = create_payment_entry( - company=self.company, - payment_type="Pay", - party_type="Supplier", - party=self.supplier, - paid_from=self.cash, - paid_to=self.advance_paid_usd, - paid_amount=inr_amount, - ) - adv.source_exchange_rate = 1 - adv.target_exchange_rate = exc_rate - adv.received_amount = usd_amount - adv.paid_amount = exc_rate * usd_amount - adv.posting_date = nowdate() - adv.save() - self.assertEqual(adv.paid_to, self.advance_paid_usd) - adv.submit() - - # create purchase invoice with advance paid - pi = self.create_purchase_invoice(qty=1, conversion_rate=80, rate=1, do_not_submit=True) - pi.append( - "advances", - { - "reference_type": "Payment Entry", - "reference_name": "ACC-PAY-2024-00002", - "remarks": "Amount INR 1 paid to _Test MC Supplier USD\nTransaction reference no Test001 dated 2024-12-20", - "advance_amount": 1.0, - "allocated_amount": 1.0, - "exchange_gain_loss": 5.0, - "ref_exchange_rate": 85.0, - "difference_posting_date": add_days(nowdate(), -2), - }, - ) - pi.save().submit() - self.assertEqual(pi.credit_to, self.creditors_usd) - - # exc Gain/Loss journal should've been creatad - exc_je_for_pi = self.get_journals_for(pi.doctype, pi.name) - exc_je_for_adv = self.get_journals_for(adv.doctype, adv.name) - self.assertEqual(len(exc_je_for_pi), 1) - self.assertEqual(len(exc_je_for_adv), 1) - self.assertEqual(exc_je_for_pi, exc_je_for_adv) - - # check jv created with difference_posting_date in purchase invoice - journal_voucher = frappe.get_doc("Journal Entry", exc_je_for_pi[0].parent) - purchase_invoice = frappe.get_doc("Purchase Invoice", pi.name) - self.assertEqual(purchase_invoice.advances[0].difference_posting_date, journal_voucher.posting_date) ->>>>>>> c14a2d73bf (test: add unit test to validate journal entry posting date)