fix: correct BOM cost calculation by using raw SQL and manual_cost
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
This commit is contained in:
@ -399,33 +399,45 @@ 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
|
||||
StockBuy.base_id == component_base_id
|
||||
).scalar() or 0.0
|
||||
|
||||
max_price = max(buy_price, semi_price, product_price)
|
||||
# 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()
|
||||
|
||||
Reference in New Issue
Block a user