From 3e59c668064c037548c7c29c4d944efbcb37ff7b Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 26 Jan 2024 21:46:19 +0530 Subject: [PATCH 01/13] fix: provisional reverse entry amount --- .../doctype/purchase_invoice/purchase_invoice.py | 6 +++--- .../stock/doctype/purchase_receipt/purchase_receipt.py | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index c4e09b47f15..4b1641e20f4 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1025,7 +1025,7 @@ class PurchaseInvoice(BuyingController): purchase_receipt_doc_map[item.purchase_receipt] = purchase_receipt_doc # Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt - expense_booked_in_pr = frappe.db.get_value( + expense_booked_in_pr, credit = frappe.db.get_value( "GL Entry", { "is_cancelled": 0, @@ -1034,13 +1034,13 @@ class PurchaseInvoice(BuyingController): "voucher_detail_no": item.pr_detail, "account": provisional_account, }, - ["name"], + ["name", "credit"], ) if expense_booked_in_pr: # Intentionally passing purchase invoice item to handle partial billing purchase_receipt_doc.add_provisional_gl_entry( - item, gl_entries, self.posting_date, provisional_account, reverse=1 + item, gl_entries, self.posting_date, provisional_account, reverse=1, item_amount=credit ) if not self.is_internal_transfer(): diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index bf6080bf236..360b911aded 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -730,16 +730,19 @@ class PurchaseReceipt(BuyingController): ) def add_provisional_gl_entry( - self, item, gl_entries, posting_date, provisional_account, reverse=0 + self, item, gl_entries, posting_date, provisional_account, reverse=0, item_amount=None ): credit_currency = get_account_currency(provisional_account) expense_account = item.expense_account debit_currency = get_account_currency(item.expense_account) remarks = self.get("remarks") or _("Accounting Entry for Service") multiplication_factor = 1 + amount = item.base_amount if reverse: multiplication_factor = -1 + # Post reverse entry for previously posted amount + amount = item_amount expense_account = frappe.db.get_value( "Purchase Receipt Item", {"name": item.get("pr_detail")}, ["expense_account"] ) @@ -749,7 +752,7 @@ class PurchaseReceipt(BuyingController): account=provisional_account, cost_center=item.cost_center, debit=0.0, - credit=multiplication_factor * item.base_amount, + credit=multiplication_factor * amount, remarks=remarks, against_account=expense_account, account_currency=credit_currency, @@ -763,7 +766,7 @@ class PurchaseReceipt(BuyingController): gl_entries=gl_entries, account=expense_account, cost_center=item.cost_center, - debit=multiplication_factor * item.base_amount, + debit=multiplication_factor * amount, credit=0.0, remarks=remarks, against_account=provisional_account, From 2a46799188a0267d76bdd292062f5a5f82429493 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 29 Jan 2024 11:34:06 +0530 Subject: [PATCH 02/13] fix: handle partial invoice against provisional entry --- .../purchase_invoice/purchase_invoice.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 4b1641e20f4..313d21272a1 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1015,9 +1015,12 @@ class PurchaseInvoice(BuyingController): if provisional_accounting_for_non_stock_items: if item.purchase_receipt: - provisional_account = frappe.db.get_value( - "Purchase Receipt Item", item.pr_detail, "provisional_expense_account" - ) or self.get_company_default("default_provisional_account") + provisional_account, pr_base_rate = frappe.get_cached_value( + "Purchase Receipt Item", item.pr_detail, ["provisional_expense_account", "base_rate"] + ) + provisional_account = provisional_account or self.get_company_default( + "default_provisional_account" + ) purchase_receipt_doc = purchase_receipt_doc_map.get(item.purchase_receipt) if not purchase_receipt_doc: @@ -1025,7 +1028,7 @@ class PurchaseInvoice(BuyingController): purchase_receipt_doc_map[item.purchase_receipt] = purchase_receipt_doc # Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt - expense_booked_in_pr, credit = frappe.db.get_value( + expense_booked_in_pr = frappe.db.get_value( "GL Entry", { "is_cancelled": 0, @@ -1034,13 +1037,18 @@ class PurchaseInvoice(BuyingController): "voucher_detail_no": item.pr_detail, "account": provisional_account, }, - ["name", "credit"], + "name", ) if expense_booked_in_pr: # Intentionally passing purchase invoice item to handle partial billing purchase_receipt_doc.add_provisional_gl_entry( - item, gl_entries, self.posting_date, provisional_account, reverse=1, item_amount=credit + item, + gl_entries, + self.posting_date, + provisional_account, + reverse=1, + item_amount=(item.qty * pr_base_rate), ) if not self.is_internal_transfer(): From f7face43cdcc9ef4e9d7a8cd90b0de8fc567d4e3 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 2 Feb 2024 21:57:45 +0530 Subject: [PATCH 03/13] fix: check payments against orders for getting request amount --- .../payment_request/payment_request.py | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index a18104eeb54..164918373b9 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -3,6 +3,7 @@ import json import frappe from frappe import _ from frappe.model.document import Document +from frappe.query_builder.functions import Sum from frappe.utils import flt, nowdate from frappe.utils.background_jobs import enqueue @@ -106,6 +107,8 @@ class PaymentRequest(Document): ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) if not hasattr(ref_doc, "order_type") or getattr(ref_doc, "order_type") != "Shopping Cart": ref_amount = get_amount(ref_doc, self.payment_account) + if not ref_amount: + frappe.throw(_("Payment Entry is already created")) if existing_payment_request_amount + flt(self.grand_total) > ref_amount: frappe.throw( @@ -453,6 +456,8 @@ def make_payment_request(**args): gateway_account = get_gateway_details(args) or frappe._dict() grand_total = get_amount(ref_doc, gateway_account.get("payment_account")) + if not grand_total: + frappe.throw(_("Payment Entry is already created")) if args.loyalty_points and args.dt == "Sales Order": from erpnext.accounts.doctype.loyalty_program.loyalty_program import validate_loyalty_points @@ -543,6 +548,7 @@ def get_amount(ref_doc, payment_account=None): dt = ref_doc.doctype if dt in ["Sales Order", "Purchase Order"]: grand_total = flt(ref_doc.rounded_total) or flt(ref_doc.grand_total) + grand_total -= get_paid_amount_against_order(dt, ref_doc.name) elif dt in ["Sales Invoice", "Purchase Invoice"]: if not ref_doc.get("is_pos"): if ref_doc.party_account_currency == ref_doc.currency: @@ -562,10 +568,7 @@ def get_amount(ref_doc, payment_account=None): elif dt == "Fees": grand_total = ref_doc.outstanding_amount - if grand_total > 0: - return grand_total - else: - frappe.throw(_("Payment Entry is already created")) + return grand_total def get_existing_payment_request_amount(ref_dt, ref_dn): @@ -748,3 +751,27 @@ def validate_payment(doc, method=None): doc.reference_docname ) ) + + +def get_paid_amount_against_order(dt, dn): + pe_ref = frappe.qb.DocType("Payment Entry Reference") + if dt == "Sales Order": + inv_dt, inv_field = "Sales Invoice Item", "sales_order" + else: + inv_dt, inv_field = "Purchase Invoice Item", "purchase_order" + inv_item = frappe.qb.DocType(inv_dt) + return ( + frappe.qb.from_(pe_ref) + .select( + Sum(pe_ref.allocated_amount), + ) + .where( + (pe_ref.docstatus == 1) + & ( + (pe_ref.reference_name == dn) + | pe_ref.reference_name.isin( + frappe.qb.from_(inv_item).select(inv_item.parent).where(inv_item[inv_field] == dn).distinct() + ) + ) + ) + ).run()[0][0] or 0 From c18ff5bd253878da2f71690f194e8fedd07b2a87 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 2 Feb 2024 21:59:53 +0530 Subject: [PATCH 04/13] fix(portal): payment amount for orders --- erpnext/templates/pages/order.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py index 21d4b860d1f..41b13845239 100644 --- a/erpnext/templates/pages/order.py +++ b/erpnext/templates/pages/order.py @@ -4,6 +4,8 @@ import frappe from frappe import _ +from erpnext.accounts.doctype.payment_request.payment_request import get_amount + def get_context(context): context.no_cache = 1 @@ -48,10 +50,7 @@ def get_context(context): ) context.available_loyalty_points = int(loyalty_program_details.get("loyalty_points")) - context.show_pay_button = ( - "payments" in frappe.get_installed_apps() - and frappe.db.get_single_value("Buying Settings", "show_pay_button") - ) + context.show_pay_button, context.pay_amount = get_payment_details(context.doc) context.show_make_pi_button = False if context.doc.get("supplier"): # show Make Purchase Invoice button based on permission @@ -64,3 +63,14 @@ def get_attachments(dt, dn): fields=["name", "file_name", "file_url", "is_private"], filters={"attached_to_name": dn, "attached_to_doctype": dt, "is_private": 0}, ) + + +def get_payment_details(doc): + show_pay_button, amount = ( + "payments" in frappe.get_installed_apps() + and frappe.db.get_single_value("Buying Settings", "show_pay_button") + ), 0 + if not show_pay_button: + return show_pay_button, amount + amount = get_amount(doc) + return bool(amount), amount From 7efb5a8cb5d581d2ddfcc728f600bf5ba9649ad5 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 2 Feb 2024 22:01:42 +0530 Subject: [PATCH 05/13] fix(portal): context pay_amount for button --- erpnext/templates/pages/order.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html index 6c59a9688dc..97269dcf639 100644 --- a/erpnext/templates/pages/order.html +++ b/erpnext/templates/pages/order.html @@ -40,7 +40,7 @@

- {{ _("Pay") }} {{doc.get_formatted("grand_total") }} + {{ _("Pay") }} {{ pay_amount }}

From cc96d2b50cbce3c137eebd754956344718cd1771 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 5 Feb 2024 15:52:46 +0530 Subject: [PATCH 06/13] fix: over billing qty along with rate --- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 313d21272a1..f2a111acbac 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1015,8 +1015,10 @@ class PurchaseInvoice(BuyingController): if provisional_accounting_for_non_stock_items: if item.purchase_receipt: - provisional_account, pr_base_rate = frappe.get_cached_value( - "Purchase Receipt Item", item.pr_detail, ["provisional_expense_account", "base_rate"] + provisional_account, pr_qty, pr_base_rate = frappe.get_cached_value( + "Purchase Receipt Item", + item.pr_detail, + ["provisional_expense_account", "qty", "base_rate"], ) provisional_account = provisional_account or self.get_company_default( "default_provisional_account" @@ -1048,7 +1050,7 @@ class PurchaseInvoice(BuyingController): self.posting_date, provisional_account, reverse=1, - item_amount=(item.qty * pr_base_rate), + item_amount=(min(item.qty, pr_qty) * pr_base_rate), ) if not self.is_internal_transfer(): From ff3ca50a4b1787cd557dffefda4997a7f20cd643 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 5 Feb 2024 15:55:17 +0530 Subject: [PATCH 07/13] test: overbilling for provisional accounting --- .../purchase_invoice/test_purchase_invoice.py | 89 ++++++++++++++++--- 1 file changed, 75 insertions(+), 14 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 992fbe6e02c..a5611233999 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1539,18 +1539,7 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin): self.assertEqual(payment_entry.taxes[0].allocated_amount, 0) def test_provisional_accounting_entry(self): - create_item("_Test Non Stock Item", is_stock_item=0) - - provisional_account = create_account( - account_name="Provision Account", - parent_account="Current Liabilities - _TC", - company="_Test Company", - ) - - company = frappe.get_doc("Company", "_Test Company") - company.enable_provisional_accounting_for_non_stock_items = 1 - company.default_provisional_account = provisional_account - company.save() + setup_provisional_accounting() pr = make_purchase_receipt( item_code="_Test Non Stock Item", posting_date=add_days(nowdate(), -2) @@ -1594,8 +1583,58 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin): self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date ) - company.enable_provisional_accounting_for_non_stock_items = 0 - company.save() + toggle_provisional_accounting_setting() + + def test_provisional_accounting_entry_for_over_billing(self): + setup_provisional_accounting() + + # Configure Buying Settings to allow rate change + frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) + + # Create PR: rate = 1000, qty = 5 + pr = make_purchase_receipt( + item_code="_Test Non Stock Item", rate=1000, posting_date=add_days(nowdate(), -2) + ) + + # Overbill PR: rate = 2000, qty = 10 + pi = create_purchase_invoice_from_receipt(pr.name) + pi.set_posting_time = 1 + pi.posting_date = add_days(pr.posting_date, -1) + pi.items[0].qty = 10 + pi.items[0].rate = 2000 + pi.items[0].expense_account = "Cost of Goods Sold - _TC" + pi.save() + pi.submit() + + expected_gle = [ + ["Cost of Goods Sold - _TC", 20000, 0, add_days(pr.posting_date, -1)], + ["Creditors - _TC", 0, 20000, add_days(pr.posting_date, -1)], + ] + + check_gl_entries(self, pi.name, expected_gle, pi.posting_date) + + expected_gle_for_purchase_receipt = [ + ["Provision Account - _TC", 5000, 0, pr.posting_date], + ["_Test Account Cost for Goods Sold - _TC", 0, 5000, pr.posting_date], + ["Provision Account - _TC", 0, 5000, pi.posting_date], + ["_Test Account Cost for Goods Sold - _TC", 5000, 0, pi.posting_date], + ] + + check_gl_entries(self, pr.name, expected_gle_for_purchase_receipt, pr.posting_date) + + # Cancel purchase invoice to check reverse provisional entry cancellation + pi.cancel() + + expected_gle_for_purchase_receipt_post_pi_cancel = [ + ["Provision Account - _TC", 0, 5000, pi.posting_date], + ["_Test Account Cost for Goods Sold - _TC", 5000, 0, pi.posting_date], + ] + + check_gl_entries( + self, pr.name, expected_gle_for_purchase_receipt_post_pi_cancel, pr.posting_date + ) + + toggle_provisional_accounting_setting() def test_adjust_incoming_rate(self): frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) @@ -2259,4 +2298,26 @@ def make_purchase_invoice_against_cost_center(**args): return pi +def setup_provisional_accounting(**args): + args = frappe._dict(args) + create_item("_Test Non Stock Item", is_stock_item=0) + company = args.company or "_Test Company" + provisional_account = create_account( + account_name=args.account_name or "Provision Account", + parent_account=args.parent_account or "Current Liabilities - _TC", + company=company, + ) + toggle_provisional_accounting_setting( + enable=1, company=company, provisional_account=provisional_account + ) + + +def toggle_provisional_accounting_setting(**args): + args = frappe._dict(args) + company = frappe.get_doc("Company", args.company or "_Test Company") + company.enable_provisional_accounting_for_non_stock_items = args.enable or 0 + company.default_provisional_account = args.provisional_account + company.save() + + test_records = frappe.get_test_records("Purchase Invoice") From c5770f2eccc62c27f18a108ad60ae4f42946a9d6 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 5 Feb 2024 15:58:06 +0530 Subject: [PATCH 08/13] test: partial billing for provisional accounting --- .../purchase_invoice/test_purchase_invoice.py | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index a5611233999..43f01ab62db 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1636,6 +1636,45 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin): toggle_provisional_accounting_setting() + def test_provisional_accounting_entry_for_partial_billing(self): + setup_provisional_accounting() + + # Configure Buying Settings to allow rate change + frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) + + # Create PR: rate = 1000, qty = 5 + pr = make_purchase_receipt( + item_code="_Test Non Stock Item", rate=1000, posting_date=add_days(nowdate(), -2) + ) + + # Partially bill PR: rate = 500, qty = 2 + pi = create_purchase_invoice_from_receipt(pr.name) + pi.set_posting_time = 1 + pi.posting_date = add_days(pr.posting_date, -1) + pi.items[0].qty = 2 + pi.items[0].rate = 500 + pi.items[0].expense_account = "Cost of Goods Sold - _TC" + pi.save() + pi.submit() + + expected_gle = [ + ["Cost of Goods Sold - _TC", 1000, 0, add_days(pr.posting_date, -1)], + ["Creditors - _TC", 0, 1000, add_days(pr.posting_date, -1)], + ] + + check_gl_entries(self, pi.name, expected_gle, pi.posting_date) + + expected_gle_for_purchase_receipt = [ + ["Provision Account - _TC", 5000, 0, pr.posting_date], + ["_Test Account Cost for Goods Sold - _TC", 0, 5000, pr.posting_date], + ["Provision Account - _TC", 0, 1000, pi.posting_date], + ["_Test Account Cost for Goods Sold - _TC", 1000, 0, pi.posting_date], + ] + + check_gl_entries(self, pr.name, expected_gle_for_purchase_receipt, pr.posting_date) + + toggle_provisional_accounting_setting() + def test_adjust_incoming_rate(self): frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0) From 0b3ecd24e21ec1f2ba490cf10d880bcdb6ec584a Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Fri, 16 Feb 2024 16:29:40 +0100 Subject: [PATCH 09/13] feat: pass doctype as context when translating label --- .../print_format/sales_invoice_return/sales_invoice_return.html | 2 +- .../doctype/item_variant_settings/item_variant_settings.js | 2 +- erpnext/templates/form_grid/includes/visible_cols.html | 2 +- erpnext/templates/print_formats/includes/total.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html index 3d5a9b1da94..e1771247e88 100644 --- a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html +++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html @@ -5,7 +5,7 @@
- +
{% if doc.get(df.fieldname) != None -%} diff --git a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.js b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.js index 058783c4ae3..457e48fdaf9 100644 --- a/erpnext/stock/doctype/item_variant_settings/item_variant_settings.js +++ b/erpnext/stock/doctype/item_variant_settings/item_variant_settings.js @@ -15,7 +15,7 @@ frappe.ui.form.on('Item Variant Settings', { frappe.model.with_doctype('Item', () => { const field_label_map = {}; frappe.get_meta('Item').fields.forEach(d => { - field_label_map[d.fieldname] = __(d.label) + ` (${d.fieldname})`; + field_label_map[d.fieldname] = __(d.label, null, d.parent) + ` (${d.fieldname})`; if (!in_list(exclude_field_types, d.fieldtype) && !d.no_copy && !in_list(exclude_fields, d.fieldname)) { diff --git a/erpnext/templates/form_grid/includes/visible_cols.html b/erpnext/templates/form_grid/includes/visible_cols.html index 3a0cc8d7239..8d79bcdf879 100644 --- a/erpnext/templates/form_grid/includes/visible_cols.html +++ b/erpnext/templates/form_grid/includes/visible_cols.html @@ -3,7 +3,7 @@ if((df.fieldname !== "description" && df.fieldname !== "item_name") && val) { %}
- {%= __(df.label) %}: + {%= __(df.label, null, df.parent) %}:
{%= doc.get_formatted(df.fieldname) %} diff --git a/erpnext/templates/print_formats/includes/total.html b/erpnext/templates/print_formats/includes/total.html index 879203bbf25..66d48b2d182 100644 --- a/erpnext/templates/print_formats/includes/total.html +++ b/erpnext/templates/print_formats/includes/total.html @@ -7,7 +7,7 @@
{% else %}
-
+
{{ doc.get_formatted("total", doc) }}
From 3327599c9d5f27b10668b9e6fbef72acdcb6d5f0 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 29 Feb 2024 17:18:42 +0530 Subject: [PATCH 10/13] fix: include Debit To/Credit To account while fetching advance --- erpnext/controllers/accounts_controller.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 063c1e353f0..fbc3a8986d9 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1128,21 +1128,24 @@ class AccountsController(TransactionBase): self.append("advances", advance_row) def get_advance_entries(self, include_unallocated=True): + party_account = [] if self.doctype == "Sales Invoice": party_type = "Customer" party = self.customer amount_field = "credit_in_account_currency" order_field = "sales_order" order_doctype = "Sales Order" + party_account.append(self.debit_to) else: party_type = "Supplier" party = self.supplier amount_field = "debit_in_account_currency" order_field = "purchase_order" order_doctype = "Purchase Order" + party_account.append(self.credit_to) - party_account = get_party_account( - party_type, party=party, company=self.company, include_advance=True + party_account.extend( + get_party_account(party_type, party=party, company=self.company, include_advance=True) ) order_list = list(set(d.get(order_field) for d in self.get("items") if d.get(order_field))) From 646e9ca0dd484b65d4f3bbe674b63760f8e3d5ce Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 29 Feb 2024 17:31:08 +0530 Subject: [PATCH 11/13] test: advance pulling logic on Sales/Purchase Invoice --- .../sales_invoice/test_sales_invoice.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 8c3aedebcdf..6da92443019 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3577,6 +3577,33 @@ class TestSalesInvoice(FrappeTestCase): check_gl_entries(self, pe.name, expected_gle, nowdate(), voucher_type="Payment Entry") set_advance_flag(company="_Test Company", flag=0, default_account="") + def test_pulling_advance_based_on_debit_to(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry + + debtors2 = create_account( + parent_account="Accounts Receivable - _TC", + account_name="Debtors 2", + company="_Test Company", + account_type="Receivable", + ) + si = create_sales_invoice(do_not_submit=True) + si.debit_to = debtors2 + si.save() + + pe = create_payment_entry( + company=si.company, + payment_type="Receive", + party_type="Customer", + party=si.customer, + paid_from=debtors2, + paid_to="Cash - _TC", + paid_amount=1000, + ) + pe.submit() + advances = si.get_advance_entries() + self.assertEqual(1, len(advances)) + self.assertEqual(advances[0].reference_name, pe.name) + def set_advance_flag(company, flag, default_account): frappe.db.set_value( From 3c191866545fa5e8a279030cc5314986df69f1c5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 29 Feb 2024 17:39:29 +0530 Subject: [PATCH 12/13] fix: ignore self on GL account validation for Bank Account --- erpnext/accounts/doctype/bank_account/bank_account.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bank_account/bank_account.py b/erpnext/accounts/doctype/bank_account/bank_account.py index df4bd5655a7..bfc8b339bdd 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.py +++ b/erpnext/accounts/doctype/bank_account/bank_account.py @@ -57,7 +57,9 @@ class BankAccount(Document): def validate_account(self): if self.account: - if accounts := frappe.db.get_all("Bank Account", filters={"account": self.account}, as_list=1): + if accounts := frappe.db.get_all( + "Bank Account", filters={"account": self.account, "name": ["!=", self.name]}, as_list=1 + ): frappe.throw( _("'{0}' account is already used by {1}. Use another account.").format( frappe.bold(self.account), From 5e736f0d061b05db8cdc0fd324fa3530079e7a07 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Thu, 29 Feb 2024 16:44:46 +0100 Subject: [PATCH 13/13] fix(Project): filter department by company --- erpnext/projects/doctype/project/project.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js index 2dac399d88f..e0dd1989e80 100644 --- a/erpnext/projects/doctype/project/project.js +++ b/erpnext/projects/doctype/project/project.js @@ -35,6 +35,14 @@ frappe.ui.form.on("Project", { }; }); + frm.set_query("department", function (doc) { + return { + filters: { + "company": doc.company, + } + }; + }); + // sales order frm.set_query('sales_order', function () { var filters = {