Merge pull request #50235 from mihir-kandoi/sre-sco

feat: stock reservation for subcontracting order
This commit is contained in:
Mihir Kandoi
2025-11-16 13:06:21 +05:30
committed by GitHub
parent 4bd3b00e5f
commit 9b303a2272
25 changed files with 895 additions and 209 deletions

View File

@@ -556,131 +556,6 @@ class SubcontractingInwardController:
item.basic_rate + (item.additional_cost / item.transfer_qty), item.precision("basic_rate")
)
def update_sre_for_subcontracting_delivery(self) -> None:
if self.purpose == "Subcontracting Delivery":
if self._action == "submit":
self.update_sre_for_subcontracting_delivery_submit()
elif self._action == "cancel":
self.update_sre_for_subcontracting_delivery_cancel()
def update_sre_for_subcontracting_delivery_submit(self):
for item in self.get("items"):
table = frappe.qb.DocType("Stock Reservation Entry")
query = (
frappe.qb.from_(table)
.select(table.name)
.where(
(table.docstatus == 1)
& (table.voucher_type == "Subcontracting Inward Order")
& (table.voucher_no == self.subcontracting_inward_order)
& (table.voucher_detail_no == item.scio_detail)
)
.orderby(table.creation)
)
sre_list = query.run(pluck="name")
if not sre_list:
continue
qty_to_deliver = item.transfer_qty
for sre in sre_list:
if qty_to_deliver <= 0:
break
sre_doc = frappe.get_doc("Stock Reservation Entry", sre)
qty_can_be_deliver = 0
if sre_doc.reservation_based_on == "Serial and Batch":
sbb = frappe.get_doc("Serial and Batch Bundle", item.serial_and_batch_bundle)
if sre_doc.has_serial_no:
delivered_serial_nos = [d.serial_no for d in sbb.entries]
for entry in sre_doc.sb_entries:
if entry.serial_no in delivered_serial_nos:
entry.delivered_qty = 1
entry.db_update()
qty_can_be_deliver += 1
delivered_serial_nos.remove(entry.serial_no)
else:
delivered_batch_qty = {d.batch_no: -1 * d.qty for d in sbb.entries}
for entry in sre_doc.sb_entries:
if entry.batch_no in delivered_batch_qty:
delivered_qty = min(
(entry.qty - entry.delivered_qty),
delivered_batch_qty[entry.batch_no],
)
entry.delivered_qty += delivered_qty
entry.db_update()
qty_can_be_deliver += delivered_qty
delivered_batch_qty[entry.batch_no] -= delivered_qty
else:
qty_can_be_deliver = min((sre_doc.reserved_qty - sre_doc.delivered_qty), qty_to_deliver)
sre_doc.delivered_qty += qty_can_be_deliver
sre_doc.db_update()
sre_doc.update_status()
sre_doc.update_reserved_stock_in_bin()
qty_to_deliver -= qty_can_be_deliver
def update_sre_for_subcontracting_delivery_cancel(self):
for item in self.get("items"):
table = frappe.qb.DocType("Stock Reservation Entry")
query = (
frappe.qb.from_(table)
.select(table.name)
.where(
(table.docstatus == 1)
& (table.voucher_type == "Subcontracting Inward Order")
& (table.voucher_no == self.subcontracting_inward_order)
& (table.voucher_detail_no == item.scio_detail)
& (table.warehouse == item.s_warehouse)
)
.orderby(table.creation)
)
sre_list = query.run(pluck="name")
if not sre_list:
continue
qty_to_undelivered = item.transfer_qty
for sre in sre_list:
if qty_to_undelivered <= 0:
break
sre_doc = frappe.get_doc("Stock Reservation Entry", sre)
qty_can_be_undelivered = 0
if sre_doc.reservation_based_on == "Serial and Batch":
sbb = frappe.get_doc("Serial and Batch Bundle", item.serial_and_batch_bundle)
if sre_doc.has_serial_no:
serial_nos_to_undelivered = [d.serial_no for d in sbb.entries]
for entry in sre_doc.sb_entries:
if entry.serial_no in serial_nos_to_undelivered:
entry.delivered_qty = 0
entry.db_update()
qty_can_be_undelivered += 1
serial_nos_to_undelivered.remove(entry.serial_no)
else:
batch_qty_to_undelivered = {d.batch_no: -1 * d.qty for d in sbb.entries}
for entry in sre_doc.sb_entries:
if entry.batch_no in batch_qty_to_undelivered:
undelivered_qty = min(
entry.delivered_qty, batch_qty_to_undelivered[entry.batch_no]
)
entry.delivered_qty -= undelivered_qty
entry.db_update()
qty_can_be_undelivered += undelivered_qty
batch_qty_to_undelivered[entry.batch_no] -= undelivered_qty
else:
qty_can_be_undelivered = min(sre_doc.delivered_qty, qty_to_undelivered)
sre_doc.delivered_qty -= qty_can_be_undelivered
sre_doc.db_update()
sre_doc.update_status()
sre_doc.update_reserved_stock_in_bin()
qty_to_undelivered -= qty_can_be_undelivered
def validate_receive_from_customer_cancel(self):
if self.purpose == "Receive from Customer":
for item in self.items: