fix: feat: multiple changes related to subcontracting inward

This commit is contained in:
Mihir Kandoi
2025-10-21 23:50:28 +05:30
parent d9fa9c6b3d
commit 9f3cb4b783
16 changed files with 525 additions and 168 deletions

View File

@@ -9,7 +9,7 @@ from erpnext.stock.serial_batch_bundle import get_serial_batch_list_from_item
class SubcontractingInwardController:
def validate_subcontracting_inward(self):
self.validate_inward_order()
self.validate_customer_provided_item_for_inward()
self.set_allow_zero_valuation_rate()
self.validate_warehouse_()
self.validate_serial_batch_for_return_or_delivery()
self.validate_delivery()
@@ -50,11 +50,22 @@ class SubcontractingInwardController:
self.validate_material_receipt()
case purpose if purpose in ["Return Raw Material to Customer", "Subcontracting Return"]:
self.validate_returns()
case "Material Transfer for Manufacture":
self.validate_material_transfer()
case "Manufacture":
self.validate_manufacture()
def validate_material_receipt(self):
rm_item_fg_combo = []
for item in self.items:
if not frappe.get_cached_value("Item", item.item_code, "is_customer_provided_item"):
frappe.throw(
_("Row #{0}: Item {1} is not a Customer Provided Item.").format(
item.idx,
get_link_to_form("Item", item.item_code),
)
)
if (
item.scio_detail
and frappe.get_cached_value(
@@ -65,17 +76,44 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Item {1} mismatch. Changing of item code is not permitted, add another row instead."
).format(item.idx, bold(item.item_code))
).format(item.idx, get_link_to_form("Item", item.item_code))
)
if not item.scio_detail: # item is additional
if item.against_fg:
if (item.item_code, item.against_fg) not in rm_item_fg_combo:
rm_item_fg_combo.append((item.item_code, item.against_fg))
else:
frappe.throw(
_(
"Row #{0}: Customer Provided Item {1} against Subcontracting Inward Order Item {2} ({3}) cannot be added multiple times."
).format(
item.idx,
get_link_to_form("Item", item.item_code),
bold(item.against_fg),
get_link_to_form(
"Item",
frappe.get_cached_value(
"Subcontracting Inward Order Item", item.against_fg, "item_code"
),
),
)
)
else:
frappe.throw(
_(
"Row #{0}: Please select the Finished Good Item against which this Customer Provided Item will be used."
).format(item.idx)
)
def validate_returns(self):
for item in self.items:
if not item.scio_detail:
frappe.throw(
_("Row #{0}: Item {1} is not a part of Subcontracting Inward Order {2}").format(
item.idx,
bold(item.item_code),
bold(self.subcontracting_inward_order),
get_link_to_form("Item", item.item_code),
get_link_to_form("Subcontracting Inward Order", self.subcontracting_inward_order),
)
)
elif item.item_code != (
@@ -86,7 +124,7 @@ class SubcontractingInwardController:
):
frappe.throw(
_("Row #{0}: Item {1} mismatch. Changing of item code is not permitted.").format(
item.idx, bold(item.item_code)
item.idx, get_link_to_form("Item", item.item_code)
)
)
@@ -101,7 +139,7 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Returned quantity cannot be greater than available quantity for Item {1}"
).format(item.idx, bold(item.item_code))
).format(item.idx, get_link_to_form("Item", item.item_code))
)
else:
data = frappe.get_value(
@@ -114,16 +152,88 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Returned quantity cannot be greater than available quantity to return for Item {1}"
).format(item.idx, bold(item.item_code))
).format(item.idx, get_link_to_form("Item", item.item_code))
)
def validate_material_transfer(self):
customer_warehouse = frappe.get_cached_value(
"Subcontracting Inward Order", self.subcontracting_inward_order, "customer_warehouse"
)
item_codes = []
for item in self.items:
if not frappe.get_cached_value("Item", item.item_code, "is_customer_provided_item"):
continue
elif item.s_warehouse != customer_warehouse:
frappe.throw(
_("Row #{0}: For Customer Provided Item {1}, Source Warehouse must be {2}").format(
item.idx,
get_link_to_form("Item", item.item_code),
get_link_to_form("Warehouse", customer_warehouse),
)
)
elif item.item_code in item_codes:
frappe.throw(
_(
"Row #{0}: Customer Provided Item {1} cannot be added multiple times in the Subcontracting Inward process."
).format(
item.idx,
get_link_to_form("Item", item.item_code),
)
)
else:
work_order_items = frappe.get_all(
"Work Order Item",
{"parent": self.work_order, "docstatus": 1, "is_customer_provided_item": 1},
["item_code", "transferred_qty", "required_qty", "stock_reserved_qty"],
)
wo_item_dict = frappe._dict(
{
wo_item.item_code: frappe._dict(
{
"transferred_qty": wo_item.transferred_qty,
"required_qty": wo_item.required_qty,
"stock_reserved_qty": wo_item.stock_reserved_qty,
}
)
for wo_item in work_order_items
}
)
if wo_item := wo_item_dict.get(item.item_code):
if wo_item.transferred_qty + item.transfer_qty > max(
wo_item.required_qty, wo_item.stock_reserved_qty
):
frappe.throw(
_(
"Row #{0}: Overconsumption of Customer Provided Item {1} against Work Order {2} is not allowed in the Subcontracting Inward process."
).format(
item.idx,
get_link_to_form("Item", item.item_code),
get_link_to_form("Work Order", self.work_order),
)
)
else:
item_codes.append(item.item_code)
else:
frappe.throw(
_("Row #{0}: Customer Provided Item {1} is not a part of Work Order {2}").format(
item.idx,
get_link_to_form("Item", item.item_code),
get_link_to_form("Work Order", self.work_order),
)
)
def validate_manufacture(self):
skip_transfer, customer_warehouse, wip_warehouse = frappe.get_cached_value(
"Work Order",
self.work_order,
["skip_transfer", "source_warehouse", "wip_warehouse"],
)
warehouse = customer_warehouse if skip_transfer else wip_warehouse
if next(item for item in self.items if item.is_finished_item).t_warehouse != (
fg_warehouse := frappe.get_cached_value("Work Order", self.work_order, "fg_warehouse")
):
frappe.throw(
_(
"Target Warehouse for Finished Good must be same as Finished Good Warehouse {1} in Work Order {2} linked to the Subcontracting Inward Order."
).format(
get_link_to_form("Warehouse", fg_warehouse),
get_link_to_form("Work Order", self.work_order),
)
)
items = [
item
@@ -133,74 +243,133 @@ class SubcontractingInwardController:
and frappe.get_cached_value("Item", item.item_code, "is_customer_provided_item")
]
table = frappe.qb.DocType("Subcontracting Inward Order Received Item")
query = (
frappe.qb.from_(table)
.select(
table.rm_item_code,
(table.received_qty - table.returned_qty).as_("total_qty"),
table.consumed_qty,
table.name,
)
.where(
(table.docstatus == 1)
& (table.parent == self.subcontracting_inward_order)
& (table.main_item_code == frappe.get_cached_value("BOM", self.bom_no, "item"))
& (table.warehouse == warehouse)
& (table.rm_item_code.isin([item.item_code for item in items]))
)
customer_warehouse = frappe.get_cached_value(
"Subcontracting Inward Order", self.subcontracting_inward_order, "customer_warehouse"
)
rm_item_dict = frappe._dict(
{
d.rm_item_code: frappe._dict(
{"name": d.name, "total_qty": d.total_qty, "qty": d.consumed_qty}
if frappe.get_cached_value("Work Order", self.work_order, "skip_transfer"):
table = frappe.qb.DocType("Subcontracting Inward Order Received Item")
query = (
frappe.qb.from_(table)
.select(
table.rm_item_code,
(table.received_qty - table.returned_qty).as_("total_qty"),
table.consumed_qty,
table.name,
)
for d in query.run(as_dict=True)
}
)
for item in items:
if rm := rm_item_dict.get(item.item_code):
if rm.qty + item.transfer_qty > rm.total_qty:
frappe.throw(
_(
"Row #{0}: Customer Provided Item {1} exceeds quantity available through Subcontracting Inward Order"
).format(item.idx, bold(item.item_code), item.transfer_qty)
)
elif item.s_warehouse != warehouse:
frappe.throw(
_("Row #{0}: For Customer Provided Item {1}, Source Warehouse must be {2}").format(
item.idx,
bold(item.item_code),
bold(warehouse),
.where(
(table.docstatus == 1)
& (table.parent == self.subcontracting_inward_order)
& (
table.reference_name
== frappe.get_cached_value(
"Work Order", self.work_order, "subcontracting_inward_order_item"
)
)
else:
frappe.throw(
_(
"Row #{0}: Customer Provided Item {1} is not a part of Subcontracting Inward Order {2}"
).format(
item.idx,
bold(item.item_code),
bold(self.subcontracting_inward_order),
)
& (table.rm_item_code.isin([item.item_code for item in items]))
)
)
rm_item_dict = frappe._dict(
{
d.rm_item_code: frappe._dict(
{"name": d.name, "total_qty": d.total_qty, "qty": d.consumed_qty}
)
for d in query.run(as_dict=True)
}
)
def validate_customer_provided_item_for_inward(self):
if self.subcontracting_inward_order:
if self.purpose in ["Subcontracting Delivery", "Subcontracting Return"]:
for item in self.items:
if (item.is_finished_item or item.is_scrap_item) and item.valuation_rate == 0:
item.allow_zero_valuation_rate = 1
elif self.purpose == "Receive from Customer":
for item in self.items:
if not frappe.get_cached_value("Item", item.item_code, "is_customer_provided_item"):
item_codes = []
for item in items:
if rm := rm_item_dict.get(item.item_code):
if rm.qty + item.transfer_qty > rm.total_qty:
frappe.throw(
_("Row #{0}: Item {1} is not a customer provided item.").format(
_(
"Row #{0}: Customer Provided Item {1} exceeds quantity available through Subcontracting Inward Order"
).format(item.idx, get_link_to_form("Item", item.item_code), item.transfer_qty)
)
elif item.s_warehouse != customer_warehouse:
frappe.throw(
_(
"Row #{0}: For Customer Provided Item {1}, Source Warehouse must be {2}"
).format(
item.idx,
get_link_to_form("Item", item.item_code),
get_link_to_form("Warehouse", customer_warehouse),
)
)
elif item.item_code in item_codes:
frappe.throw(
_(
"Row #{0}: Customer Provided Item {1} cannot be added multiple times in the Subcontracting Inward process."
).format(
item.idx,
get_link_to_form("Item", item.item_code),
)
)
else:
item_codes.append(item.item_code)
else:
frappe.throw(
_(
"Row #{0}: Customer Provided Item {1} is not a part of Subcontracting Inward Order {2}"
).format(
item.idx,
get_link_to_form("Item", item.item_code),
get_link_to_form("Subcontracting Inward Order", self.subcontracting_inward_order),
)
)
else:
work_order_items = frappe.get_all(
"Work Order Item",
{"parent": self.work_order, "docstatus": 1, "is_customer_provided_item": 1},
["item_code", "transferred_qty", "consumed_qty"],
)
wo_item_dict = frappe._dict(
{
wo_item.item_code: frappe._dict(
{"transferred_qty": wo_item.transferred_qty, "consumed_qty": wo_item.consumed_qty}
)
for wo_item in work_order_items
}
)
item_codes = []
for item in items:
if wo_item := wo_item_dict.get(item.item_code):
if wo_item.consumed_qty + item.transfer_qty > wo_item.transferred_qty:
frappe.throw(
_(
"Row #{0}: Overconsumption of Customer Provided Item {1} against Work Order {2} is not allowed in the Subcontracting Inward process."
).format(
item.idx,
get_link_to_form("Item", item.item_code),
get_link_to_form("Work Order", self.work_order),
)
)
elif item.item_code in item_codes:
frappe.throw(
_(
"Row #{0}: Customer Provided Item {1} cannot be added multiple times in the Subcontracting Inward process."
).format(
item.idx,
get_link_to_form("Item", item.item_code),
)
)
else:
item_codes.append(item.item_code)
else:
frappe.throw(
_("Row #{0}: Customer Provided Item {1} is not a part of Work Order {2}").format(
item.idx,
get_link_to_form("Item", item.item_code),
get_link_to_form("Work Order", self.work_order),
)
)
def set_allow_zero_valuation_rate(self):
if self.subcontracting_inward_order:
if self.purpose in ["Subcontracting Delivery", "Subcontracting Return", "Manufacture"]:
for item in self.items:
if (item.is_finished_item or item.is_scrap_item) and item.valuation_rate == 0:
item.allow_zero_valuation_rate = 1
def validate_warehouse_(self):
if self.subcontracting_inward_order and self.purpose in [
@@ -222,13 +391,13 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Target Warehouse must be same as Customer Warehouse {1} from the linked Subcontracting Inward Order"
).format(item.idx, bold(customer_warehouse))
).format(item.idx, get_link_to_form("Warehouse", customer_warehouse))
)
else:
frappe.throw(
_(
"Row #{0}: Source Warehouse must be same as Customer Warehouse {1} from the linked Subcontracting Inward Order"
).format(item.idx, bold(customer_warehouse))
).format(item.idx, get_link_to_form("Warehouse", customer_warehouse))
)
def validate_serial_batch_for_return_or_delivery(self):
@@ -249,7 +418,10 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Serial No(s) {1} are not a part of the linked Subcontracting Inward Order. Please select valid Serial No(s)."
).format(item.idx, ", ".join([bold(sn) for sn in incorrect_serial_nos]))
).format(
item.idx,
", ".join([get_link_to_form("Serial No", sn) for sn in incorrect_serial_nos]),
)
)
if batch_list and (
incorrect_batch_nos := [bn for bn in batch_list if bn not in list(batch_nos.keys())]
@@ -257,7 +429,10 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Batch No(s) {1} is not a part of the linked Subcontracting Inward Order. Please select valid Batch No(s)."
).format(item.idx, ", ".join([bold(bn) for bn in incorrect_batch_nos]))
).format(
item.idx,
", ".join([get_link_to_form("Batch No", bn) for bn in incorrect_batch_nos]),
)
)
def get_serial_nos_and_batches_from_sres(self, scio_detail, only_pending=True):
@@ -302,7 +477,7 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Cannot cancel this Stock Entry as returned quantity cannot be greater than delivered quantity for Item {1} in the linked Subcontracting Inward Order"
).format(item.idx, bold(item.item_code))
).format(item.idx, get_link_to_form("Item", item.item_code))
)
def validate_delivery_on_save(self):
@@ -315,8 +490,8 @@ class SubcontractingInwardController:
frappe.throw(
_("Row #{0}: Item {1} is not a part of Subcontracting Inward Order {2}").format(
item.idx,
bold(item.item_code),
bold(self.subcontracting_inward_order),
get_link_to_form("Item", item.item_code),
get_link_to_form("Subcontracting Inward Order", self.subcontracting_inward_order),
)
)
@@ -359,7 +534,7 @@ class SubcontractingInwardController:
"Row #{0}: Quantity of Item {1} cannot be more than {2} {3} against Subcontracting Inward Order {4}"
).format(
item.idx,
bold(item.item_code),
get_link_to_form("Item", item.item_code),
bold(max_allowed_qty),
bold(
frappe.get_cached_value(
@@ -370,7 +545,7 @@ class SubcontractingInwardController:
"stock_uom",
)
),
bold(self.subcontracting_inward_order),
get_link_to_form("Subcontracting Inward Order", self.subcontracting_inward_order),
)
)
@@ -400,7 +575,6 @@ class SubcontractingInwardController:
& (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)
)
@@ -522,7 +696,7 @@ class SubcontractingInwardController:
) < scio_rm_item.work_order_qty:
frappe.throw(
_("Row #{0}: Work Order exists against full or partial quantity of Item {1}").format(
item.idx, bold(item.item_code)
item.idx, get_link_to_form("Item", item.item_code)
)
)
@@ -561,7 +735,7 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Cannot cancel this Manufacturing Stock Entry as quantity of Scrap Item {1} produced cannot be less than quantity delivered."
).format(item.idx, bold(item.item_code))
).format(item.idx, get_link_to_form("Item", item.item_code))
)
else:
scio_rm_item = frappe.get_value(
@@ -570,7 +744,7 @@ class SubcontractingInwardController:
"docstatus": 1,
"rm_item_code": item.item_code,
"warehouse": item.s_warehouse,
"reference_name": fg_item_name, # if this field is set then the additional item is NOT customer provided
"is_customer_provided_item": 0,
"is_additional_item": 1,
},
["consumed_qty", "billed_qty", "returned_qty"],
@@ -582,7 +756,7 @@ class SubcontractingInwardController:
frappe.throw(
_(
"Row #{0}: Cannot cancel this Manufacturing Stock Entry as billed quantity of Item {1} cannot be greater than consumed quantity."
).format(item.idx, bold(item.item_code))
).format(item.idx, get_link_to_form("Item", item.item_code))
)
def update_inward_order_item(self):
@@ -638,7 +812,9 @@ class SubcontractingInwardController:
data = frappe._dict()
for item in self.items:
if item.scio_detail:
data[item.scio_detail] = item.transfer_qty if self._action == "submit" else -item.transfer_qty
data[item.scio_detail] = frappe._dict(
{"transfer_qty": item.transfer_qty, "rate": item.customer_provided_item_cost}
)
else:
scio_rm = frappe.new_doc(
"Subcontracting Inward Order Received Item",
@@ -657,9 +833,16 @@ class SubcontractingInwardController:
consumed_qty=0,
work_order_qty=0,
returned_qty=0,
rate=item.customer_provided_item_cost,
is_customer_provided_item=True,
is_additional_item=True,
reference_name=item.against_fg,
main_item_code=frappe.get_cached_value(
"Subcontracting Inward Order Item", item.against_fg, "item_code"
),
)
scio_rm.insert()
scio_rm.submit()
item.db_set("scio_detail", scio_rm.name)
if data:
@@ -670,39 +853,47 @@ class SubcontractingInwardController:
"name": ["in", list(data.keys())],
"docstatus": 1,
},
fields=["name", "required_qty", "received_qty"],
fields=["rate", "name", "required_qty", "received_qty"],
)
deleted_docs = []
table = frappe.qb.DocType("Subcontracting Inward Order Received Item")
case_expr = Case()
case_expr_qty, case_expr_rate = Case(), Case()
for d in result:
d.received_qty += data[d.name]
d.received_qty += (
data[d.name].transfer_qty if self._action == "submit" else -data[d.name].transfer_qty
)
d.rate += data[d.name].rate if self._action == "submit" else -data[d.name].rate
if not d.required_qty and not d.received_qty:
deleted_docs.append(d.name)
frappe.delete_doc("Subcontracting Inward Order Received Item", d.name)
else:
case_expr = case_expr.when(table.name == d.name, d.received_qty)
case_expr_qty = case_expr_qty.when(table.name == d.name, d.received_qty)
case_expr_rate = case_expr_rate.when(table.name == d.name, d.rate)
if len(list(set(data.keys()) - set(deleted_docs))) > 0:
frappe.qb.update(table).set(table.received_qty, case_expr).where(
(table.name.isin(list(set(data.keys()) - set(deleted_docs)))) & (table.docstatus == 1)
).run()
if final_list := list(set(data.keys()) - set(deleted_docs)):
frappe.qb.update(table).set(table.received_qty, case_expr_qty).set(
table.rate, case_expr_rate
).where((table.name.isin(final_list)) & (table.docstatus == 1)).run()
def update_inward_order_received_items_for_manufacture(self):
customer_warehouse = frappe.get_cached_value(
"Subcontracting Inward Order", self.subcontracting_inward_order, "customer_warehouse"
)
items = [item for item in self.items if not item.is_finished_item and not item.is_scrap_item]
item_code_wh = frappe._dict(
{
(item.item_code, item.s_warehouse): item.transfer_qty
if self._action == "submit"
else -item.transfer_qty
(
item.item_code,
customer_warehouse
if frappe.get_cached_value("Item", item.item_code, "is_customer_provided_item")
else item.s_warehouse,
): item.transfer_qty if self._action == "submit" else -item.transfer_qty
for item in items
}
)
item_codes, warehouses = zip(*list(item_code_wh.keys()), strict=True)
item_codes = list(item_codes)
warehouses = list(warehouses)
table = frappe.qb.DocType("Subcontracting Inward Order Received Item")
data = (
@@ -712,22 +903,21 @@ class SubcontractingInwardController:
table.rm_item_code,
table.is_customer_provided_item,
table.consumed_qty,
table.required_qty,
table.warehouse,
table.is_additional_item,
)
.where(
(table.docstatus == 1)
& (table.rm_item_code.isin(item_codes))
& ((table.warehouse.isin(warehouses)) | (table.warehouse.isnull()))
& (table.rm_item_code.isin(list(set(item_codes))))
& (
(table.warehouse.isin(list(set(warehouses)))) | (table.warehouse.isnull())
) # warehouse will always be null for non additional self procured raw materials
& (table.parent == self.subcontracting_inward_order)
& (
(
table.reference_name
== frappe.get_cached_value(
"Work Order", self.work_order, "subcontracting_inward_order_item"
)
table.reference_name
== frappe.get_cached_value(
"Work Order", self.work_order, "subcontracting_inward_order_item"
)
| (table.reference_name.isnull())
)
)
)
@@ -745,25 +935,26 @@ class SubcontractingInwardController:
used_item_wh.append((d.rm_item_code, d.warehouse))
qty = d.consumed_qty + item_code_wh[(d.rm_item_code, d.warehouse)]
if qty or d.is_customer_provided_item:
if qty or d.is_customer_provided_item or not d.is_additional_item:
case_expr = case_expr.when((table.name == d.name), qty)
else:
deleted_docs.append(d.name)
frappe.delete_doc("Subcontracting Inward Order Received Item", d.name)
final_name_list = list(set([d.name for d in data]) - set(deleted_docs))
if len(final_name_list) > 0:
if final_list := list(set([d.name for d in data]) - set(deleted_docs)):
frappe.qb.update(table).set(table.consumed_qty, case_expr).where(
(table.name.isin(final_name_list)) & (table.docstatus == 1)
(table.name.isin(final_list)) & (table.docstatus == 1)
).run()
main_item_code = next(fg for fg in self.items if fg.is_finished_item).item_code
for extra_item in [
item
for item in items
if (item.item_code, item.s_warehouse) not in [(d.rm_item_code, d.warehouse) for d in data]
if not frappe.get_cached_value("Item", item.item_code, "is_customer_provided_item")
and (item.item_code, item.s_warehouse)
not in [(d.rm_item_code, d.warehouse) for d in data if not d.is_customer_provided_item]
]:
frappe.new_doc(
doc = frappe.new_doc(
"Subcontracting Inward Order Received Item",
parent=self.subcontracting_inward_order,
parenttype="Subcontracting Inward Order",
@@ -783,7 +974,9 @@ class SubcontractingInwardController:
consumed_qty=extra_item.transfer_qty,
warehouse=extra_item.s_warehouse,
is_additional_item=True,
).insert()
)
doc.insert()
doc.submit()
def update_inward_order_scrap_items(self):
if (scio := self.subcontracting_inward_order) and self.purpose == "Manufacture":
@@ -835,8 +1028,9 @@ class SubcontractingInwardController:
table.name == value.name, value.produced_qty + scrap_items.get(key)
)
final_list = list(set([v.name for v in scrap_item_dict.values()]) - set(deleted_docs))
if len(final_list) > 0:
if final_list := list(
set([v.name for v in scrap_item_dict.values()]) - set(deleted_docs)
):
frappe.qb.update(table).set(table.produced_qty, case_expr).where(
(table.name.isin(final_list)) & (table.docstatus == 1)
).run()
@@ -847,7 +1041,7 @@ class SubcontractingInwardController:
for item in scrap_items_list
if (item.item_code, item.t_warehouse) not in [(d.item_code, d.warehouse) for d in result]
]:
frappe.new_doc(
doc = frappe.new_doc(
"Subcontracting Inward Order Scrap Item",
parent=scio,
parenttype="Subcontracting Inward Order",
@@ -862,7 +1056,9 @@ class SubcontractingInwardController:
reference_name=frappe.get_value(
"Work Order", self.work_order, "subcontracting_inward_order_item"
),
).insert()
)
doc.insert()
doc.submit()
def cancel_stock_reservation_entries_for_inward(self):
if self.purpose == "Receive from Customer":
@@ -1022,3 +1218,17 @@ class SubcontractingInwardController:
)
update_subcontracting_inward_order_status(self.subcontracting_inward_order)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_fg_reference_names(doctype, txt, searchfield, start, page_len, filters):
return frappe.get_all(
"Subcontracting Inward Order Item",
limit_start=start,
limit_page_length=page_len,
filters={"parent": filters.get("parent"), "item_code": ("like", "%%%s%%" % txt), "docstatus": 1},
fields=["name", "item_code", "delivery_warehouse"],
as_list=True,
order_by="idx",
)