perf: reduce number of queries for checking if future SL entry exists (#25064)

This commit is contained in:
Sagar Vora 2021-03-31 12:44:03 +05:30 committed by GitHub
parent 368cb45147
commit e50324aed7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 23 deletions

View File

@ -495,7 +495,7 @@ class StockController(AccountsController):
"voucher_no": self.name, "voucher_no": self.name,
"company": self.company "company": self.company
}) })
if check_if_future_sle_exists(args): if future_sle_exists(args):
create_repost_item_valuation_entry(args) create_repost_item_valuation_entry(args)
elif not is_reposting_pending(): elif not is_reposting_pending():
check_if_stock_and_account_balance_synced(self.posting_date, check_if_stock_and_account_balance_synced(self.posting_date,
@ -506,37 +506,42 @@ def is_reposting_pending():
{'docstatus': 1, 'status': ['in', ['Queued','In Progress']]}) {'docstatus': 1, 'status': ['in', ['Queued','In Progress']]})
def check_if_future_sle_exists(args): def future_sle_exists(args):
sl_entries = frappe.db.get_all("Stock Ledger Entry", sl_entries = frappe.get_all("Stock Ledger Entry",
filters={"voucher_type": args.voucher_type, "voucher_no": args.voucher_no}, filters={"voucher_type": args.voucher_type, "voucher_no": args.voucher_no},
fields=["item_code", "warehouse"], fields=["item_code", "warehouse"],
order_by="creation asc") order_by="creation asc")
distinct_item_warehouses = list(set([(d.item_code, d.warehouse) for d in sl_entries])) if not sl_entries:
return
sle_exists = False warehouse_items_map = {}
for item_code, warehouse in distinct_item_warehouses: for entry in sl_entries:
args.update({ if entry.warehouse not in warehouse_items_map:
"item_code": item_code, warehouse_items_map[entry.warehouse] = set()
"warehouse": warehouse
}) warehouse_items_map[entry.warehouse].add(entry.item_code)
if get_sle(args):
sle_exists = True or_conditions = []
break for warehouse, items in warehouse_items_map.items():
return sle_exists or_conditions.append(
"warehouse = '{}' and item_code in ({})".format(
warehouse,
", ".join(frappe.db.escape(item) for item in items)
)
)
def get_sle(args):
return frappe.db.sql(""" return frappe.db.sql("""
select name select name
from `tabStock Ledger Entry` from `tabStock Ledger Entry`
where where
item_code=%(item_code)s ({})
and warehouse=%(warehouse)s and timestamp(posting_date, posting_time)
and timestamp(posting_date, posting_time) >= timestamp(%(posting_date)s, %(posting_time)s) >= timestamp(%(posting_date)s, %(posting_time)s)
and voucher_no != %(voucher_no)s and voucher_no != %(voucher_no)s
and is_cancelled = 0 and is_cancelled = 0
limit 1 limit 1
""", args) """.format(" or ".join(or_conditions)), args)
def create_repost_item_valuation_entry(args): def create_repost_item_valuation_entry(args):
args = frappe._dict(args) args = frappe._dict(args)

View File

@ -207,11 +207,11 @@ class update_entries_after(object):
def build(self): def build(self):
from erpnext.controllers.stock_controller import check_if_future_sle_exists from erpnext.controllers.stock_controller import future_sle_exists
if self.args.get("sle_id"): if self.args.get("sle_id"):
self.process_sle_against_current_timestamp() self.process_sle_against_current_timestamp()
if not check_if_future_sle_exists(self.args): if not future_sle_exists(self.args):
self.update_bin() self.update_bin()
else: else:
entries_to_fix = self.get_future_entries_to_fix() entries_to_fix = self.get_future_entries_to_fix()