This commit is contained in:
dxc
2026-06-25 15:21:43 +08:00
parent 8ba1ff37f0
commit c1092407ad
7 changed files with 128 additions and 43 deletions

View File

@ -388,25 +388,31 @@ class BomService:
# 1. 提取所有子件的 ID 列表
child_ids = [child['child_id'] for child in detail['children']]
# 2. 用一条 IN 语句批量查出所有相关子件的库存和库位
stock_stats = db.session.query(
StockBuy.base_id,
func.coalesce(func.sum(StockBuy.available_quantity), 0).label('total_qty'),
func.string_agg(distinct(StockBuy.warehouse_location), ', ').label('locations')
).filter(
StockBuy.base_id.in_(child_ids),
StockBuy.available_quantity > 0
).group_by(
StockBuy.base_id
).all()
# 2. 分别查三张库存表Python 侧合并聚合(避免 UNION ALL 子查询列名问题)
from collections import defaultdict
stock_agg = defaultdict(lambda: {'qty': 0.0, 'locs': set()})
# 3. 将查询结果转换为字典 (Map),方便后续 O(1) 极速匹配
for model in (StockBuy, StockSemi, StockProduct):
rows = db.session.query(
model.base_id,
model.available_quantity,
model.warehouse_location
).filter(
model.base_id.in_(child_ids),
model.available_quantity > 0
).all()
for base_id, qty, loc in rows:
stock_agg[base_id]['qty'] += float(qty or 0)
if loc:
stock_agg[base_id]['locs'].add(loc)
# 3. 将聚合结果转换为字典 (Map),方便后续 O(1) 极速匹配
stock_map = {
stat.base_id: {
'qty': stat.total_qty,
'loc': stat.locations if stat.locations else ''
base_id: {
'qty': agg['qty'],
'loc': ', '.join(sorted(agg['locs'])) if agg['locs'] else ''
}
for stat in stock_stats
for base_id, agg in stock_agg.items()
}
# 4. 遍历组装数据(纯内存操作,极快)
@ -480,17 +486,23 @@ class BomService:
parent_name = detail.get('parent_name', '')
# 2. 提取所有子件 ID查询采购库存stock_buy
# 2. 提取所有子件 ID分别查三张库存表Python 侧合并聚合
child_ids = [child['child_id'] for child in detail['children']]
buy_stats = db.session.query(
StockBuy.base_id,
func.coalesce(func.sum(StockBuy.available_quantity), 0).label('total_qty')
).filter(
StockBuy.base_id.in_(child_ids)
).group_by(StockBuy.base_id).all()
from collections import defaultdict
stock_agg = defaultdict(float)
buy_map = {stat.base_id: float(stat.total_qty) for stat in buy_stats}
for model in (StockBuy, StockSemi, StockProduct):
rows = db.session.query(
model.base_id,
model.available_quantity
).filter(
model.base_id.in_(child_ids)
).all()
for base_id, qty in rows:
stock_agg[base_id] += float(qty or 0)
stock_map = dict(stock_agg)
# 3. 提取所有子件的基础物料信息(名称/规格/类型)
materials = db.session.query(
@ -511,7 +523,7 @@ class BomService:
dosage = float(child.get('dosage') or 0)
need_qty = dosage * order_qty
available_stock = buy_map.get(child_id, 0)
available_stock = stock_map.get(child_id, 0)
suggested_qty = max(0.0, min(need_qty, available_stock))
gap = available_stock - need_qty