Skip to content

Commit

Permalink
perf: stock entry with batch
Browse files Browse the repository at this point in the history
(cherry picked from commit 0b1b964)
  • Loading branch information
rohitwaghchaure authored and mergify[bot] committed Jan 29, 2025
1 parent b5856d4 commit 8d63ab4
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,6 @@ def test_merging_into_sales_invoice_for_batched_item(self):
item_code=item_code, qty=5, rate=300, use_serial_batch_fields=1, batch_no=batch_no
)

batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty")
self.assertEqual(batch_qty, 10)

batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code)
self.assertEqual(batch_qty_with_pos, 0.0)

Expand Down Expand Up @@ -256,9 +253,6 @@ def test_merging_into_sales_invoice_for_batched_item(self):
pcv_doc.reload()
pcv_doc.cancel()

batch_qty = frappe.db.get_value("Batch", batch_no, "batch_qty")
self.assertEqual(batch_qty, 10)

batch_qty_with_pos = get_batch_qty(batch_no, "_Test Warehouse - _TC", item_code)
self.assertEqual(batch_qty_with_pos, 0.0)

Expand Down
2 changes: 2 additions & 0 deletions erpnext/controllers/stock_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,9 +921,11 @@ def update_inventory_dimensions(self, row, sl_dict) -> None:
row.db_set(dimension.source_fieldname, sl_dict[dimension.target_fieldname])

def make_sl_entries(self, sl_entries, allow_negative_stock=False, via_landed_cost_voucher=False):
from erpnext.stock.serial_batch_bundle import update_batch_qty
from erpnext.stock.stock_ledger import make_sl_entries

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)

def make_gl_entries_on_cancel(self):
cancel_exchange_gain_loss_journal(frappe._dict(doctype=self.doctype, name=self.name))
Expand Down
10 changes: 7 additions & 3 deletions erpnext/stock/doctype/batch/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,10 +455,14 @@ def get_available_batches(kwargs):

batches = get_auto_batch_nos(kwargs)
for batch in batches:
if batch.get("batch_no") not in batchwise_qty:
batchwise_qty[batch.get("batch_no")] = batch.get("qty")
key = batch.get("batch_no")
if kwargs.get("based_on_warehouse"):
key = (batch.get("batch_no"), batch.get("warehouse"))

if key not in batchwise_qty:
batchwise_qty[key] = batch.get("qty")
else:
batchwise_qty[batch.get("batch_no")] += batch.get("qty")
batchwise_qty[key] += batch.get("qty")

return batchwise_qty

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ def validate(self):
self.set_is_outward()
self.calculate_total_qty()
self.set_warehouse()
self.set_incoming_rate()

if self.voucher_type != "Stock Entry" or not self.voucher_no or self.docstatus == 1:
self.set_incoming_rate()

self.calculate_qty_and_amount()

def allow_existing_serial_nos(self):
Expand Down Expand Up @@ -1026,7 +1029,6 @@ def before_submit(self):
self.set_purchase_document_no()

def on_submit(self):
self.validate_batch_inventory()
self.validate_serial_nos_inventory()

def set_purchase_document_no(self):
Expand All @@ -1053,25 +1055,9 @@ def validate_serial_and_batch_inventory(self):
self.validate_batch_inventory()

def validate_batch_inventory(self):
if (
self.voucher_type in ["Purchase Invoice", "Purchase Receipt"]
and frappe.db.get_value(self.voucher_type, self.voucher_no, "docstatus") == 1
):
return

if self.voucher_type in ["Sales Invoice", "Delivery Note"] and self.type_of_transaction == "Inward":
return

if not self.has_batch_no:
return

if (
self.voucher_type == "Stock Reconciliation"
and self.type_of_transaction == "Outward"
and frappe.db.get_value("Stock Reconciliation Item", self.voucher_detail_no, "qty") > 0
):
return

batches = [d.batch_no for d in self.entries if d.batch_no]
if not batches:
return
Expand Down
73 changes: 50 additions & 23 deletions erpnext/stock/serial_batch_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,6 @@ def post_process(self):
):
self.set_batch_no_in_serial_nos()

if self.item_details.has_batch_no == 1:
self.update_batch_qty()

if self.sle.is_cancelled and self.sle.serial_and_batch_bundle:
self.cancel_serial_and_batch_bundle()

Expand Down Expand Up @@ -410,26 +407,6 @@ def set_batch_no_in_serial_nos(self):
.where(sn_table.name.isin(serial_nos))
).run()

def update_batch_qty(self):
from erpnext.stock.doctype.batch.batch import get_available_batches

batches = get_batch_nos(self.sle.serial_and_batch_bundle)
if not self.sle.serial_and_batch_bundle and self.sle.batch_no:
batches = frappe._dict({self.sle.batch_no: self.sle.actual_qty})

batches_qty = get_available_batches(
frappe._dict(
{
"item_code": self.item_code,
"batch_no": list(batches.keys()),
"consider_negative_batches": 1,
}
)
)

for batch_no in batches:
frappe.db.set_value("Batch", batch_no, "batch_qty", batches_qty.get(batch_no, 0))


def get_serial_nos(serial_and_batch_bundle, serial_nos=None):
if not serial_and_batch_bundle:
Expand Down Expand Up @@ -1258,3 +1235,53 @@ def get_serial_nos_batch(serial_nos):
as_list=1,
)
)


def update_batch_qty(voucher_type, voucher_no, via_landed_cost_voucher=False):
from erpnext.stock.doctype.batch.batch import get_available_batches

batches = get_distinct_batches(voucher_type, voucher_no)
if not batches:
return

precision = frappe.get_precision("Batch", "batch_qty")
batch_data = get_available_batches(
frappe._dict({"batch_no": batches, "consider_negative_batches": 1, "based_on_warehouse": True})
)
batchwise_qty = defaultdict(float)

for (batch_no, warehouse), qty in batch_data.items():
if not via_landed_cost_voucher and flt(qty, precision) < 0:
throw_negative_batch_validation(batch_no, warehouse, qty)

batchwise_qty[batch_no] += 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):
frappe.throw(
_("The Batch {0} has negative quantity {1} in warehouse {2}. Please correct the quantity.").format(
bold(batch_no), bold(qty), bold(warehouse)
),
title=_("Negative Batch Quantity"),
)


def get_distinct_batches(voucher_type, voucher_no):
bundles = frappe.get_all(
"Serial and Batch Bundle",
filters={"voucher_no": voucher_no, "voucher_type": voucher_type},
pluck="name",
)
if not bundles:
return

return frappe.get_all(
"Serial and Batch Entry",
filters={"parent": ("in", bundles), "batch_no": ("is", "set")},
group_by="batch_no",
pluck="batch_no",
)

0 comments on commit 8d63ab4

Please sign in to comment.