Merge pull request #48204 from rohitwaghchaure/fixed-stock-reservation-status

fix: stock reservation status
This commit is contained in:
rohitwaghchaure
2025-06-23 20:57:08 +05:30
committed by GitHub
7 changed files with 44 additions and 28 deletions

View File

@@ -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

View File

@@ -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"),

View File

@@ -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",

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

View File

@@ -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")