68 lines
2.3 KiB
Python
68 lines
2.3 KiB
Python
from app.extensions import db
|
|
from app.models.bom import BomTable
|
|
from app.models.base import MaterialBase
|
|
from app.models.inbound.buy import StockBuy
|
|
from sqlalchemy import func
|
|
|
|
class BomService:
|
|
@staticmethod
|
|
def create_or_update_bom(parent_id, child_list):
|
|
"""
|
|
保存/更新父件的BOM子件关系
|
|
child_list: [{"child_id": int, "dosage": float, "remark": str}, ...]
|
|
"""
|
|
# 校验父件不能与子件相同
|
|
for item in child_list:
|
|
if item['child_id'] == parent_id:
|
|
raise ValueError('父件与子件不能是同一物料')
|
|
# 删除该父件原有的BOM记录
|
|
BomTable.query.filter_by(parent_id=parent_id).delete()
|
|
# 插入新的
|
|
for item in child_list:
|
|
bom = BomTable(
|
|
parent_id=parent_id,
|
|
child_id=item['child_id'],
|
|
dosage=item.get('dosage', 0),
|
|
remark=item.get('remark', '')
|
|
)
|
|
db.session.add(bom)
|
|
db.session.commit()
|
|
return True
|
|
|
|
@staticmethod
|
|
def get_bom_with_stock(parent_id):
|
|
"""
|
|
查询父件的BOM结构及库存信息
|
|
"""
|
|
bom_items = db.session.query(
|
|
BomTable,
|
|
MaterialBase.name.label('child_name')
|
|
).join(
|
|
MaterialBase, BomTable.child_id == MaterialBase.id
|
|
).filter(
|
|
BomTable.parent_id == parent_id
|
|
).all()
|
|
|
|
result = []
|
|
for bom, child_name in bom_items:
|
|
# 查询该子件在 StockBuy 中的可用库存总量
|
|
stock_qty = db.session.query(
|
|
func.coalesce(func.sum(StockBuy.available_quantity), 0)
|
|
).filter(
|
|
StockBuy.base_id == bom.child_id
|
|
).scalar() or 0
|
|
|
|
# 计算最大可生产数量
|
|
dosage = float(bom.dosage) if bom.dosage else 0
|
|
max_producible = int(stock_qty // dosage) if dosage > 0 else 0
|
|
|
|
result.append({
|
|
'child_id': bom.child_id,
|
|
'child_name': child_name,
|
|
'dosage': dosage,
|
|
'current_stock': float(stock_qty),
|
|
'max_producible': max_producible,
|
|
'remark': bom.remark or ''
|
|
})
|
|
return result
|