refactor: rewrite `Batch-Wise Balance History Report` queries in `QB`
diff --git a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
index 8a13300..2f54325 100644
--- a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
+++ b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
@@ -4,6 +4,7 @@
import frappe
from frappe import _
+from frappe.query_builder.functions import IfNull, Sum
from frappe.utils import cint, flt, getdate
@@ -64,37 +65,35 @@
return columns
-def get_conditions(filters):
- conditions = ""
+# get all details
+def get_stock_ledger_entries(filters):
if not filters.get("from_date"):
frappe.throw(_("'From Date' is required"))
- if filters.get("to_date"):
- conditions += " and posting_date <= '%s'" % filters["to_date"]
- else:
+ if not filters.get("to_date"):
frappe.throw(_("'To Date' is required"))
- for field in ["item_code", "warehouse", "batch_no", "company"]:
- if filters.get(field):
- conditions += " and {0} = {1}".format(field, frappe.db.escape(filters.get(field)))
-
- return conditions
-
-
-# get all details
-def get_stock_ledger_entries(filters):
- conditions = get_conditions(filters)
- return frappe.db.sql(
- """
- select item_code, batch_no, warehouse, posting_date, sum(actual_qty) as actual_qty
- from `tabStock Ledger Entry`
- where is_cancelled = 0 and docstatus < 2 and ifnull(batch_no, '') != '' %s
- group by voucher_no, batch_no, item_code, warehouse
- order by item_code, warehouse"""
- % conditions,
- as_dict=1,
+ sle = frappe.qb.DocType("Stock Ledger Entry")
+ query = (
+ frappe.qb.from_(sle)
+ .select(
+ sle.item_code,
+ sle.batch_no,
+ sle.warehouse,
+ sle.posting_date,
+ Sum(sle.actual_qty).as_("actual_qty"),
+ )
+ .where((sle.is_cancelled == 0) & (sle.docstatus < 2) & (IfNull(sle.batch_no, "") != ""))
+ .groupby(sle.voucher_no, sle.batch_no, sle.item_code, sle.warehouse)
+ .orderby(sle.item_code, sle.warehouse)
)
+ for field in ("item_code", "warehouse", "batch_no", "company"):
+ if filters.get(field):
+ query = query.where(sle[field] == filters[field])
+
+ return query.run(as_dict=True)
+
def get_item_warehouse_batch_map(filters, float_precision):
sle = get_stock_ledger_entries(filters)
@@ -127,7 +126,9 @@
def get_item_details(filters):
item_map = {}
- for d in frappe.db.sql("select name, item_name, description, stock_uom from tabItem", as_dict=1):
+ for d in (frappe.qb.from_("Item").select("name", "item_name", "description", "stock_uom")).run(
+ as_dict=1
+ ):
item_map.setdefault(d.name, d)
return item_map