From 9a5e3ee6b06156b9a07cef9982a3f9af22da7187 Mon Sep 17 00:00:00 2001 From: DXC Date: Fri, 12 Jun 2026 11:06:34 +0800 Subject: [PATCH] =?UTF-8?q?TransService.get=5Frecords:=20=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=20material=5Fname=20=E5=AD=97=E6=AE=B5=20+=20SKU=20?= =?UTF-8?q?=E5=85=9C=E5=BA=95=E6=9F=A5=E8=AF=A2=E8=A7=A3=E5=86=B3=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=AD=A4=E5=B2=9B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/services/trans_service.py | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/inventory-backend/app/services/trans_service.py b/inventory-backend/app/services/trans_service.py index 5edfc3a..3e91f42 100644 --- a/inventory-backend/app/services/trans_service.py +++ b/inventory-backend/app/services/trans_service.py @@ -7,6 +7,7 @@ from app.models.inbound.semi import StockSemi from app.models.inbound.product import StockProduct from app.models.base import MaterialBase from sqlalchemy import desc, func, nullslast, asc, or_, and_ +from sqlalchemy.orm import joinedload class TransService: @@ -396,8 +397,75 @@ class TransService: q = q.order_by(nullslast(asc(TransBorrow.expected_return_time))) pagination = q.paginate(page=page, per_page=limit, error_out=False) + # ============================================================ + # ★ 批量预加载物料名称(两步:收集ID → 批量 JOIN → 内存拼装) + # ============================================================ + items_with_names = [] + items = pagination.items + if items: + # 步骤 1:收集所有 (source_table, stock_id) 对 + stock_ids_by_table = {'stock_buy': set(), 'stock_semi': set(), 'stock_product': set()} + for item in items: + if item.source_table in stock_ids_by_table and item.stock_id: + stock_ids_by_table[item.source_table].add(item.stock_id) + + # 步骤 2:批量查询库存表并 JOIN MaterialBase + stock_map = {} # { ('stock_buy', 101): '物料名称', ... } + model_map = { + 'stock_buy': StockBuy, + 'stock_semi': StockSemi, + 'stock_product': StockProduct + } + for table_name, ids in stock_ids_by_table.items(): + if not ids: + continue + ModelClass = model_map.get(table_name) + if not ModelClass: + continue + stocks = ModelClass.query.options( + joinedload(ModelClass.base) + ).filter(ModelClass.id.in_(ids)).all() + for stock in stocks: + name = stock.base.name if stock.base else '' + stock_map[(table_name, stock.id)] = name + + # 步骤 3(前置):收集 SKU 兜底候选集 + empty_sku_set = set() + for item in items: + name = stock_map.get((item.source_table, item.stock_id), '') + if not name and item.sku: + empty_sku_set.add(item.sku) + + # 步骤 3(前置):SKU 兜底批量查询 + # 场景:库存记录被跨表转移(删旧建新)时,trans_borrow.stock_id 指向孤立记录 + # 通过 sku 在三张库存表中查找任意匹配,再通过 base_id 获取 MaterialBase.name + sku_name_map = {} + if empty_sku_set: + for ModelClass in [StockProduct, StockSemi, StockBuy]: + stocks = ModelClass.query.options( + joinedload(ModelClass.base) + ).filter( + ModelClass.sku.in_(empty_sku_set) + ).all() + for stock in stocks: + if stock.sku not in sku_name_map and stock.base: + sku_name_map[stock.sku] = stock.base.name + + # 步骤 3:为每条记录注入 material_name(含 SKU 兜底) + for item in items: + item_dict = item.to_dict() + material_name = stock_map.get((item.source_table, item.stock_id), '') + if not material_name and item.sku: + material_name = sku_name_map.get(item.sku, '') + item_dict['material_name'] = material_name + items_with_names.append(item_dict) + + items_data = items_with_names + else: + items_data = [] + return { - 'items': [r.to_dict() for r in pagination.items], + 'items': items_data, 'total': pagination.total, 'page': page, 'limit': limit