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

@ -410,7 +410,7 @@ class ProductInboundService:
sql = text(""" sql = text("""
SELECT child_id, dosage SELECT child_id, dosage
FROM bom_table FROM bom_table
WHERE bom_no = :bom_no AND version = :version AND is_enabled = true WHERE bom_no = :bom_no AND version = :version
""") """)
bom_lines = db.session.execute(sql, {'bom_no': bom_no, 'version': bom_version}).fetchall() bom_lines = db.session.execute(sql, {'bom_no': bom_no, 'version': bom_version}).fetchall()

View File

@ -458,42 +458,44 @@ class SemiInboundService:
@staticmethod @staticmethod
def calculate_bom_cost(bom_no, bom_version): 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.buy import StockBuy
from app.models.inbound.semi import StockSemi from app.models.inbound.semi import StockSemi
from app.models.inbound.product import StockProduct from app.models.inbound.product import StockProduct
from sqlalchemy import func from sqlalchemy import func, text
try: try:
# 兼容你的表名 # 使用原生 SQL 精准查询 bom_table避免模型映射错误
bom_lines = db.session.execute( sql = text("""
text("SELECT child_id, dosage FROM bom_table WHERE bom_no = :bom_no AND version = :version"), SELECT child_id, dosage
{'bom_no': bom_no, 'version': bom_version} FROM bom_table
).fetchall() 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 total_cost = 0.0
for line in bom_lines: for line in bom_lines:
component_base_id = line[0] component_base_id = line[0] # child_id
usage_qty = float(line[1] or 1.0) usage_qty = float(line[1] or 1.0) # dosage
# 查采购表最高价 # 1. 查采购表最高价 (不含税)
buy_price = db.session.query(func.max(StockBuy.pre_tax_unit_price)).filter( buy_price = db.session.query(func.max(StockBuy.pre_tax_unit_price)).filter(
StockBuy.base_id == component_base_id StockBuy.base_id == component_base_id
).scalar() or 0.0 ).scalar() or 0.0
# 查半成品表最高价 (直接查 manual_cost,因为它存的就是单件成本) # 2. 查半成品表最高价 (单件成本映射存在 manual_cost 里了)
semi_price = db.session.query(func.max(StockSemi.manual_cost)).filter( semi_price = db.session.query(func.max(StockSemi.manual_cost)).filter(
StockSemi.base_id == component_base_id StockSemi.base_id == component_base_id
).scalar() or 0.0 ).scalar() or 0.0
# 查成品表最高价 # 3. 查成品表最高价 (同样存储在 manual_cost 字段里)
product_price = db.session.query(func.max(StockProduct.manual_cost)).filter( product_price = db.session.query(func.max(StockProduct.manual_cost)).filter(
StockProduct.base_id == component_base_id StockProduct.base_id == component_base_id
).scalar() or 0.0 ).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 total_cost += max_price * usage_qty
return round(total_cost, 2) return round(total_cost, 2)