From f7b3253683b0e532236762a8b855fa51ce82feff Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 20 Nov 2025 17:40:28 +0530 Subject: [PATCH 1/2] fix: pick list status doesn't update when DN created from it and PL was created from SO --- erpnext/stock/doctype/pick_list/pick_list.py | 33 ++++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 507534a16ac..b62732d62b9 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -637,10 +637,12 @@ class PickList(TransactionBase): def update_bundle_picked_qty(self): product_bundles = self._get_product_bundles() - product_bundle_qty_map = self._get_product_bundle_qty_map(product_bundles.values()) + product_bundle_qty_map = self._get_product_bundle_qty_map( + next(iter(product_bundles.values())).get("item_code") + ) - for so_row, item_code in product_bundles.items(): - picked_qty = self._compute_picked_qty_for_bundle(so_row, product_bundle_qty_map[item_code]) + for so_row, value in product_bundles.items(): + picked_qty = self._compute_picked_qty_for_bundle(so_row, product_bundle_qty_map[value.item_code]) item_table = "Sales Order Item" already_picked = frappe.db.get_value(item_table, so_row, "picked_qty", for_update=True) frappe.db.set_value( @@ -763,15 +765,23 @@ class PickList(TransactionBase): if not item.product_bundle_item: continue - product_bundles[item.sales_order_item] = frappe.db.get_value( - "Sales Order Item", - item.sales_order_item, - "item_code", + product_bundles[item.sales_order_item] = frappe._dict( + { + "item_code": frappe.db.get_value( + "Sales Order Item", + item.sales_order_item, + "item_code", + ), + "pick_list_item": item.name, + } ) return product_bundles def _get_product_bundle_qty_map(self, bundles: list[str]) -> dict[str, dict[str, float]]: # bundle_item_code: Dict[component, qty] + if isinstance(bundles, str): + bundles = [bundles] + product_bundle_qty_map = {} for bundle_item_code in bundles: bundle = frappe.get_last_doc("Product Bundle", {"new_item_code": bundle_item_code, "disabled": 0}) @@ -1378,17 +1388,20 @@ def add_product_bundles_to_delivery_note( When mapping pick list items, the bundle item itself isn't part of the locations. Dynamically fetch and add parent bundle item into DN.""" product_bundles = pick_list._get_product_bundles() - product_bundle_qty_map = pick_list._get_product_bundle_qty_map(product_bundles.values()) + product_bundle_qty_map = pick_list._get_product_bundle_qty_map( + next(iter(product_bundles.values())).get("item_code") + ) - for so_row, item_code in product_bundles.items(): + for so_row, value in product_bundles.items(): sales_order_item = frappe.get_doc("Sales Order Item", so_row) if sales_order and sales_order_item.parent != sales_order: continue dn_bundle_item = map_child_doc(sales_order_item, delivery_note, item_mapper) dn_bundle_item.qty = pick_list._compute_picked_qty_for_bundle( - so_row, product_bundle_qty_map[item_code] + so_row, product_bundle_qty_map[value.item_code] ) + dn_bundle_item.pick_list_item = value.pick_list_item dn_bundle_item.against_pick_list = pick_list.name update_delivery_note_item(sales_order_item, dn_bundle_item, delivery_note) From d26f8aa62937364917ced7a51dfb7e1bdfd5e20e Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 21 Nov 2025 10:51:19 +0530 Subject: [PATCH 2/2] fix: tests --- erpnext/stock/doctype/pick_list/pick_list.py | 22 +++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index b62732d62b9..cb2e05916d5 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -7,7 +7,7 @@ from itertools import groupby import frappe from frappe import _, bold -from frappe.model.mapper import get_mapped_doc, map_child_doc +from frappe.model.mapper import map_child_doc from frappe.query_builder import Case from frappe.query_builder.custom import GROUP_CONCAT from frappe.query_builder.functions import Coalesce, Locate, Replace, Sum @@ -637,9 +637,7 @@ class PickList(TransactionBase): def update_bundle_picked_qty(self): product_bundles = self._get_product_bundles() - product_bundle_qty_map = self._get_product_bundle_qty_map( - next(iter(product_bundles.values())).get("item_code") - ) + product_bundle_qty_map = self._get_product_bundle_qty_map(product_bundles.values()) for so_row, value in product_bundles.items(): picked_qty = self._compute_picked_qty_for_bundle(so_row, product_bundle_qty_map[value.item_code]) @@ -777,15 +775,11 @@ class PickList(TransactionBase): ) return product_bundles - def _get_product_bundle_qty_map(self, bundles: list[str]) -> dict[str, dict[str, float]]: - # bundle_item_code: Dict[component, qty] - if isinstance(bundles, str): - bundles = [bundles] - + def _get_product_bundle_qty_map(self, bundles) -> dict[str, dict[str, float]]: product_bundle_qty_map = {} - for bundle_item_code in bundles: - bundle = frappe.get_last_doc("Product Bundle", {"new_item_code": bundle_item_code, "disabled": 0}) - product_bundle_qty_map[bundle_item_code] = {item.item_code: item.qty for item in bundle.items} + for data in bundles: + bundle = frappe.get_last_doc("Product Bundle", {"new_item_code": data.item_code, "disabled": 0}) + product_bundle_qty_map[data.item_code] = {item.item_code: item.qty for item in bundle.items} return product_bundle_qty_map def _compute_picked_qty_for_bundle(self, bundle_row, bundle_items) -> int: @@ -1388,9 +1382,7 @@ def add_product_bundles_to_delivery_note( When mapping pick list items, the bundle item itself isn't part of the locations. Dynamically fetch and add parent bundle item into DN.""" product_bundles = pick_list._get_product_bundles() - product_bundle_qty_map = pick_list._get_product_bundle_qty_map( - next(iter(product_bundles.values())).get("item_code") - ) + product_bundle_qty_map = pick_list._get_product_bundle_qty_map(product_bundles.values()) for so_row, value in product_bundles.items(): sales_order_item = frappe.get_doc("Sales Order Item", so_row)