perf: fetch SLE's on demand and memoize

This commit is contained in:
ruthra kumar 2023-02-03 16:24:52 +05:30
parent a0eb5e5535
commit 3e5691072a

View File

@ -395,6 +395,7 @@ def get_column_names():
class GrossProfitGenerator(object): class GrossProfitGenerator(object):
def __init__(self, filters=None): def __init__(self, filters=None):
self.sle = {}
self.data = [] self.data = []
self.average_buying_rate = {} self.average_buying_rate = {}
self.filters = frappe._dict(filters) self.filters = frappe._dict(filters)
@ -404,7 +405,6 @@ class GrossProfitGenerator(object):
if filters.group_by == "Invoice": if filters.group_by == "Invoice":
self.group_items_by_invoice() self.group_items_by_invoice()
self.load_stock_ledger_entries()
self.load_product_bundle() self.load_product_bundle()
self.load_non_stock_items() self.load_non_stock_items()
self.get_returned_invoice_items() self.get_returned_invoice_items()
@ -633,7 +633,7 @@ class GrossProfitGenerator(object):
return flt(row.qty) * item_rate return flt(row.qty) * item_rate
else: else:
my_sle = self.sle.get((item_code, row.warehouse)) my_sle = self.get_stock_ledger_entries(item_code, row.warehouse)
if (row.update_stock or row.dn_detail) and my_sle: if (row.update_stock or row.dn_detail) and my_sle:
parenttype, parent = row.parenttype, row.parent parenttype, parent = row.parenttype, row.parent
if row.dn_detail: if row.dn_detail:
@ -651,7 +651,7 @@ class GrossProfitGenerator(object):
dn["item_row"], dn["item_row"],
dn["warehouse"], dn["warehouse"],
) )
my_sle = self.sle.get((item_code, warehouse)) my_sle = self.get_stock_ledger_entries(item_code, row.warehouse)
return self.calculate_buying_amount_from_sle( return self.calculate_buying_amount_from_sle(
row, my_sle, parenttype, parent, item_row, item_code row, my_sle, parenttype, parent, item_row, item_code
) )
@ -947,24 +947,36 @@ class GrossProfitGenerator(object):
"Item", item_code, ["item_name", "description", "item_group", "brand"] "Item", item_code, ["item_name", "description", "item_group", "brand"]
) )
def load_stock_ledger_entries(self): def get_stock_ledger_entries(self, item_code, warehouse):
res = frappe.db.sql( if item_code and warehouse:
"""select item_code, voucher_type, voucher_no, if (item_code, warehouse) not in self.sle:
voucher_detail_no, stock_value, warehouse, actual_qty as qty sle = qb.DocType("Stock Ledger Entry")
from `tabStock Ledger Entry` res = (
where company=%(company)s and is_cancelled = 0 qb.from_(sle)
order by .select(
item_code desc, warehouse desc, posting_date desc, sle.item_code,
posting_time desc, creation desc""", sle.voucher_type,
self.filters, sle.voucher_no,
as_dict=True, sle.voucher_detail_no,
sle.stock_value,
sle.warehouse,
sle.actual_qty.as_("qty"),
)
.where(
(sle.company == self.filters.company)
& (sle.item_code == item_code)
& (sle.warehouse == warehouse)
& (sle.is_cancelled == 0)
)
.orderby(sle.item_code)
.orderby(sle.warehouse, sle.posting_date, sle.posting_time, sle.creation, order=Order.desc)
.run(as_dict=True)
) )
self.sle = {}
for r in res:
if (r.item_code, r.warehouse) not in self.sle:
self.sle[(r.item_code, r.warehouse)] = []
self.sle[(r.item_code, r.warehouse)].append(r) self.sle[(item_code, warehouse)] = res
return self.sle[(item_code, warehouse)]
return []
def load_product_bundle(self): def load_product_bundle(self):
self.product_bundles = {} self.product_bundles = {}