diff --git a/inventory-backend/app/services/inbound/product_service.py b/inventory-backend/app/services/inbound/product_service.py index 8ebcbb0..0d73767 100644 --- a/inventory-backend/app/services/inbound/product_service.py +++ b/inventory-backend/app/services/inbound/product_service.py @@ -399,34 +399,46 @@ class ProductInboundService: def calculate_bom_cost(bom_no, bom_version): """ 根据 BOM 编号和版本计算原材料总成本 - 遍历 BOM 子件,取每个子件在采购、半成品、成品三个表中的最高单价,乘以用量后累加 + 遍历 BOM 子件,使用原生 SQL 查物理表 bom_table,取每个子件在采购、半成品、成品三个表中的最高单价,乘以用量后累加 """ - from app.models.bom import BomLine 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 = BomLine.query.filter( - BomLine.bom_no == bom_no, - BomLine.bom_version == bom_version - ).all() + # 使用原生 SQL 精准查询 bom_table,避免模型映射错误 + sql = text(""" + SELECT child_id, dosage + FROM bom_table + WHERE bom_no = :bom_no AND version = :version AND is_enabled = true + """) + 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.component_id - usage_qty = float(line.usage_quantity 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 - semi_price = db.session.query(func.max(StockSemi.unit_total_cost)).filter( - StockSemi.base_id == component_base_id).scalar() or 0.0 - product_price = db.session.query(func.max(StockProduct.unit_total_cost)).filter( - StockProduct.base_id == component_base_id).scalar() or 0.0 - - max_price = max(buy_price, semi_price, product_price) + StockBuy.base_id == component_base_id + ).scalar() or 0.0 + + # 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 + + # 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 \ No newline at end of file + raise e