From 6381e75fa5b402a678c94320eba14b19a3c11012 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 17 Oct 2022 12:17:05 +0530 Subject: [PATCH 1/2] fix: group warehouse filter not working for Batchwise Balance history report --- .../batch_wise_balance_history.py | 67 +++++++++++++------ 1 file changed, 47 insertions(+), 20 deletions(-) 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 8a13300dc8..911f4c3167 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 @@ -5,6 +5,8 @@ import frappe from frappe import _ from frappe.utils import cint, flt, getdate +from pypika import functions as fn +from pypika.terms import ExistsCriterion def execute(filters=None): @@ -64,36 +66,61 @@ def get_columns(filters): 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"] + sle = frappe.qb.DocType("Stock Ledger Entry") + query = ( + frappe.qb.from_(sle) + .select( + sle.item_code, + sle.warehouse, + sle.batch_no, + sle.posting_date, + fn.Sum(sle.actual_qty).as_("actual_qty"), + ) + .where( + (sle.docstatus < 2) + & (sle.is_cancelled == 0) + & (sle.batch_no.isnotnull()) + & (sle.batch_no != "") + ) + .groupby(sle.voucher_no, sle.batch_no, sle.item_code, sle.warehouse) + .orderby(sle.item_code, sle.warehouse) + ) + + if to_date := filters.get("to_date"): + query = query.where(sle.posting_date <= to_date) else: frappe.throw(_("'To Date' is required")) - for field in ["item_code", "warehouse", "batch_no", "company"]: + query = apply_warehouse_filter(query, sle, filters) + for field in ["item_code", "batch_no", "company"]: if filters.get(field): - conditions += " and {0} = {1}".format(field, frappe.db.escape(filters.get(field))) + query = query.where(sle[field] == filters.get(field)) - return conditions + return query.run(as_dict=True) -# 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, - ) +def apply_warehouse_filter(query, sle, filters): + if warehouse := filters.get("warehouse"): + warehouse_table = frappe.qb.DocType("Warehouse") + + lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) + chilren_subquery = ( + frappe.qb.from_(warehouse_table) + .select(warehouse_table.name) + .where( + (warehouse_table.lft >= lft) + & (warehouse_table.rgt <= rgt) + & (warehouse_table.name == sle.warehouse) + ) + ) + query = query.where(ExistsCriterion(chilren_subquery)) + + return query def get_item_warehouse_batch_map(filters, float_precision): From 2481574a2808e888acc0b59492642e0ffd5d9376 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 17 Oct 2022 14:18:55 +0530 Subject: [PATCH 2/2] chore: seperate function to apply filter for warehouse in case of QB --- erpnext/stock/doctype/warehouse/warehouse.py | 21 ++++++++++++++++++ .../batch_wise_balance_history.py | 22 ++----------------- .../report/stock_balance/stock_balance.py | 16 +++----------- .../stock/report/stock_ledger/stock_ledger.py | 17 ++------------ 4 files changed, 28 insertions(+), 48 deletions(-) diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index ab784ca107..6e06d23617 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -9,6 +9,7 @@ from frappe import _, throw from frappe.contacts.address_and_contact import load_address_and_contact from frappe.utils import cint, flt from frappe.utils.nestedset import NestedSet +from pypika.terms import ExistsCriterion from erpnext.stock import get_warehouse_account @@ -266,3 +267,23 @@ def get_warehouses_based_on_account(account, company=None): frappe.throw(_("Warehouse not found against the account {0}").format(account)) return warehouses + + +# Will be use for frappe.qb +def apply_warehouse_filter(query, sle, filters): + if warehouse := filters.get("warehouse"): + warehouse_table = frappe.qb.DocType("Warehouse") + + lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) + chilren_subquery = ( + frappe.qb.from_(warehouse_table) + .select(warehouse_table.name) + .where( + (warehouse_table.lft >= lft) + & (warehouse_table.rgt <= rgt) + & (warehouse_table.name == sle.warehouse) + ) + ) + query = query.where(ExistsCriterion(chilren_subquery)) + + return query 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 911f4c3167..291c6b5dab 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 @@ -6,7 +6,8 @@ import frappe from frappe import _ from frappe.utils import cint, flt, getdate from pypika import functions as fn -from pypika.terms import ExistsCriterion + +from erpnext.stock.doctype.warehouse.warehouse import apply_warehouse_filter def execute(filters=None): @@ -104,25 +105,6 @@ def get_stock_ledger_entries(filters): return query.run(as_dict=True) -def apply_warehouse_filter(query, sle, filters): - if warehouse := filters.get("warehouse"): - warehouse_table = frappe.qb.DocType("Warehouse") - - lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) - chilren_subquery = ( - frappe.qb.from_(warehouse_table) - .select(warehouse_table.name) - .where( - (warehouse_table.lft >= lft) - & (warehouse_table.rgt <= rgt) - & (warehouse_table.name == sle.warehouse) - ) - ) - query = query.where(ExistsCriterion(chilren_subquery)) - - return query - - def get_item_warehouse_batch_map(filters, float_precision): sle = get_stock_ledger_entries(filters) iwb_map = {} diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 679d234c9f..0fc642ef20 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -10,10 +10,10 @@ from frappe import _ from frappe.query_builder.functions import CombineDatetime from frappe.utils import cint, date_diff, flt, getdate from frappe.utils.nestedset import get_descendants_of -from pypika.terms import ExistsCriterion import erpnext from erpnext.stock.doctype.inventory_dimension.inventory_dimension import get_inventory_dimensions +from erpnext.stock.doctype.warehouse.warehouse import apply_warehouse_filter from erpnext.stock.report.stock_ageing.stock_ageing import FIFOSlots, get_average_age from erpnext.stock.utils import add_additional_uom_columns, is_reposting_item_valuation_in_progress @@ -270,18 +270,8 @@ def apply_conditions(query, filters): if company := filters.get("company"): query = query.where(sle.company == company) - if warehouse := filters.get("warehouse"): - lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) - chilren_subquery = ( - frappe.qb.from_(warehouse_table) - .select(warehouse_table.name) - .where( - (warehouse_table.lft >= lft) - & (warehouse_table.rgt <= rgt) - & (warehouse_table.name == sle.warehouse) - ) - ) - query = query.where(ExistsCriterion(chilren_subquery)) + if filters.get("warehouse"): + query = apply_warehouse_filter(query, sle, filters) elif warehouse_type := filters.get("warehouse_type"): query = ( query.join(warehouse_table) diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index e18d4c7522..a95119736a 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -6,11 +6,11 @@ import frappe from frappe import _ from frappe.query_builder.functions import CombineDatetime from frappe.utils import cint, flt -from pypika.terms import ExistsCriterion from erpnext.stock.doctype.inventory_dimension.inventory_dimension import get_inventory_dimensions from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import get_stock_balance_for +from erpnext.stock.doctype.warehouse.warehouse import apply_warehouse_filter from erpnext.stock.utils import ( is_reposting_item_valuation_in_progress, update_included_uom_in_report, @@ -295,20 +295,7 @@ def get_stock_ledger_entries(filters, items): if filters.get(field): query = query.where(sle[field] == filters.get(field)) - if warehouse := filters.get("warehouse"): - lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"]) - - warehouse_table = frappe.qb.DocType("Warehouse") - chilren_subquery = ( - frappe.qb.from_(warehouse_table) - .select(warehouse_table.name) - .where( - (warehouse_table.lft >= lft) - & (warehouse_table.rgt <= rgt) - & (warehouse_table.name == sle.warehouse) - ) - ) - query = query.where(ExistsCriterion(chilren_subquery)) + query = apply_warehouse_filter(query, sle, filters) return query.run(as_dict=True)