mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-16 07:58:38 +00:00
refactor(controllers): make StatusUpdater Postgres-valid (ifnull→coalesce, raw SQL→qb)
- Replace MySQL-only `ifnull(...)` with `coalesce(...)` in the two source/second-source percentage subqueries that remain raw (they interpolate dynamic table/field names). - zero_amount_refdocs: raw `sql_list` → `frappe.get_all(pluck="name")`. - update_billing_status: two raw `ifnull(sum(qty), 0)` selects → frappe.qb `Sum`; an empty result yields None and flt(None) == 0, matching the old ifnull behaviour. Behaviour is unchanged on MariaDB. The percentage path (coalesce subquery) is exercised by test_selling_controller's Sales Order -> Delivery Note per_delivered test on both engines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.functions import Sum
|
||||
from frappe.utils import comma_or, flt, get_link_to_form, getdate, now, nowdate, safe_div
|
||||
|
||||
|
||||
@@ -554,7 +555,7 @@ class StatusUpdater(Document):
|
||||
args["second_source_extra_cond"] = ""
|
||||
|
||||
args["second_source_condition"] = frappe.db.sql(
|
||||
""" select ifnull((select sum({second_source_field})
|
||||
""" select coalesce((select sum({second_source_field})
|
||||
from `tab{second_source_dt}`
|
||||
where `{second_join_field}`=%(detail_id)s
|
||||
and (`tab{second_source_dt}`.docstatus=1)
|
||||
@@ -569,7 +570,7 @@ class StatusUpdater(Document):
|
||||
args["source_dt_value"] = (
|
||||
frappe.db.sql(
|
||||
"""
|
||||
(select ifnull(sum({source_field}), 0)
|
||||
(select coalesce(sum({source_field}), 0)
|
||||
from `tab{source_dt}` where `{join_field}`=%(detail_id)s
|
||||
and (docstatus=1 {cond}) {extra_cond})
|
||||
""".format(**args),
|
||||
@@ -684,18 +685,10 @@ class StatusUpdater(Document):
|
||||
if not ref_docs:
|
||||
return
|
||||
|
||||
zero_amount_refdocs = frappe.db.sql_list(
|
||||
f"""
|
||||
SELECT
|
||||
name
|
||||
from
|
||||
`tab{ref_dt}`
|
||||
where
|
||||
docstatus = 1
|
||||
and base_net_total = 0
|
||||
and name in %(ref_docs)s
|
||||
""",
|
||||
{"ref_docs": ref_docs},
|
||||
zero_amount_refdocs = frappe.get_all(
|
||||
ref_dt,
|
||||
filters={"docstatus": 1, "base_net_total": 0, "name": ["in", ref_docs]},
|
||||
pluck="name",
|
||||
)
|
||||
|
||||
if zero_amount_refdocs:
|
||||
@@ -703,20 +696,20 @@ class StatusUpdater(Document):
|
||||
|
||||
def update_billing_status(self, zero_amount_refdoc, ref_dt, ref_fieldname):
|
||||
for ref_dn in zero_amount_refdoc:
|
||||
ref_item = frappe.qb.DocType(f"{ref_dt} Item")
|
||||
ref_doc_qty = flt(
|
||||
frappe.db.sql(
|
||||
"""select ifnull(sum(qty), 0) from `tab{} Item`
|
||||
where parent={}""".format(ref_dt, "%s"),
|
||||
(ref_dn),
|
||||
)[0][0]
|
||||
frappe.qb.from_(ref_item)
|
||||
.select(Sum(ref_item.qty))
|
||||
.where(ref_item.parent == ref_dn)
|
||||
.run()[0][0]
|
||||
)
|
||||
|
||||
doc_item = frappe.qb.DocType(f"{self.doctype} Item")
|
||||
billed_qty = flt(
|
||||
frappe.db.sql(
|
||||
"""select ifnull(sum(qty), 0)
|
||||
from `tab{} Item` where {}={} and docstatus=1""".format(self.doctype, ref_fieldname, "%s"),
|
||||
(ref_dn),
|
||||
)[0][0]
|
||||
frappe.qb.from_(doc_item)
|
||||
.select(Sum(doc_item.qty))
|
||||
.where((doc_item[ref_fieldname] == ref_dn) & (doc_item.docstatus == 1))
|
||||
.run()[0][0]
|
||||
)
|
||||
|
||||
per_billed = safe_div(min(ref_doc_qty, billed_qty), ref_doc_qty) * 100
|
||||
|
||||
Reference in New Issue
Block a user