fix: adjust BOM cost calculation SQL and refactor for consistency

Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
This commit is contained in:
dxc
2026-03-02 11:52:24 +08:00
parent 9cfbdc7d13
commit bcd39729f8
2 changed files with 25 additions and 23 deletions

View File

@ -458,45 +458,47 @@ class SemiInboundService:
@staticmethod
def calculate_bom_cost(bom_no, bom_version):
"""
【防崩修正版】查询物理字段:采购的税前价 / 半成品和成品的 manual_cost(映射后的单件成本)
根据 BOM 编号和版本计算原材料总成本
遍历 BOM 子件,使用原生 SQL 查物理表 bom_table取每个子件在采购、半成品、成品三个表中的最高单价乘以用量后累加
"""
from app.models.bom import bom_table # 假设这可能是 SQLAlchemy 表对象或类
from app.models.inbound.buy import StockBuy
from app.models.inbound.semi import StockSemi
from app.models.inbound.product import StockProduct
from sqlalchemy import func
from sqlalchemy import func, text
try:
# 兼容你的表名
bom_lines = db.session.execute(
text("SELECT child_id, dosage FROM bom_table WHERE bom_no = :bom_no AND version = :version"),
{'bom_no': bom_no, 'version': bom_version}
).fetchall()
# 使用原生 SQL 精准查询 bom_table避免模型映射错误
sql = text("""
SELECT child_id, dosage
FROM bom_table
WHERE bom_no = :bom_no AND version = :version
""")
bom_lines = db.session.execute(sql, {'bom_no': bom_no, 'version': bom_version}).fetchall()
total_cost = 0.0
for line in bom_lines:
component_base_id = line[0]
usage_qty = float(line[1] or 1.0)
# 查采购表最高价
component_base_id = line[0] # child_id
usage_qty = float(line[1] or 1.0) # dosage
# 1. 查采购表最高价 (不含税)
buy_price = db.session.query(func.max(StockBuy.pre_tax_unit_price)).filter(
StockBuy.base_id == component_base_id
).scalar() or 0.0
# 查半成品表最高价 (直接查 manual_cost,因为它存的就是单件成本)
# 2. 查半成品表最高价 (单件成本映射存在 manual_cost 里了)
semi_price = db.session.query(func.max(StockSemi.manual_cost)).filter(
StockSemi.base_id == component_base_id
).scalar() or 0.0
# 查成品表最高价
# 3. 查成品表最高价 (同样存储在 manual_cost 字段里)
product_price = db.session.query(func.max(StockProduct.manual_cost)).filter(
StockProduct.base_id == component_base_id
).scalar() or 0.0
max_price = max(buy_price, semi_price, product_price)
# 4. 取三个表中的最大值,乘以用量 (dosage)
max_price = max(float(buy_price), float(semi_price), float(product_price))
total_cost += max_price * usage_qty
return round(total_cost, 2)
except Exception as e:
traceback.print_exc()
raise e
raise e