TransService.get_records: 追加 material_name 字段 + SKU 兜底查询解决数据孤岛问题

This commit is contained in:
DXC
2026-06-12 11:06:34 +08:00
parent 67bc5b6c5d
commit 9a5e3ee6b0

View File

@ -7,6 +7,7 @@ from app.models.inbound.semi import StockSemi
from app.models.inbound.product import StockProduct from app.models.inbound.product import StockProduct
from app.models.base import MaterialBase from app.models.base import MaterialBase
from sqlalchemy import desc, func, nullslast, asc, or_, and_ from sqlalchemy import desc, func, nullslast, asc, or_, and_
from sqlalchemy.orm import joinedload
class TransService: class TransService:
@ -396,8 +397,75 @@ class TransService:
q = q.order_by(nullslast(asc(TransBorrow.expected_return_time))) q = q.order_by(nullslast(asc(TransBorrow.expected_return_time)))
pagination = q.paginate(page=page, per_page=limit, error_out=False) 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 { return {
'items': [r.to_dict() for r in pagination.items], 'items': items_data,
'total': pagination.total, 'total': pagination.total,
'page': page, 'page': page,
'limit': limit 'limit': limit