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:
@ -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()
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user