mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-13 18:21:22 +00:00
perf: stock ageing and batch-wise balance history report
This commit is contained in:
@@ -40,16 +40,26 @@ frappe.query_reports["Batch-Wise Balance History"] = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldname: "warehouse_type",
|
||||||
|
label: __("Warehouse Type"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
width: "80",
|
||||||
|
options: "Warehouse Type",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname: "warehouse",
|
fieldname: "warehouse",
|
||||||
label: __("Warehouse"),
|
label: __("Warehouse"),
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Warehouse",
|
options: "Warehouse",
|
||||||
get_query: function () {
|
get_query: function () {
|
||||||
let company = frappe.query_report.get_filter_value("company");
|
let warehouse_type = frappe.query_report.get_filter_value("warehouse_type");
|
||||||
|
const company = frappe.query_report.get_filter_value("company");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
company: company,
|
...(warehouse_type && { warehouse_type }),
|
||||||
|
...(company && { company }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -113,6 +113,16 @@ def get_stock_ledger_entries(filters):
|
|||||||
)
|
)
|
||||||
|
|
||||||
query = apply_warehouse_filter(query, sle, filters)
|
query = apply_warehouse_filter(query, sle, filters)
|
||||||
|
if filters.warehouse_type and not filters.warehouse:
|
||||||
|
warehouses = frappe.get_all(
|
||||||
|
"Warehouse",
|
||||||
|
filters={"warehouse_type": filters.warehouse_type, "is_group": 0},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
|
||||||
|
if warehouses:
|
||||||
|
query = query.where(sle.warehouse.isin(warehouses))
|
||||||
|
|
||||||
for field in ["item_code", "batch_no", "company"]:
|
for field in ["item_code", "batch_no", "company"]:
|
||||||
if filters.get(field):
|
if filters.get(field):
|
||||||
query = query.where(sle[field] == filters.get(field))
|
query = query.where(sle[field] == filters.get(field))
|
||||||
|
|||||||
@@ -18,15 +18,25 @@ frappe.query_reports["Stock Ageing"] = {
|
|||||||
default: frappe.datetime.get_today(),
|
default: frappe.datetime.get_today(),
|
||||||
reqd: 1,
|
reqd: 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldname: "warehouse_type",
|
||||||
|
label: __("Warehouse Type"),
|
||||||
|
fieldtype: "Link",
|
||||||
|
width: "80",
|
||||||
|
options: "Warehouse Type",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname: "warehouse",
|
fieldname: "warehouse",
|
||||||
label: __("Warehouse"),
|
label: __("Warehouse"),
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Warehouse",
|
options: "Warehouse",
|
||||||
get_query: () => {
|
get_query: () => {
|
||||||
|
let warehouse_type = frappe.query_report.get_filter_value("warehouse_type");
|
||||||
const company = frappe.query_report.get_filter_value("company");
|
const company = frappe.query_report.get_filter_value("company");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
|
...(warehouse_type && { warehouse_type }),
|
||||||
...(company && { company }),
|
...(company && { company }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -227,25 +227,30 @@ class FIFOSlots:
|
|||||||
consumed/updated and maintained via FIFO. **
|
consumed/updated and maintained via FIFO. **
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
if self.sle is None:
|
stock_ledger_entries = self.sle
|
||||||
self.sle = self.__get_stock_ledger_entries()
|
|
||||||
|
|
||||||
for d in self.sle:
|
with frappe.db.unbuffered_cursor():
|
||||||
key, fifo_queue, transferred_item_key = self.__init_key_stores(d)
|
if self.sle is None:
|
||||||
|
self.sle = self.__get_stock_ledger_entries()
|
||||||
|
|
||||||
if d.voucher_type == "Stock Reconciliation":
|
for d in self.sle:
|
||||||
# get difference in qty shift as actual qty
|
key, fifo_queue, transferred_item_key = self.__init_key_stores(d)
|
||||||
prev_balance_qty = self.item_details[key].get("qty_after_transaction", 0)
|
|
||||||
d.actual_qty = flt(d.qty_after_transaction) - flt(prev_balance_qty)
|
|
||||||
|
|
||||||
serial_nos = get_serial_nos(d.serial_no) if d.serial_no else []
|
if d.voucher_type == "Stock Reconciliation":
|
||||||
|
# get difference in qty shift as actual qty
|
||||||
|
prev_balance_qty = self.item_details[key].get("qty_after_transaction", 0)
|
||||||
|
d.actual_qty = flt(d.qty_after_transaction) - flt(prev_balance_qty)
|
||||||
|
|
||||||
if d.actual_qty > 0:
|
serial_nos = get_serial_nos(d.serial_no) if d.serial_no else []
|
||||||
self.__compute_incoming_stock(d, fifo_queue, transferred_item_key, serial_nos)
|
|
||||||
else:
|
|
||||||
self.__compute_outgoing_stock(d, fifo_queue, transferred_item_key, serial_nos)
|
|
||||||
|
|
||||||
self.__update_balances(d, key)
|
if d.actual_qty > 0:
|
||||||
|
self.__compute_incoming_stock(d, fifo_queue, transferred_item_key, serial_nos)
|
||||||
|
else:
|
||||||
|
self.__compute_outgoing_stock(d, fifo_queue, transferred_item_key, serial_nos)
|
||||||
|
|
||||||
|
self.__update_balances(d, key)
|
||||||
|
|
||||||
|
del stock_ledger_entries
|
||||||
|
|
||||||
if not self.filters.get("show_warehouse_wise_stock"):
|
if not self.filters.get("show_warehouse_wise_stock"):
|
||||||
# (Item 1, WH 1), (Item 1, WH 2) => (Item 1)
|
# (Item 1, WH 1), (Item 1, WH 2) => (Item 1)
|
||||||
@@ -412,10 +417,19 @@ class FIFOSlots:
|
|||||||
|
|
||||||
if self.filters.get("warehouse"):
|
if self.filters.get("warehouse"):
|
||||||
sle_query = self.__get_warehouse_conditions(sle, sle_query)
|
sle_query = self.__get_warehouse_conditions(sle, sle_query)
|
||||||
|
elif self.filters.get("warehouse_type"):
|
||||||
|
warehouses = frappe.get_all(
|
||||||
|
"Warehouse",
|
||||||
|
filters={"warehouse_type": self.filters.get("warehouse_type"), "is_group": 0},
|
||||||
|
pluck="name",
|
||||||
|
)
|
||||||
|
|
||||||
|
if warehouses:
|
||||||
|
sle_query = sle_query.where(sle.warehouse.isin(warehouses))
|
||||||
|
|
||||||
sle_query = sle_query.orderby(sle.posting_date, sle.posting_time, sle.creation, sle.actual_qty)
|
sle_query = sle_query.orderby(sle.posting_date, sle.posting_time, sle.creation, sle.actual_qty)
|
||||||
|
|
||||||
return sle_query.run(as_dict=True)
|
return sle_query.run(as_dict=True, as_iterator=True)
|
||||||
|
|
||||||
def __get_item_query(self) -> str:
|
def __get_item_query(self) -> str:
|
||||||
item_table = frappe.qb.DocType("Item")
|
item_table = frappe.qb.DocType("Item")
|
||||||
|
|||||||
Reference in New Issue
Block a user