TransService.get_records: 追加 material_name 字段 + SKU 兜底查询解决数据孤岛问题
This commit is contained in:
@ -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
|
||||
|
||||
Reference in New Issue
Block a user