diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py
index 6e7254a9dc0..0ab520d8548 100644
--- a/erpnext/controllers/subcontracting_controller.py
+++ b/erpnext/controllers/subcontracting_controller.py
@@ -1403,16 +1403,18 @@ def make_rm_stock_entry(
items_dict = {
rm_item_code: {
rm_detail_field: rm_item.get("name"),
+ "item_code": rm_item_code,
"item_name": rm_item.get("item_name")
or item_wh.get(rm_item_code, {}).get("item_name", ""),
"description": item_wh.get(rm_item_code, {}).get("description", ""),
"qty": qty,
- "from_warehouse": rm_item.get("warehouse")
+ "s_warehouse": rm_item.get("warehouse")
or rm_item.get("reserve_warehouse"),
- "to_warehouse": source_doc.supplier_warehouse,
+ "t_warehouse": source_doc.supplier_warehouse,
"stock_uom": rm_item.get("stock_uom"),
"serial_and_batch_bundle": rm_item.get("serial_and_batch_bundle"),
"main_item_code": fg_item_code,
+ "subcontracted_item": fg_item_code,
"allow_alternative_item": item_wh.get(rm_item_code, {}).get(
"allow_alternative_item"
),
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index ce59cdf4d97..87ccc105dab 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -2005,7 +2005,7 @@ def get_secondary_items_from_sub_assemblies(bom_no, company, qty, secondary_item
def get_backflush_based_on(bom_no=None):
backflush_based_on = None
if bom_no:
- backflush_based_on = frappe.get_cached_value("BOM", bom_no, "backflush_based_on")
+ backflush_based_on = frappe.db.get_value("BOM", bom_no, "backflush_based_on")
if not backflush_based_on:
backflush_based_on = frappe.db.get_single_value(
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 8a3dd1a46e3..4ae120ece7f 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -684,7 +684,10 @@ class TestWorkOrder(ERPNextTestSuite):
def test_cost_center_for_manufacture(self):
wo_order = make_wo_order_test_record()
- ste = make_stock_entry(wo_order.name, "Material Transfer for Manufacture", wo_order.qty)
+ ste = frappe.get_doc(
+ make_stock_entry(wo_order.name, "Material Transfer for Manufacture", wo_order.qty)
+ )
+ ste.save()
self.assertEqual(ste.get("items")[0].get("cost_center"), "_Test Cost Center - _TC")
def test_operation_time_with_batch_size(self):
@@ -1320,7 +1323,6 @@ class TestWorkOrder(ERPNextTestSuite):
stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10))
stock_entry.set_work_order_details()
- ManufactureStockEntry(stock_entry).set_serial_nos_for_finished_good()
for row in stock_entry.items:
if row.item_code == fg_item:
self.assertTrue(row.serial_and_batch_bundle)
@@ -1361,7 +1363,6 @@ class TestWorkOrder(ERPNextTestSuite):
stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10))
stock_entry.set_work_order_details()
- ManufactureStockEntry(stock_entry).set_serial_nos_for_finished_good()
for row in stock_entry.items:
if row.item_code == fg_item:
self.assertTrue(row.serial_and_batch_bundle)
@@ -4292,7 +4293,6 @@ class TestWorkOrder(ERPNextTestSuite):
)
material_transfer_entry.submit()
-
manufacture_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 1))
manufacture_entry.save()
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 785bdc36e64..4f99539a7da 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -2087,8 +2087,9 @@ class WorkOrder(Document):
additional_items = frappe._dict()
for row in stock_entry.items:
- if row.item_code not in required_items:
- additional_items.setdefault(row.item_code, []).append(row)
+ item_code = row.original_item if row.original_item else row.item_code
+ if item_code not in required_items:
+ additional_items.setdefault(item_code, []).append(row)
self.flags.ignore_validate_update_after_submit = True
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index e6afc5798d1..7ec1eede5c2 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -255,6 +255,8 @@ class StockEntry(StockController, SubcontractingInwardController):
if self.se_handler_class and hasattr(self.se_handler_class, "before_validate"):
self.se_handler_class(self).before_validate()
+ self.set_default_cost_center()
+
apply_rule = self.apply_putaway_rule and (self.purpose in ["Material Transfer", "Material Receipt"])
if self.get("items") and apply_rule:
@@ -268,6 +270,17 @@ class StockEntry(StockController, SubcontractingInwardController):
if not item.project:
item.project = self.project
+ def set_default_cost_center(self):
+ for row in self.items:
+ if not row.cost_center:
+ row.cost_center = get_default_cost_center(
+ row,
+ row,
+ get_item_group_defaults(row.item_code, self.company),
+ get_brand_defaults(row.item_code, self.company),
+ self.company,
+ )
+
def validate(self):
if self.se_handler_class:
self.se_handler_class(self).validate()
@@ -318,7 +331,6 @@ class StockEntry(StockController, SubcontractingInwardController):
self.se_handler_class(self).on_submit()
self.make_bundle_using_old_serial_batch_fields()
- self.update_disassembled_order()
self.adjust_stock_reservation_entries_for_return()
self.update_stock_reservation_entries()
self.update_stock_ledger()
@@ -346,7 +358,6 @@ class StockEntry(StockController, SubcontractingInwardController):
if self.work_order and self.purpose == "Material Consumption for Manufacture":
self.validate_work_order_status()
- self.update_disassembled_order()
self.cancel_stock_reservation_entries_for_inward()
self.update_stock_ledger()
@@ -1167,13 +1178,6 @@ class StockEntry(StockController, SubcontractingInwardController):
self._wo_doc = frappe.get_doc("Work Order", self.work_order)
return getattr(self, "_wo_doc", None)
- def update_disassembled_order(self):
- if not self.work_order:
- return
- if self.purpose == "Disassemble" and self.fg_completed_qty:
- pro_doc = frappe.get_doc("Work Order", self.work_order)
- pro_doc.run_method("update_disassembled_qty", self.fg_completed_qty, self._action == "cancel")
-
def make_stock_reserve_for_wip_and_fg(self):
if self.is_stock_reserve_for_work_order():
pro_doc = frappe.get_doc("Work Order", self.work_order)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_handler/disassemble.py b/erpnext/stock/doctype/stock_entry/stock_entry_handler/disassemble.py
index 699e66ec368..ff9834917b7 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry_handler/disassemble.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry_handler/disassemble.py
@@ -62,7 +62,6 @@ class DisassembleStockEntry:
"docstatus": 1,
},
pluck="name",
- limit_page_length=2,
)
if len(manufacture_entries) == 1:
self.doc.source_stock_entry = manufacture_entries[0]
@@ -200,6 +199,8 @@ class DisassembleStockEntry:
item_args["bom_secondary_item"] = row.get("name")
row.qty = row.qty * self.doc.fg_completed_qty
+ if row.get("process_loss_per"):
+ row.qty -= flt(row.qty * row.get("process_loss_per") / 100)
item_args["qty"] = ceil_qty_if_uom_has_whole_number(row.qty, item_args["uom"])
self.doc.append("items", item_args)
@@ -284,6 +285,10 @@ class DisassembleStockEntry:
def on_submit(self):
self.set_serial_batch_for_disassembly()
+ self.update_disassembled_order()
+
+ def on_cancel(self):
+ self.update_disassembled_order()
def set_serial_batch_for_disassembly(self):
if self.doc.get("source_stock_entry"):
@@ -388,6 +393,16 @@ class DisassembleStockEntry:
row.serial_and_batch_bundle = bundle_doc.name
row.use_serial_batch_fields = 0
+ def update_disassembled_order(self):
+ if not self.doc.work_order:
+ return
+
+ if self.doc.fg_completed_qty:
+ pro_doc = frappe.get_doc("Work Order", self.doc.work_order)
+ pro_doc.run_method(
+ "update_disassembled_qty", self.doc.fg_completed_qty, self.doc._action == "cancel"
+ )
+
def get_available_materials(work_order, stock_entry_doc=None) -> dict:
data = get_stock_entry_data(work_order, stock_entry_doc=stock_entry_doc)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_handler/manufacturing.py b/erpnext/stock/doctype/stock_entry/stock_entry_handler/manufacturing.py
index 95d12a883ad..72011725d6f 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry_handler/manufacturing.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry_handler/manufacturing.py
@@ -97,10 +97,14 @@ class BaseManufactureStockEntry:
secondary_items = get_secondary_items(self.doc.bom_no, self.doc.work_order)
for row in secondary_items:
item_args = self.get_item_dict(row)
- item_args["is_legacy_scrap_item"] = row.get("is_legacy") and row.type == "Scrap"
+ item_args["is_legacy_scrap_item"] = bool(row.get("is_legacy"))
item_args["type"] = row.type
item_args["bom_secondary_item"] = row.name
- item_args["t_warehouse"] = self.doc.to_warehouse
+
+ if row.type == "Scrap" and self.wo_doc and self.wo_doc.get("scrap_warehouse"):
+ item_args["t_warehouse"] = self.wo_doc.scrap_warehouse
+ else:
+ item_args["t_warehouse"] = self.doc.to_warehouse
row.qty = row.qty * self.doc.fg_completed_qty
if row.get("process_loss_per"):
@@ -197,7 +201,7 @@ class BaseManufactureStockEntry:
row = frappe._dict({"serial_nos": serial_nos[0 : cint(item_details.qty)]})
_id = create_serial_and_batch_bundle(
- self.se_doc,
+ self.doc,
row,
frappe._dict(
{
@@ -485,11 +489,13 @@ class ManufactureStockEntry(BaseManufactureStockEntry):
return alternative_items
def set_alternative_item_details(self, row, alternative_item_details):
- if self.doc.work_order:
- row.allow_alternative_item = self.wo_doc.allow_alternative_item
+ if self.doc.work_order and row.get("allow_alternative_item") is None:
+ row["allow_alternative_item"] = self.wo_doc.allow_alternative_item
- if row.allow_alternative_item:
+ if row["allow_alternative_item"]:
+ original_item = row["item_code"]
row.update(alternative_item_details)
+ row["original_item"] = original_item
def add_raw_materials_based_on_transfer(self):
self.prepare_available_materials_based_on_transfer()
@@ -504,18 +510,46 @@ class ManufactureStockEntry(BaseManufactureStockEntry):
for row in self.available_materials:
row = self.available_materials[row]
item_args = self.get_item_dict(row)
- qty = (flt(row.qty) * flt(self.doc.fg_completed_qty)) / pending_qty_to_mfg
+ if not self.doc.get("is_return"):
+ qty = (flt(row.qty) * flt(self.doc.fg_completed_qty)) / pending_qty_to_mfg
+ else:
+ qty = row.qty
+
item_args["qty"] = ceil_qty_if_uom_has_whole_number(qty, row.uom)
item_args["transfer_qty"] = item_args["qty"]
- if row.serial_nos or (row.batches and len(row.batches) == 1):
- item_args["serial_no"] = row.serial_nos[0 : cint(qty)]
- item_args["batch_no"] = next(iter(row.batches.values()))
- if not item_args["uom"]:
- item_args["uom"] = row.stock_uom
+ if not self.doc.get("is_return"):
+ item_args["t_warehouse"] = None
+ item_args["s_warehouse"] = row.warehouse
+ else:
+ # In case of return, source and target warehouse will be swapped
+ item_args["s_warehouse"] = row.s_warehouse
+ item_args["t_warehouse"] = row.t_warehouse
+
+ if row.serial_nos or row.batches:
+ self.assign_serial_batches_to_materials(item_args, row, qty)
+ else:
self.doc.append("items", item_args)
- elif row.batches:
- self.split_items_based_on_batches(qty, item_args, row)
+
+ def assign_serial_batches_to_materials(self, item_args, row, qty):
+ if row.serial_nos:
+ if serial_nos := row.serial_nos[0 : cint(qty)]:
+ item_args["serial_no"] = "\n".join(serial_nos)
+
+ if not item_args["uom"]:
+ item_args["uom"] = row.stock_uom
+
+ item_args["use_serial_batch_fields"] = 1
+ self.doc.append("items", item_args)
+ elif row.batches and len(row.batches) == 1:
+ item_args["batch_no"] = next(iter(row.batches.keys()))
+ if not item_args["uom"]:
+ item_args["uom"] = row.stock_uom
+
+ item_args["use_serial_batch_fields"] = 1
+ self.doc.append("items", item_args)
+ elif row.batches:
+ self.split_items_based_on_batches(qty, item_args, row)
def split_items_based_on_batches(self, qty, item_args, row):
for batch_no, batch_qty in row.batches.items():
@@ -533,7 +567,9 @@ class ManufactureStockEntry(BaseManufactureStockEntry):
if not item_args["uom"]:
item_args["uom"] = row.stock_uom
+ item_args["batch_no"] = batch_no
item_args["transfer_qty"] = item_args["qty"]
+ item_args["use_serial_batch_fields"] = 1
self.doc.append("items", item_args)
@@ -577,8 +613,8 @@ class ManufactureStockEntry(BaseManufactureStockEntry):
key = (row.item_code, row.warehouse)
if key not in self.available_materials:
self.available_materials[key] = frappe._dict(row)
-
- self.available_materials[key].qty += row.qty
+ else:
+ self.available_materials[key].qty += row.qty
if row.serial_and_batch_bundle:
self.available_materials[key].update(self.get_sabb_details(row.serial_and_batch_bundle))
@@ -835,9 +871,19 @@ def get_bom_items(bom_no, use_multi_level_bom=None, qty=None, fetch_secondary_it
doctype.conversion_factor,
)
elif table_name == "BOM Item":
- query = query.select(doctype.allow_alternative_item, doctype.uom, doctype.conversion_factor)
+ query = query.select(
+ doctype.allow_alternative_item, doctype.uom, doctype.conversion_factor, doctype.bom_no
+ )
- return query.run(as_dict=1)
+ items = query.run(as_dict=1)
+ item_dict = {}
+ for item in items:
+ if item.item_code in item_dict:
+ item_dict[item.item_code].qty += item.qty
+ else:
+ item_dict[item.item_code] = item
+
+ return list(item_dict.values())
def get_secondary_items(bom_no, work_order=None):
@@ -856,13 +902,12 @@ def get_secondary_items(bom_no, work_order=None):
def get_secondary_items_from_sub_assemblies(bom_no):
items = []
bom_items = get_bom_items(bom_no)
- items.extend(bom_items)
for row in bom_items:
if not row.bom_no:
continue
items.extend(get_bom_items(row.bom_no, qty=row.qty, fetch_secondary_items=True))
- get_secondary_items_from_sub_assemblies(row.bom_no)
+ items.extend(get_secondary_items_from_sub_assemblies(row.bom_no))
return items
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_handler/material_receipt_issue.py b/erpnext/stock/doctype/stock_entry/stock_entry_handler/material_receipt_issue.py
index 3d5fa95c730..8908c0f9730 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry_handler/material_receipt_issue.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry_handler/material_receipt_issue.py
@@ -17,9 +17,9 @@ class MaterialReceiptStockEntry:
def set_default_warehouse(self):
for row in self.doc.items:
+ row.s_warehouse = None
if not row.t_warehouse and self.doc.to_warehouse:
row.t_warehouse = self.doc.to_warehouse
- row.s_warehouse = None
def validate_warehouse(self):
for row in self.doc.items:
@@ -33,9 +33,9 @@ class BaseMaterialIssueStockEntry:
def set_default_warehouse(self):
for row in self.doc.items:
+ row.t_warehouse = None
if not row.s_warehouse and self.doc.from_warehouse:
row.s_warehouse = self.doc.from_warehouse
- row.t_warehouse = None
def validate_warehouse(self):
for row in self.doc.items:
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_handler/material_transfer.py b/erpnext/stock/doctype/stock_entry/stock_entry_handler/material_transfer.py
index 1b775eb75d0..cb658f7a121 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry_handler/material_transfer.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry_handler/material_transfer.py
@@ -131,6 +131,14 @@ class MaterialTransferForManufactureStockEntry(BaseMaterialTransferStockEntry):
title=_("Missing Item"),
)
+ def get_matched_items(self, item_code):
+ items = [item for item in self.doc.items if item.s_warehouse]
+ for row in items:
+ if row.item_code == item_code or row.original_item == item_code:
+ return row
+
+ return {}
+
def add_items(self):
item_dict = self.get_pending_raw_materials()
if self.doc.to_warehouse and self.wo_doc:
@@ -189,6 +197,10 @@ class MaterialTransferForManufactureStockEntry(BaseMaterialTransferStockEntry):
else:
item_dict[item]["qty"] = 0
+ item_dict[item]["transfer_qty"] = flt(item_dict[item]["qty"]) * flt(
+ item_dict[item].get("conversion_factor") or 1
+ )
+
# delete items with 0 qty
list_of_items = list(item_dict.keys())
for item in list_of_items:
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_handler/subcontracting.py b/erpnext/stock/doctype/stock_entry/stock_entry_handler/subcontracting.py
index 9dac0f1dd40..9c3546d34d7 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry_handler/subcontracting.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry_handler/subcontracting.py
@@ -91,7 +91,7 @@ class SendToSubcontractorStockEntry:
)
def validate_subcontracting_order_for_transfer(self, child_row):
- if not self.doc.subcontracted_item:
+ if not child_row.subcontracted_item:
frappe.throw(
_("Row {0}: Subcontracted Item is mandatory for the raw material {1}").format(
child_row.idx, bold(child_row.item_code)
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py
index 6d9e40052b1..5b933427ee4 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.py
@@ -196,7 +196,6 @@ class StockEntryDetail(Document):
)
def set_actual_qty(self, posting_date, posting_time):
- allow_negative_stock = is_negative_stock_allowed(item_code=self.item_code)
previous_sle = get_previous_sle(
{
"item_code": self.item_code,
@@ -209,33 +208,6 @@ class StockEntryDetail(Document):
# get actual stock at source warehouse
self.actual_qty = previous_sle.get("qty_after_transaction") or 0
- # validate qty during submit
- if (
- self.docstatus == 1
- and self.s_warehouse
- and not allow_negative_stock
- and flt(self.actual_qty, self.precision("actual_qty"))
- < flt(self.transfer_qty, self.precision("actual_qty"))
- ):
- frappe.throw(
- _(
- "Row {0}: Quantity not available for {4} in warehouse {1} at posting time of the entry ({2} {3})"
- ).format(
- self.idx,
- bold(self.s_warehouse),
- formatdate(posting_date),
- format_time(posting_time),
- bold(self.item_code),
- )
- + "
"
- + _("Available quantity is {0}, you need {1}").format(
- bold(flt(self.actual_qty, self.precision("actual_qty"))),
- bold(self.transfer_qty),
- ),
- NegativeStockError,
- title=_("Insufficient Stock"),
- )
-
def delink_asset_repair_sabb(self, asset_repair):
if not self.serial_and_batch_bundle:
return
diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py
index 9a3f5d39055..4e4acd38da7 100644
--- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py
+++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.py
@@ -122,10 +122,10 @@ class ManufactureEntry:
if backflush_based_on != "BOM":
available_serial_batches = self.get_transferred_serial_batches()
- items_list = []
for item_code, _dict in item_dict.items():
_dict.from_warehouse = self.source_wh.get(item_code) or self.wip_warehouse
_dict.to_warehouse = ""
+ _dict.item_code = item_code
if backflush_based_on != "BOM" and not frappe.db.get_value(
"Job Card", self.job_card, "skip_material_transfer"
@@ -139,9 +139,7 @@ class ManufactureEntry:
_dict.qty = calculated_qty
self.update_available_serial_batches(_dict, available_serial_batches)
- items_list.append(_dict)
-
- self.stock_entry.append("items", items_list)
+ self.stock_entry.append("items", _dict)
def parse_available_serial_batches(self, item_dict, available_serial_batches):
key = (item_dict.item_code, item_dict.from_warehouse)
diff --git a/erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.py b/erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.py
index c3b5358e9d5..db44245e2ce 100644
--- a/erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.py
+++ b/erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.py
@@ -372,8 +372,9 @@ class SubcontractingInwardOrder(SubcontractingController):
items_dict = {
rm_item.get("rm_item_code"): {
"scio_detail": rm_item.get("name"),
+ "item_code": rm_item.get("rm_item_code"),
"qty": calculate_qty_as_per_bom(rm_item),
- "to_warehouse": rm_item.get("warehouse"),
+ "t_warehouse": rm_item.get("warehouse"),
"stock_uom": rm_item.get("stock_uom"),
}
}
@@ -413,8 +414,9 @@ class SubcontractingInwardOrder(SubcontractingController):
items_dict = {
rm_item.get("rm_item_code"): {
"scio_detail": rm_item.get("name"),
+ "item_code": rm_item.get("rm_item_code"),
"qty": rm_item.received_qty - rm_item.work_order_qty - rm_item.returned_qty,
- "from_warehouse": rm_item.get("warehouse"),
+ "s_warehouse": rm_item.get("warehouse"),
"stock_uom": rm_item.get("stock_uom"),
}
}
@@ -465,7 +467,8 @@ class SubcontractingInwardOrder(SubcontractingController):
items_dict = {
fg_item.item_code: {
"qty": qty,
- "from_warehouse": fg_item.delivery_warehouse,
+ "item_code": fg_item.item_code,
+ "s_warehouse": fg_item.delivery_warehouse,
"stock_uom": fg_item.stock_uom,
"scio_detail": fg_item.name,
"is_finished_item": 1,
@@ -490,7 +493,8 @@ class SubcontractingInwardOrder(SubcontractingController):
items_dict = {
secondary_item.item_code: {
"qty": secondary_item.produced_qty - secondary_item.delivered_qty,
- "from_warehouse": secondary_item.warehouse,
+ "item_code": secondary_item.item_code,
+ "s_warehouse": secondary_item.warehouse,
"stock_uom": secondary_item.stock_uom,
"scio_detail": secondary_item.name,
"type": secondary_item.type,
@@ -536,6 +540,7 @@ class SubcontractingInwardOrder(SubcontractingController):
items_dict = {
fg_item.item_code: {
"qty": qty,
+ "item_code": fg_item.item_code,
"stock_uom": fg_item.stock_uom,
"scio_detail": fg_item.name,
"is_finished_item": 1,