Merge pull request #48204 from rohitwaghchaure/fixed-stock-reservation-status
fix: stock reservation status
This commit is contained in:
@@ -884,6 +884,9 @@ class ProductionPlan(Document):
|
||||
|
||||
wo = frappe.new_doc("Work Order")
|
||||
wo.update(item)
|
||||
if not wo.source_warehouse:
|
||||
wo.source_warehouse = item.get("fg_warehouse")
|
||||
|
||||
wo.reserve_stock = self.reserve_stock
|
||||
wo.planned_start_date = item.get("planned_start_date") or item.get("schedule_date")
|
||||
|
||||
@@ -891,7 +894,7 @@ class ProductionPlan(Document):
|
||||
wo.fg_warehouse = item.get("warehouse")
|
||||
|
||||
wo.set_work_order_operations()
|
||||
wo.set_required_items()
|
||||
wo.set_required_items(reset_source_warehouse=True)
|
||||
|
||||
try:
|
||||
wo.flags.ignore_mandatory = True
|
||||
|
||||
@@ -1213,7 +1213,7 @@ class WorkOrder(Document):
|
||||
if self.wip_warehouse:
|
||||
d.available_qty_at_wip_warehouse = get_latest_stock_qty(d.item_code, self.wip_warehouse)
|
||||
|
||||
def set_required_items(self, reset_only_qty=False):
|
||||
def set_required_items(self, reset_only_qty=False, reset_source_warehouse=False):
|
||||
"""set required_items for production to keep track of reserved qty"""
|
||||
if not reset_only_qty:
|
||||
self.required_items = []
|
||||
@@ -1247,7 +1247,9 @@ class WorkOrder(Document):
|
||||
"description": item.description,
|
||||
"allow_alternative_item": item.allow_alternative_item,
|
||||
"required_qty": item.qty,
|
||||
"source_warehouse": item.source_warehouse or item.default_warehouse,
|
||||
"source_warehouse": (item.source_warehouse or item.default_warehouse)
|
||||
if not reset_source_warehouse
|
||||
else self.source_warehouse,
|
||||
"include_item_in_manufacturing": item.include_item_in_manufacturing,
|
||||
"operation_row_id": item.operation_row_id,
|
||||
},
|
||||
@@ -1295,22 +1297,37 @@ class WorkOrder(Document):
|
||||
self.update_qty_in_stock_reservation(row, transferred_qty, row_wise_serial_batch)
|
||||
|
||||
def update_qty_in_stock_reservation(self, row, transferred_qty, row_wise_serial_batch):
|
||||
if name := frappe.db.get_value(
|
||||
if names := frappe.get_all(
|
||||
"Stock Reservation Entry",
|
||||
{
|
||||
filters={
|
||||
"voucher_no": self.name,
|
||||
"item_code": row.item_code,
|
||||
"voucher_detail_no": row.name,
|
||||
"warehouse": row.source_warehouse,
|
||||
},
|
||||
"name",
|
||||
pluck="name",
|
||||
):
|
||||
doc = frappe.get_doc("Stock Reservation Entry", name)
|
||||
doc.db_set("transferred_qty", flt(transferred_qty), update_modified=False)
|
||||
if (doc.has_batch_no or doc.has_serial_no) and doc.reservation_based_on == "Serial and Batch":
|
||||
doc.consume_serial_batch_for_material_transfer(row_wise_serial_batch)
|
||||
doc.update_status()
|
||||
doc.update_reserved_stock_in_bin()
|
||||
for name in names:
|
||||
doc = frappe.get_doc("Stock Reservation Entry", name)
|
||||
qty_to_update = 0.0
|
||||
if transferred_qty <= 0:
|
||||
continue
|
||||
|
||||
if transferred_qty > flt(doc.reserved_qty - doc.consumed_qty):
|
||||
qty_to_update = doc.reserved_qty - doc.transferred_qty
|
||||
transferred_qty -= qty_to_update
|
||||
else:
|
||||
qty_to_update = transferred_qty
|
||||
transferred_qty = 0.0
|
||||
|
||||
if qty_to_update <= 0:
|
||||
continue
|
||||
|
||||
doc.db_set("transferred_qty", flt(qty_to_update), update_modified=False)
|
||||
if (doc.has_batch_no or doc.has_serial_no) and doc.reservation_based_on == "Serial and Batch":
|
||||
doc.consume_serial_batch_for_material_transfer(row_wise_serial_batch)
|
||||
doc.update_status()
|
||||
doc.update_reserved_stock_in_bin()
|
||||
|
||||
def update_returned_qty(self):
|
||||
ste = frappe.qb.DocType("Stock Entry")
|
||||
@@ -2167,8 +2184,8 @@ def create_job_card(work_order, row, enable_capacity_planning=False, auto_create
|
||||
"hour_rate": row.get("hour_rate"),
|
||||
"serial_no": row.get("serial_no"),
|
||||
"time_required": row.get("time_in_mins"),
|
||||
"source_warehouse": row.get("source_warehouse"),
|
||||
"target_warehouse": row.get("fg_warehouse"),
|
||||
"source_warehouse": row.get("source_warehouse") or work_order.get("source_warehouse"),
|
||||
"target_warehouse": row.get("fg_warehouse") or work_order.get("fg_warehouse"),
|
||||
"wip_warehouse": work_order.wip_warehouse or row.get("wip_warehouse")
|
||||
if not work_order.skip_transfer or work_order.from_wip_warehouse
|
||||
else work_order.source_warehouse or row.get("source_warehouse"),
|
||||
|
||||
@@ -953,7 +953,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-05-31 18:51:32.651562",
|
||||
"modified": "2025-05-31 19:51:32.651562",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note Item",
|
||||
|
||||
@@ -1923,9 +1923,10 @@ def get_reserved_serial_nos(kwargs) -> list:
|
||||
if not reserved_entries:
|
||||
return ignore_serial_nos, consider_serial_nos
|
||||
|
||||
reserved_voucher_details = get_reserved_voucher_details(kwargs)
|
||||
if not reserved_voucher_details:
|
||||
return ignore_serial_nos, consider_serial_nos
|
||||
if kwargs.get("sabb_voucher_type") == "Delivery Note" and kwargs.get("against_sales_order"):
|
||||
reserved_voucher_details = [kwargs.get("against_sales_order")]
|
||||
else:
|
||||
reserved_voucher_details = get_reserved_voucher_details(kwargs)
|
||||
|
||||
serial_nos = []
|
||||
for entry in reserved_entries:
|
||||
|
||||
@@ -1156,7 +1156,7 @@ class StockReservation:
|
||||
sre.voucher_no = item.get("voucher_no") or self.doc.name
|
||||
sre.voucher_detail_no = item.get(child_doctype) or item.name or item.get("voucher_detail_no")
|
||||
sre.available_qty = self.available_qty_to_reserve
|
||||
sre.voucher_qty = qty
|
||||
sre.voucher_qty = self.qty_to_be_reserved
|
||||
sre.reserved_qty = self.qty_to_be_reserved
|
||||
sre.company = self.doc.company
|
||||
sre.stock_uom = item_details.stock_uom
|
||||
|
||||
@@ -365,17 +365,9 @@ class TestStockReservationEntry(IntegrationTestCase):
|
||||
dn2 = make_delivery_note(so.name)
|
||||
|
||||
for item in dn2.items:
|
||||
item.qty = 80
|
||||
item.qty = 70
|
||||
|
||||
dn2.save()
|
||||
for row in dn2.items:
|
||||
if row.item_code in item_wise_serial_nos:
|
||||
consumed_serial_no = ", ".join(item_wise_serial_nos[row.item_code])
|
||||
picked_serial_no = get_serial_nos(row.serial_no)
|
||||
|
||||
serial_nos = list(set(picked_serial_no) - set(consumed_serial_no))
|
||||
row.serial_no = "\n".join(serial_nos)
|
||||
|
||||
dn2.submit()
|
||||
|
||||
for item in so.items:
|
||||
|
||||
@@ -208,6 +208,9 @@ def update_stock(ctx, out, doc=None):
|
||||
}
|
||||
)
|
||||
|
||||
if ctx.get("doctype") == "Delivery Note":
|
||||
kwargs["against_sales_order"] = ctx.get("against_sales_order")
|
||||
|
||||
if ctx.get("ignore_serial_nos"):
|
||||
kwargs["ignore_serial_nos"] = ctx.get("ignore_serial_nos")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user