mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-01 20:48:27 +00:00
fix: batch qty calculation performance issue
(cherry picked from commit 1a262483a4)
This commit is contained in:
committed by
Mergify
parent
08cfd00373
commit
921f317423
@@ -957,7 +957,9 @@ class StockController(AccountsController):
|
|||||||
from erpnext.stock.stock_ledger import make_sl_entries
|
from erpnext.stock.stock_ledger import make_sl_entries
|
||||||
|
|
||||||
make_sl_entries(sl_entries, allow_negative_stock, via_landed_cost_voucher)
|
make_sl_entries(sl_entries, allow_negative_stock, via_landed_cost_voucher)
|
||||||
update_batch_qty(self.doctype, self.name, via_landed_cost_voucher=via_landed_cost_voucher)
|
update_batch_qty(
|
||||||
|
self.doctype, self.name, self.docstatus, via_landed_cost_voucher=via_landed_cost_voucher
|
||||||
|
)
|
||||||
|
|
||||||
def make_gl_entries_on_cancel(self, from_repost=False):
|
def make_gl_entries_on_cancel(self, from_repost=False):
|
||||||
if not from_repost:
|
if not from_repost:
|
||||||
|
|||||||
@@ -222,7 +222,12 @@ class TestSerialandBatchBundle(FrappeTestCase):
|
|||||||
).insert(ignore_permissions=True)
|
).insert(ignore_permissions=True)
|
||||||
|
|
||||||
self.assertTrue(batch_doc.use_batchwise_valuation)
|
self.assertTrue(batch_doc.use_batchwise_valuation)
|
||||||
batch_doc.db_set("use_batchwise_valuation", 0)
|
batch_doc.db_set(
|
||||||
|
{
|
||||||
|
"use_batchwise_valuation": 0,
|
||||||
|
"batch_qty": 30,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
stock_queue = []
|
stock_queue = []
|
||||||
qty_after_transaction = 0
|
qty_after_transaction = 0
|
||||||
|
|||||||
@@ -1326,40 +1326,40 @@ def get_serial_nos_batch(serial_nos):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def update_batch_qty(voucher_type, voucher_no, via_landed_cost_voucher=False):
|
def update_batch_qty(voucher_type, voucher_no, docstatus, via_landed_cost_voucher=False):
|
||||||
from erpnext.stock.doctype.batch.batch import get_available_batches
|
batches = get_batchwise_qty(voucher_type, voucher_no)
|
||||||
|
|
||||||
batches = get_distinct_batches(voucher_type, voucher_no)
|
|
||||||
if not batches:
|
if not batches:
|
||||||
return
|
return
|
||||||
|
|
||||||
precision = frappe.get_precision("Batch", "batch_qty")
|
precision = frappe.get_precision("Batch", "batch_qty")
|
||||||
batch_data = get_available_batches(
|
for batch, qty in batches.items():
|
||||||
frappe._dict({"batch_no": batches, "consider_negative_batches": 1, "based_on_warehouse": True})
|
current_qty = get_batch_current_qty(batch)
|
||||||
)
|
current_qty += flt(qty, precision) * (-1 if docstatus == 2 else 1)
|
||||||
batchwise_qty = defaultdict(float)
|
|
||||||
|
|
||||||
for (batch_no, warehouse), qty in batch_data.items():
|
if not via_landed_cost_voucher and current_qty < 0:
|
||||||
if not via_landed_cost_voucher and flt(qty, precision) < 0:
|
throw_negative_batch_validation(batch, current_qty)
|
||||||
throw_negative_batch_validation(batch_no, warehouse, qty)
|
|
||||||
|
|
||||||
batchwise_qty[batch_no] += qty
|
frappe.db.set_value("Batch", batch, "batch_qty", current_qty)
|
||||||
|
|
||||||
for batch_no in batches:
|
|
||||||
qty = flt(batchwise_qty.get(batch_no, 0), precision)
|
|
||||||
frappe.db.set_value("Batch", batch_no, "batch_qty", qty)
|
|
||||||
|
|
||||||
|
|
||||||
def throw_negative_batch_validation(batch_no, warehouse, qty):
|
def get_batch_current_qty(batch):
|
||||||
|
doctype = frappe.qb.DocType("Batch")
|
||||||
|
query = frappe.qb.from_(doctype).select(doctype.batch_qty).where(doctype.name == batch).for_update()
|
||||||
|
batch_qty = query.run()
|
||||||
|
|
||||||
|
return flt(batch_qty[0][0]) if batch_qty else 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def throw_negative_batch_validation(batch_no, qty):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("The Batch {0} has negative quantity {1} in warehouse {2}. Please correct the quantity.").format(
|
_("The Batch {0} has negative quantity {1}. Please correct the quantity.").format(
|
||||||
bold(batch_no), bold(qty), bold(warehouse)
|
bold(batch_no), bold(qty)
|
||||||
),
|
),
|
||||||
title=_("Negative Batch Quantity"),
|
title=_("Negative Batch Quantity"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_distinct_batches(voucher_type, voucher_no):
|
def get_batchwise_qty(voucher_type, voucher_no):
|
||||||
bundles = frappe.get_all(
|
bundles = frappe.get_all(
|
||||||
"Serial and Batch Bundle",
|
"Serial and Batch Bundle",
|
||||||
filters={"voucher_no": voucher_no, "voucher_type": voucher_type},
|
filters={"voucher_no": voucher_no, "voucher_type": voucher_type},
|
||||||
@@ -1368,9 +1368,15 @@ def get_distinct_batches(voucher_type, voucher_no):
|
|||||||
if not bundles:
|
if not bundles:
|
||||||
return
|
return
|
||||||
|
|
||||||
return frappe.get_all(
|
batches = frappe.get_all(
|
||||||
"Serial and Batch Entry",
|
"Serial and Batch Entry",
|
||||||
filters={"parent": ("in", bundles), "batch_no": ("is", "set")},
|
filters={"parent": ("in", bundles), "batch_no": ("is", "set")},
|
||||||
|
fields=["batch_no", "SUM(qty) as qty"],
|
||||||
group_by="batch_no",
|
group_by="batch_no",
|
||||||
pluck="batch_no",
|
as_list=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not batches:
|
||||||
|
return frappe._dict({})
|
||||||
|
|
||||||
|
return frappe._dict(batches)
|
||||||
|
|||||||
Reference in New Issue
Block a user