diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index f4822fe583a..fa9e1cb3508 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -1115,6 +1115,7 @@ def get_subitems( item_default.default_warehouse, item.purchase_uom, item_uom.conversion_factor, + bom.item.as_("main_bom_item"), ) .where( (bom.name == bom_no) @@ -1228,6 +1229,7 @@ def get_material_request_items( "sales_order": sales_order, "description": row.get("description"), "uom": row.get("purchase_uom") or row.get("stock_uom"), + "main_bom_item": row.get("main_bom_item"), } diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index f657967c0c5..167d0443df2 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -1322,20 +1322,20 @@ def stop_unstop(work_order, status): @frappe.whitelist() -def query_sales_order(production_item): - out = frappe.db.sql_list( - """ - select distinct so.name from `tabSales Order` so, `tabSales Order Item` so_item - where so_item.parent=so.name and so_item.item_code=%s and so.docstatus=1 - union - select distinct so.name from `tabSales Order` so, `tabPacked Item` pi_item - where pi_item.parent=so.name and pi_item.item_code=%s and so.docstatus=1 - """, - (production_item, production_item), +def query_sales_order(production_item: str) -> list[str]: + return frappe.get_list( + "Sales Order", + filters=[ + ["Sales Order", "docstatus", "=", 1], + ], + or_filters=[ + ["Sales Order Item", "item_code", "=", production_item], + ["Packed Item", "item_code", "=", production_item], + ], + pluck="name", + distinct=True, ) - return out - @frappe.whitelist() def make_job_card(work_order, operations): diff --git a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py index d233643c244..96a6822cd11 100644 --- a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py +++ b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py @@ -79,7 +79,7 @@ def get_bom_stock(filters): BOM_ITEM.stock_qty, BOM_ITEM.stock_uom, BOM_ITEM.stock_qty * qty_to_produce / BOM.quantity, - Sum(BIN.actual_qty).as_("actual_qty"), + BIN.actual_qty.as_("actual_qty"), Sum(Floor(BIN.actual_qty / (BOM_ITEM.stock_qty * qty_to_produce / BOM.quantity))), ) .where((BOM_ITEM.parent == filters.get("bom")) & (BOM_ITEM.parenttype == "BOM")) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 6d135812358..7d06a487f46 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -1266,6 +1266,11 @@ def make_raw_material_request(items, company, sales_order, project=None): items.update({"company": company, "sales_order": sales_order}) + item_wh = {} + for item in items.get("items"): + if item.get("warehouse"): + item_wh[item.get("item_code")] = item.get("warehouse") + raw_materials = get_items_for_material_requests(items) if not raw_materials: frappe.msgprint(_("Material Request not created, as quantity for Raw Materials already available.")) @@ -1290,7 +1295,7 @@ def make_raw_material_request(items, company, sales_order, project=None): "item_code": item.get("item_code"), "qty": item.get("quantity"), "schedule_date": schedule_date, - "warehouse": item.get("warehouse"), + "warehouse": item_wh.get(item.get("main_bom_item")) or item.get("warehouse"), "sales_order": sales_order, "project": project, }, diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index d1b81aa2ebe..79bbf0b502c 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -489,6 +489,10 @@ class StockReconciliation(StockController): self.update_inventory_dimensions(row, data) + if self.docstatus == 1 and has_dimensions and not row.batch_no: + data.qty_after_transaction = data.actual_qty + data.actual_qty = 0.0 + return data def make_sle_on_cancel(self): diff --git a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py index 07119411304..000aca9f43e 100644 --- a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py +++ b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py @@ -159,10 +159,11 @@ def assign_item_groups_to_svd_list(svd_list: SVDList) -> None: def get_item_groups_map(svd_list: SVDList) -> dict[str, str]: item_codes = set(i["item_code"] for i in svd_list) - ig_list = frappe.get_list( - "Item", fields=["item_code", "item_group"], filters=[("item_code", "in", item_codes)] + return frappe._dict( + frappe.get_all( + "Item", fields=["name", "item_group"], filters=[("name", "in", item_codes)], as_list=True + ) ) - return {i["item_code"]: i["item_group"] for i in ig_list} def get_item_groups_dict() -> ItemGroupsDict: diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 1cacb0172c4..cc0a9e0f04e 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -655,8 +655,11 @@ class update_entries_after: if not sle.is_adjustment_entry: sle.stock_value_difference = stock_value_difference elif sle.is_adjustment_entry and not self.args.get("sle_id"): - sle.stock_value_difference = get_stock_value_difference( - sle.item_code, sle.warehouse, sle.posting_date, sle.posting_time, sle.voucher_no + sle.stock_value_difference = ( + get_stock_value_difference( + sle.item_code, sle.warehouse, sle.posting_date, sle.posting_time, sle.voucher_no + ) + * -1 ) sle.doctype = "Stock Ledger Entry" diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index 636d620fad3..0067c321049 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -109,6 +109,8 @@ def get_stock_balance( from erpnext.stock.stock_ledger import get_previous_sle + frappe.has_permission("Item", "read", throw=True) + if posting_date is None: posting_date = nowdate() if posting_time is None: