diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 40d552bc88f..7579da86cdf 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -186,9 +186,12 @@ class JournalEntry(AccountsController): def update_advance_paid(self): advance_paid = frappe._dict() + advance_payment_doctypes = frappe.get_hooks( + "advance_payment_customer_doctypes" + ) + frappe.get_hooks("advance_payment_supplier_doctypes") for d in self.get("accounts"): if d.is_advance: - if d.reference_type in frappe.get_hooks("advance_payment_doctypes"): + if d.reference_type in advance_payment_doctypes: advance_paid.setdefault(d.reference_type, []).append(d.reference_name) for voucher_type, order_list in advance_paid.items(): diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index dbebbb00fac..b8781ef1203 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -925,7 +925,10 @@ class PaymentEntry(AccountsController): def calculate_base_allocated_amount_for_reference(self, d) -> float: base_allocated_amount = 0 - if d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"): + advance_payment_doctypes = frappe.get_hooks( + "advance_payment_customer_doctypes" + ) + frappe.get_hooks("advance_payment_supplier_doctypes") + if d.reference_doctype in advance_payment_doctypes: # When referencing Sales/Purchase Order, use the source/target exchange rate depending on payment type. # This is so there are no Exchange Gain/Loss generated for such doctypes @@ -1423,8 +1426,11 @@ class PaymentEntry(AccountsController): def update_advance_paid(self): if self.payment_type in ("Receive", "Pay") and self.party: + advance_payment_doctypes = frappe.get_hooks( + "advance_payment_customer_doctypes" + ) + frappe.get_hooks("advance_payment_supplier_doctypes") for d in self.get("references"): - if d.allocated_amount and d.reference_doctype in frappe.get_hooks("advance_payment_doctypes"): + if d.allocated_amount and d.reference_doctype in advance_payment_doctypes: frappe.get_doc( d.reference_doctype, d.reference_name, for_update=True ).set_total_advance_paid() diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py index 9772b9456d8..839348a5411 100644 --- a/erpnext/accounts/doctype/payment_request/payment_request.py +++ b/erpnext/accounts/doctype/payment_request/payment_request.py @@ -169,6 +169,13 @@ class PaymentRequest(Document): elif self.payment_channel == "Phone": self.request_phone_payment() + advance_payment_doctypes = frappe.get_hooks( + "advance_payment_customer_doctypes" + ) + frappe.get_hooks("advance_payment_supplier_doctypes") + if self.reference_doctype in advance_payment_doctypes: + # set advance payment status + ref_doc.set_total_advance_paid() + def request_phone_payment(self): controller = _get_payment_gateway_controller(self.payment_gateway) request_amount = self.get_request_amount() @@ -207,6 +214,14 @@ class PaymentRequest(Document): self.check_if_payment_entry_exists() self.set_as_cancelled() + ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) + advance_payment_doctypes = frappe.get_hooks( + "advance_payment_customer_doctypes" + ) + frappe.get_hooks("advance_payment_supplier_doctypes") + if self.reference_doctype in advance_payment_doctypes: + # set advance payment status + ref_doc.set_total_advance_paid() + def make_invoice(self): ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) if hasattr(ref_doc, "order_type") and getattr(ref_doc, "order_type") == "Shopping Cart": diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 19095bc46e4..9b706299945 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -600,7 +600,10 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False): jv_detail = journal_entry.get("accounts", {"name": d["voucher_detail_no"]})[0] # Update Advance Paid in SO/PO since they might be getting unlinked - if jv_detail.get("reference_type") in ("Sales Order", "Purchase Order"): + advance_payment_doctypes = frappe.get_hooks( + "advance_payment_customer_doctypes" + ) + frappe.get_hooks("advance_payment_supplier_doctypes") + if jv_detail.get("reference_type") in advance_payment_doctypes: frappe.get_doc(jv_detail.reference_type, jv_detail.reference_name).set_total_advance_paid() if flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) != 0: @@ -673,7 +676,10 @@ def update_reference_in_payment_entry( existing_row = payment_entry.get("references", {"name": d["voucher_detail_no"]})[0] # Update Advance Paid in SO/PO since they are getting unlinked - if existing_row.get("reference_doctype") in ("Sales Order", "Purchase Order"): + advance_payment_doctypes = frappe.get_hooks( + "advance_payment_customer_doctypes" + ) + frappe.get_hooks("advance_payment_supplier_doctypes") + if existing_row.get("reference_doctype") in advance_payment_doctypes: frappe.get_doc( existing_row.reference_doctype, existing_row.reference_name ).set_total_advance_paid() diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index f74df6630e9..9da49a79ee2 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -134,6 +134,7 @@ "more_info_tab", "tracking_section", "status", + "advance_payment_status", "column_break_75", "per_billed", "per_received", @@ -1269,13 +1270,25 @@ "fieldtype": "Tab Break", "label": "Connections", "show_dashboard": 1 + }, + { + "fieldname": "advance_payment_status", + "fieldtype": "Select", + "hidden": 1, + "in_standard_filter": 1, + "label": "Advance Payment Status", + "no_copy": 1, + "oldfieldname": "status", + "oldfieldtype": "Select", + "options": "Not Initiated\nInitiated\nPartially Paid\nFully Paid", + "print_hide": 1 } ], "icon": "fa fa-file-text", "idx": 105, "is_submittable": 1, "links": [], - "modified": "2023-10-01 20:58:07.851037", + "modified": "2023-10-10 13:37:40.158761", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", @@ -1330,4 +1343,4 @@ "timeline_field": "supplier", "title_field": "supplier_name", "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index b830e7d204d..4efbb270e90 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -215,6 +215,10 @@ class PurchaseOrder(BuyingController): self.validate_fg_item_for_subcontracting() self.set_received_qty_for_drop_ship_items() + + if not self.advance_payment_status: + self.advance_payment_status = "Not Initiated" + validate_inter_company_party( self.doctype, self.supplier, self.company, self.inter_company_order_reference ) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_list.js b/erpnext/buying/doctype/purchase_order/purchase_order_list.js index 6594746cfc5..d39d7f92137 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order_list.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order_list.js @@ -1,6 +1,6 @@ frappe.listview_settings['Purchase Order'] = { add_fields: ["base_grand_total", "company", "currency", "supplier", - "supplier_name", "per_received", "per_billed", "status"], + "supplier_name", "per_received", "per_billed", "status", "advance_payment_status"], get_indicator: function (doc) { if (doc.status === "Closed") { return [__("Closed"), "green", "status,=,Closed"]; @@ -8,6 +8,8 @@ frappe.listview_settings['Purchase Order'] = { return [__("On Hold"), "orange", "status,=,On Hold"]; } else if (doc.status === "Delivered") { return [__("Delivered"), "green", "status,=,Closed"]; + } else if (doc.advance_payment_status == "Initiated") { + return [__("To Pay"), "gray", "advance_payment_status,=,Initiated"]; } else if (flt(doc.per_received, 2) < 100 && doc.status !== "Closed") { if (flt(doc.per_billed, 2) < 100) { return [__("To Receive and Bill"), "orange", diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 9b382bbd7e4..5405799b4ec 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -1021,6 +1021,33 @@ class TestPurchaseOrder(FrappeTestCase): self.assertTrue(frappe.db.get_value("Subcontracting Order", {"purchase_order": po.name})) + def test_purchase_order_advance_payment_status(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry + from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request + + po = create_purchase_order() + self.assertEqual( + frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Not Initiated" + ) + + pr = make_payment_request(dt=po.doctype, dn=po.name, submit_doc=True, return_doc=True) + self.assertEqual(frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Initiated") + + pe = get_payment_entry(po.doctype, po.name).save().submit() + self.assertEqual( + frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Fully Paid" + ) + + pe.reload() + pe.cancel() + self.assertEqual(frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Initiated") + + pr.reload() + pr.cancel() + self.assertEqual( + frappe.db.get_value(po.doctype, po.name, "advance_payment_status"), "Not Initiated" + ) + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier diff --git a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js index 91506c0ab39..3bf4f2bb296 100644 --- a/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js +++ b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js @@ -54,7 +54,7 @@ frappe.query_reports["Purchase Order Analysis"] = { "fieldtype": "MultiSelectList", "width": "80", get_data: function(txt) { - let status = ["To Bill", "To Receive", "To Receive and Bill", "Completed"] + let status = ["To Pay", "To Bill", "To Receive", "To Receive and Bill", "Completed"] let options = [] for (let option of status){ options.push({ diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 0c554f23740..7cc4bfe2c96 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1749,7 +1749,10 @@ class AccountsController(TransactionBase): def set_total_advance_paid(self): ple = frappe.qb.DocType("Payment Ledger Entry") - party = self.customer if self.doctype == "Sales Order" else self.supplier + if self.doctype in frappe.get_hooks("advance_payment_customer_doctypes"): + party = self.customer + if self.doctype in frappe.get_hooks("advance_payment_supplier_doctypes"): + party = self.supplier advance = ( frappe.qb.from_(ple) .select(ple.account_currency, Abs(Sum(ple.amount_in_account_currency)).as_("amount")) @@ -1763,6 +1766,8 @@ class AccountsController(TransactionBase): .run(as_dict=True) ) + advance_paid, order_total = None, None + if advance: advance = advance[0] @@ -1791,7 +1796,38 @@ class AccountsController(TransactionBase): ).format(formatted_advance_paid, self.name, formatted_order_total) ) - frappe.db.set_value(self.doctype, self.name, "advance_paid", advance_paid) + self.db_set("advance_paid", advance_paid) + + self.set_advance_payment_status(advance_paid, order_total) + + def set_advance_payment_status( + self, advance_paid: float | None = None, order_total: float | None = None + ): + new_status = None + # if money is paid set the paid states + if advance_paid: + new_status = "Partially Paid" if advance_paid < order_total else "Fully Paid" + + if not new_status: + prs = frappe.db.count( + "Payment Request", + { + "reference_doctype": self.doctype, + "reference_name": self.name, + "docstatus": 1, + }, + ) + if self.doctype in frappe.get_hooks("advance_payment_customer_doctypes"): + new_status = "Requested" if prs else "Not Requested" + if self.doctype in frappe.get_hooks("advance_payment_supplier_doctypes"): + new_status = "Initiated" if prs else "Not Initiated" + + if new_status == self.advance_payment_status: + return + + self.db_set("advance_payment_status", new_status) + self.set_status(update=True) + self.notify_update() @property def company_abbr(self): diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 297f8c26be9..ac8c88f2a53 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -53,6 +53,10 @@ status_map = { "To Deliver", "eval:self.per_delivered < 100 and self.per_billed >= 100 and self.docstatus == 1 and not self.skip_delivery_note", ], + [ + "To Pay", + "eval:self.advance_payment_status == 'Requested' and self.docstatus == 1", + ], [ "Completed", "eval:(self.per_delivered >= 100 or self.skip_delivery_note) and self.per_billed >= 100 and self.docstatus == 1", @@ -63,15 +67,19 @@ status_map = { ], "Purchase Order": [ ["Draft", None], - [ - "To Receive and Bill", - "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1", - ], ["To Bill", "eval:self.per_received >= 100 and self.per_billed < 100 and self.docstatus == 1"], [ "To Receive", "eval:self.per_received < 100 and self.per_billed == 100 and self.docstatus == 1", ], + [ + "To Receive and Bill", + "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1", + ], + [ + "To Pay", + "eval:self.advance_payment_status == 'Initiated' and self.docstatus == 1", + ], [ "Completed", "eval:self.per_received >= 100 and self.per_billed == 100 and self.docstatus == 1", diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 6efb893e630..e21d7bd79b8 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -481,7 +481,8 @@ payment_gateway_enabled = "erpnext.accounts.utils.create_payment_gateway_account communication_doctypes = ["Customer", "Supplier"] -advance_payment_doctypes = ["Sales Order", "Purchase Order"] +advance_payment_customer_doctypes = ["Sales Order"] +advance_payment_supplier_doctypes = ["Purchase Order"] invoice_doctypes = ["Sales Invoice", "Purchase Invoice"] diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 1110617e908..4ead7e71f0e 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -352,6 +352,7 @@ erpnext.patches.v14_0.update_zero_asset_quantity_field execute:frappe.db.set_single_value("Buying Settings", "project_update_frequency", "Each Transaction") execute:frappe.db.set_default("date_format", frappe.db.get_single_value("System Settings", "date_format")) erpnext.patches.v14_0.update_total_asset_cost_field +erpnext.patches.v15_0.create_advance_payment_status # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index # 2023-12-20 diff --git a/erpnext/patches/v15_0/create_advance_payment_status.py b/erpnext/patches/v15_0/create_advance_payment_status.py new file mode 100644 index 00000000000..18ab9fa88c3 --- /dev/null +++ b/erpnext/patches/v15_0/create_advance_payment_status.py @@ -0,0 +1,54 @@ +import frappe + + +def execute(): + """ + Description: + Calculate the new Advance Payment Statuse column in SO & PO + """ + + if frappe.reload_doc("selling", "doctype", "Sales Order"): + so = frappe.qb.DocType("Sales Order") + frappe.qb.update(so).set(so.advance_payment_status, "Not Requested").where( + so.docstatus == 1 + ).where(so.advance_paid == 0.0).run() + + frappe.qb.update(so).set(so.advance_payment_status, "Partially Paid").where( + so.docstatus == 1 + ).where(so.advance_payment_status.isnull()).where( + so.advance_paid < (so.rounded_total or so.grand_total) + ).run() + + frappe.qb.update(so).set(so.advance_payment_status, "Fully Paid").where(so.docstatus == 1).where( + so.advance_payment_status.isnull() + ).where(so.advance_paid == (so.rounded_total or so.grand_total)).run() + + pr = frappe.qb.DocType("Payment Request") + frappe.qb.update(so).join(pr).on(so.name == pr.reference_name).set( + so.advance_payment_status, "Requested" + ).where(so.docstatus == 1).where(pr.docstatus == 1).where( + so.advance_payment_status == "Not Requested" + ).run() + + if frappe.reload_doc("buying", "doctype", "Purchase Order"): + po = frappe.qb.DocType("Purchase Order") + frappe.qb.update(po).set(po.advance_payment_status, "Not Initiated").where( + po.docstatus == 1 + ).where(po.advance_paid == 0.0).run() + + frappe.qb.update(po).set(po.advance_payment_status, "Partially Paid").where( + po.docstatus == 1 + ).where(po.advance_payment_status.isnull()).where( + po.advance_paid < (po.rounded_total or po.grand_total) + ).run() + + frappe.qb.update(po).set(po.advance_payment_status, "Fully Paid").where(po.docstatus == 1).where( + po.advance_payment_status.isnull() + ).where(po.advance_paid == (po.rounded_total or po.grand_total)).run() + + pr = frappe.qb.DocType("Payment Request") + frappe.qb.update(po).join(pr).on(po.name == pr.reference_name).set( + po.advance_payment_status, "Initiated" + ).where(po.docstatus == 1).where(pr.docstatus == 1).where( + po.advance_payment_status == "Not Initiated" + ).run() diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 01d047ceadb..3c516d0ea37 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -131,6 +131,7 @@ "per_billed", "per_picked", "billing_status", + "advance_payment_status", "sales_team_section_break", "sales_partner", "column_break7", @@ -1269,7 +1270,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "\nDraft\nOn Hold\nTo Deliver and Bill\nTo Bill\nTo Deliver\nCompleted\nCancelled\nClosed", + "options": "\nDraft\nOn Hold\nTo Pay\nTo Deliver and Bill\nTo Bill\nTo Deliver\nCompleted\nCancelled\nClosed", "print_hide": 1, "read_only": 1, "reqd": 1, @@ -1638,6 +1639,18 @@ "no_copy": 1, "print_hide": 1, "report_hide": 1 + }, + { + "fieldname": "advance_payment_status", + "fieldtype": "Select", + "hidden": 1, + "hide_days": 1, + "hide_seconds": 1, + "in_standard_filter": 1, + "label": "Advance Payment Status", + "no_copy": 1, + "options": "Not Requested\nRequested\nPartially Paid\nFully Paid", + "print_hide": 1 } ], "icon": "fa fa-file-text", @@ -1722,4 +1735,4 @@ "title_field": "customer_name", "track_changes": 1, "track_seen": 1 -} \ No newline at end of file +} diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 5ef2c50146a..5d1d7695eb4 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -223,6 +223,8 @@ class SalesOrder(SellingController): self.billing_status = "Not Billed" if not self.delivery_status: self.delivery_status = "Not Delivered" + if not self.advance_payment_status: + self.advance_payment_status = "Not Requested" self.reset_default_field_value("set_warehouse", "items", "warehouse") diff --git a/erpnext/selling/doctype/sales_order/sales_order_list.js b/erpnext/selling/doctype/sales_order/sales_order_list.js index 518f0187260..37686a85c33 100644 --- a/erpnext/selling/doctype/sales_order/sales_order_list.js +++ b/erpnext/selling/doctype/sales_order/sales_order_list.js @@ -1,6 +1,6 @@ frappe.listview_settings['Sales Order'] = { add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date", - "per_delivered", "per_billed", "status", "order_type", "name", "skip_delivery_note"], + "per_delivered", "per_billed", "status", "advance_payment_status", "order_type", "name", "skip_delivery_note"], get_indicator: function (doc) { if (doc.status === "Closed") { // Closed @@ -10,6 +10,8 @@ frappe.listview_settings['Sales Order'] = { return [__("On Hold"), "orange", "status,=,On Hold"]; } else if (doc.status === "Completed") { return [__("Completed"), "green", "status,=,Completed"]; + } else if (doc.advance_payment_status === "Requested") { + return [__("To Pay"), "gray", "advance_payment_status,=,Requested"]; } else if (!doc.skip_delivery_note && flt(doc.per_delivered, 2) < 100) { if (frappe.datetime.get_diff(doc.delivery_date) < 0) { // not delivered & overdue diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index ac7fdb1b45a..5ae48ee5617 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -1996,6 +1996,33 @@ class TestSalesOrder(FrappeTestCase): self.assertEqual(so.items[0].rate, scenario.get("expected_rate")) self.assertEqual(so.packed_items[0].rate, scenario.get("expected_rate")) + def test_sales_order_advance_payment_status(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry + from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request + + so = make_sales_order(qty=1, rate=100) + self.assertEqual( + frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Not Requested" + ) + + pr = make_payment_request(dt=so.doctype, dn=so.name, submit_doc=True, return_doc=True) + self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Requested") + + pe = get_payment_entry(so.doctype, so.name).save().submit() + self.assertEqual( + frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Fully Paid" + ) + + pe.reload() + pe.cancel() + self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Requested") + + pr.reload() + pr.cancel() + self.assertEqual( + frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Not Requested" + ) + def automatically_fetch_payment_terms(enable=1): accounts_settings = frappe.get_doc("Accounts Settings") diff --git a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py index 3682c5fd62e..00acc803d59 100644 --- a/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py +++ b/erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py @@ -209,7 +209,7 @@ def get_so_with_invoices(filters): ) .where( (so.docstatus == 1) - & (so.status.isin(["To Deliver and Bill", "To Bill"])) + & (so.status.isin(["To Deliver and Bill", "To Bill", "To Pay"])) & (so.payment_terms_template != "NULL") & (so.company == conditions.company) & (so.transaction_date[conditions.start_date : conditions.end_date]) diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js index ac3d3dbf710..fc685e0fe96 100644 --- a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js +++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js @@ -56,7 +56,7 @@ frappe.query_reports["Sales Order Analysis"] = { "fieldtype": "MultiSelectList", "width": "80", get_data: function(txt) { - let status = ["To Bill", "To Deliver", "To Deliver and Bill", "Completed"] + let status = ["To Pay", "To Bill", "To Deliver", "To Deliver and Bill", "Completed"] let options = [] for (let option of status){ options.push({