88import frappe
99from frappe import _
1010from frappe .query_builder import Order
11- from frappe .query_builder .functions import Coalesce
11+ from frappe .query_builder .functions import Coalesce , Count
1212from frappe .utils import add_days , cint , date_diff , flt , getdate
1313from frappe .utils .nestedset import get_descendants_of
1414
@@ -155,6 +155,8 @@ def get_item_warehouse_map(self):
155155 if self .filters .get ("show_stock_ageing_data" ):
156156 self .sle_entries = self .sle_query .run (as_dict = True )
157157
158+ self .prepare_stock_reco_voucher_wise_count ()
159+
158160 # HACK: This is required to avoid causing db query in flt
159161 _system_settings = frappe .get_cached_doc ("System Settings" )
160162 with frappe .db .unbuffered_cursor ():
@@ -181,6 +183,30 @@ def get_item_warehouse_map(self):
181183
182184 return item_warehouse_map
183185
186+ def prepare_stock_reco_voucher_wise_count (self ):
187+ self .stock_reco_voucher_wise_count = frappe ._dict ()
188+
189+ doctype = frappe .qb .DocType ("Stock Ledger Entry" )
190+ item = frappe .qb .DocType ("Item" )
191+
192+ query = (
193+ frappe .qb .from_ (doctype )
194+ .inner_join (item )
195+ .on (doctype .item_code == item .name )
196+ .select (doctype .voucher_detail_no , Count (doctype .name ).as_ ("count" ))
197+ .where (
198+ (doctype .voucher_type == "Stock Reconciliation" )
199+ & (doctype .docstatus < 2 )
200+ & (doctype .is_cancelled == 0 )
201+ & (item .has_serial_no == 1 )
202+ )
203+ .groupby (doctype .voucher_detail_no )
204+ )
205+
206+ data = query .run (as_list = True )
207+ if data :
208+ self .stock_reco_voucher_wise_count = frappe ._dict (data )
209+
184210 def get_sre_reserved_qty_details (self ) -> dict :
185211 from erpnext .stock .doctype .stock_reservation_entry .stock_reservation_entry import (
186212 get_sre_reserved_qty_for_items_and_warehouses as get_reserved_qty_details ,
@@ -199,9 +225,13 @@ def prepare_item_warehouse_map(self, item_warehouse_map, entry, group_by_key):
199225 qty_dict [field ] = entry .get (field )
200226
201227 if entry .voucher_type == "Stock Reconciliation" and (
202- not entry .batch_no and not entry .serial_no and not entry .serial_and_batch_bundle
228+ not entry .batch_no or entry .serial_no or entry .serial_and_batch_bundle
203229 ):
204- qty_diff = flt (entry .qty_after_transaction ) - flt (qty_dict .bal_qty )
230+ if entry .serial_no and self .stock_reco_voucher_wise_count .get (entry .voucher_detail_no , 0 ) == 1 :
231+ qty_dict .bal_qty = 0.0
232+ qty_diff = flt (entry .actual_qty )
233+ else :
234+ qty_diff = flt (entry .qty_after_transaction ) - flt (qty_dict .bal_qty )
205235 else :
206236 qty_diff = flt (entry .actual_qty )
207237
@@ -318,6 +348,7 @@ def prepare_stock_ledger_entries(self):
318348 sle .serial_no ,
319349 sle .serial_and_batch_bundle ,
320350 sle .has_serial_no ,
351+ sle .voucher_detail_no ,
321352 item_table .item_group ,
322353 item_table .stock_uom ,
323354 item_table .item_name ,
0 commit comments