fix(stock): include subcontracting order qty while calculating the bin qty

This commit is contained in:
Sudharsanan11
2026-02-01 10:42:33 +05:30
parent 54d96bb761
commit de8f8ef9f4
2 changed files with 62 additions and 35 deletions

View File

@@ -3,6 +3,7 @@
import frappe
from frappe.query_builder.functions import Coalesce, Sum
from frappe.utils import cstr, flt, now, nowdate, nowtime
from erpnext.controllers.stock_controller import create_repost_item_valuation_entry
@@ -182,18 +183,67 @@ def get_indented_qty(item_code, warehouse):
def get_ordered_qty(item_code, warehouse):
ordered_qty = frappe.db.sql(
"""
select sum((po_item.qty - po_item.received_qty)*po_item.conversion_factor)
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
where po_item.item_code=%s and po_item.warehouse=%s
and po_item.qty > po_item.received_qty and po_item.parent=po.name
and po.status not in ('Closed', 'Delivered') and po.docstatus=1
and po_item.delivered_by_supplier = 0""",
(item_code, warehouse),
"""Return total pending ordered quantity for an item in a warehouse.
Includes outstanding quantities from Purchase Orders and Subcontracting Orders"""
purchase_order_qty = get_purchase_order_qty(item_code, warehouse)
subcontracting_order_qty = get_subcontracting_order_qty(item_code, warehouse)
return flt(purchase_order_qty) + flt(subcontracting_order_qty)
def get_purchase_order_qty(item_code, warehouse):
PurchaseOrder = frappe.qb.DocType("Purchase Order")
PurchaseOrderItem = frappe.qb.DocType("Purchase Order Item")
purchase_order_qty = (
frappe.qb.from_(PurchaseOrderItem)
.join(PurchaseOrder)
.on(PurchaseOrderItem.parent == PurchaseOrder.name)
.select(
Sum(
(PurchaseOrderItem.qty - PurchaseOrderItem.received_qty) * PurchaseOrderItem.conversion_factor
)
)
.where(
(PurchaseOrderItem.item_code == item_code)
& (PurchaseOrderItem.warehouse == warehouse)
& (PurchaseOrderItem.qty > PurchaseOrderItem.received_qty)
& (PurchaseOrder.status.notin(["Closed", "Delivered"]))
& (PurchaseOrder.docstatus == 1)
& (Coalesce(PurchaseOrderItem.delivered_by_supplier, 0) == 0)
)
.run()
)
return flt(ordered_qty[0][0]) if ordered_qty else 0
return purchase_order_qty[0][0] if purchase_order_qty else 0
def get_subcontracting_order_qty(item_code, warehouse):
SubcontractingOrder = frappe.qb.DocType("Subcontracting Order")
SubcontractingOrderItem = frappe.qb.DocType("Subcontracting Order Item")
subcontracting_order_qty = (
frappe.qb.from_(SubcontractingOrderItem)
.join(SubcontractingOrder)
.on(SubcontractingOrderItem.parent == SubcontractingOrder.name)
.select(
Sum(
(SubcontractingOrderItem.qty - SubcontractingOrderItem.received_qty)
* SubcontractingOrderItem.conversion_factor
)
)
.where(
(SubcontractingOrderItem.item_code == item_code)
& (SubcontractingOrderItem.warehouse == warehouse)
& (SubcontractingOrderItem.qty > SubcontractingOrderItem.received_qty)
& (SubcontractingOrder.status.notin(["Closed", "Completed"]))
& (SubcontractingOrder.docstatus == 1)
)
.run()
)
return subcontracting_order_qty[0][0] if subcontracting_order_qty else 0
def get_planned_qty(item_code, warehouse):

View File

@@ -12,7 +12,7 @@ from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry impor
StockReservation,
has_reserved_stock,
)
from erpnext.stock.stock_balance import update_bin_qty
from erpnext.stock.stock_balance import get_ordered_qty, update_bin_qty
from erpnext.stock.utils import get_bin
@@ -234,30 +234,7 @@ class SubcontractingOrder(SubcontractingController):
):
item_wh_list.append([item.item_code, item.warehouse])
for item_code, warehouse in item_wh_list:
update_bin_qty(item_code, warehouse, {"ordered_qty": self.get_ordered_qty(item_code, warehouse)})
@staticmethod
def get_ordered_qty(item_code, warehouse):
table = frappe.qb.DocType("Subcontracting Order")
child = frappe.qb.DocType("Subcontracting Order Item")
query = (
frappe.qb.from_(table)
.inner_join(child)
.on(table.name == child.parent)
.select((child.qty - child.received_qty) * child.conversion_factor)
.where(
(table.docstatus == 1)
& (child.item_code == item_code)
& (child.warehouse == warehouse)
& (child.qty > child.received_qty)
& (table.status != "Completed")
)
)
query = query.run()
return flt(query[0][0]) if query else 0
update_bin_qty(item_code, warehouse, {"ordered_qty": get_ordered_qty(item_code, warehouse)})
def update_reserved_qty_for_subcontracting(self, sco_item_rows=None):
for item in self.supplied_items: