Merge remote-tracking branch 'upstream/develop' into feat/so-po-advance-payment-status
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 5f0b434..f600424 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -110,6 +110,21 @@
elif self.payment_channel == "Phone":
self.request_phone_payment()
+ if (
+ self.reference_doctype in ["Sales Order"] and ref_doc.advance_payment_status == "Not Requested"
+ ):
+ ref_doc.db_set("advance_payment_status", "Requested")
+ ref_doc.set_status(update=True)
+ ref_doc.notify_update()
+
+ if (
+ self.reference_doctype in ["Purchase Order"]
+ and ref_doc.advance_payment_status == "Not Initiated"
+ ):
+ ref_doc.db_set("advance_payment_status", "Initiated")
+ ref_doc.set_status(update=True)
+ ref_doc.notify_update()
+
def request_phone_payment(self):
controller = _get_payment_gateway_controller(self.payment_gateway)
request_amount = self.get_request_amount()
@@ -148,6 +163,39 @@
self.check_if_payment_entry_exists()
self.set_as_cancelled()
+ if self.reference_doctype in ["Sales Order", "Purchase Order"]:
+
+ ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
+ if self.reference_doctype in ["Sales Order"] and ref_doc.advance_payment_status == "Requested":
+ peer_pr = frappe.db.count(
+ "Payment Request",
+ {
+ "reference_doctype": self.reference_doctype,
+ "reference_name": self.reference_name,
+ "docstatus": 1,
+ },
+ )
+ if not peer_pr:
+ ref_doc.db_set("advance_payment_status", "Not Requested")
+ ref_doc.set_status(update=True)
+ ref_doc.notify_update()
+
+ if (
+ self.reference_doctype in ["Purchase Order"] and ref_doc.advance_payment_status == "Initiated"
+ ):
+ peer_pr = frappe.db.count(
+ "Payment Request",
+ {
+ "reference_doctype": self.reference_doctype,
+ "reference_name": self.reference_name,
+ "docstatus": 1,
+ },
+ )
+ if not peer_pr:
+ ref_doc.db_set("advance_payment_status", "Not Initiated")
+ ref_doc.set_status(update=True)
+ ref_doc.notify_update()
+
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/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index f74df66..97f2310 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\nPaid",
+ "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 961697c..2d7dbd6 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -349,6 +349,9 @@
self.validate_budget()
self.update_reserved_qty_for_subcontract()
+ if not self.advance_payment_status:
+ self.advance_payment_status = "Not Initiated"
+
frappe.get_doc("Authorization Control").validate_approving_authority(
self.doctype, self.company, self.base_grand_total
)
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_list.js b/erpnext/buying/doctype/purchase_order/purchase_order_list.js
index 6594746..d39d7f9 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 @@
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/report/purchase_order_analysis/purchase_order_analysis.js b/erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js
index 91506c0..3bf4f2b 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 @@
"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 6efe631..6ea154c 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1714,6 +1714,12 @@
)
frappe.db.set_value(self.doctype, self.name, "advance_paid", advance_paid)
+ frappe.db.set_value(
+ self.doctype,
+ self.name,
+ "advance_payment_status",
+ "Partially Paid" if advance_paid < order_total else "Paid",
+ )
@property
def company_abbr(self):
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 73a248f..2b79b89 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -54,6 +54,10 @@
"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,16 +67,20 @@
],
"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/patches.txt b/erpnext/patches.txt
index d7f33ad..3f9744d 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -343,5 +343,6 @@
erpnext.patches.v15_0.update_sre_from_voucher_details
erpnext.patches.v14_0.rename_over_order_allowance_field
erpnext.patches.v14_0.migrate_delivery_stop_lock_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
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 0000000..ff5ba8f
--- /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, "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, "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 01d047c..5b80dfd 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\nPaid",
+ "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 2f6578e..eb6d63e 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -89,6 +89,8 @@
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 518f018..37686a8 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 @@
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/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 3682c5f..00acc80 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 @@
)
.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 ac3d3db..fc685e0 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 @@
"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({