refactor: use highest unit price per material base in export

Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
This commit is contained in:
dxc
2026-03-02 09:55:49 +08:00
parent 646804bb98
commit b688480892

View File

@ -14,6 +14,7 @@ import datetime
# 需要 pip install openpyxl
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
from collections import defaultdict
class MaterialBaseService:
@ -411,15 +412,59 @@ class MaterialBaseService:
query_product = query_product.filter(cond)
list_product = query_product.all()
# 2.4 计算每个物料基础的最高单价/成本
buy_max = defaultdict(float)
for stock, base in list_buy:
p = float(stock.pre_tax_unit_price or 0)
if p > buy_max[base.id]:
buy_max[base.id] = p
semi_max = defaultdict(float)
for stock, base in list_semi:
p = float(stock.raw_material_cost or 0) + float(stock.manual_cost or 0)
if p > semi_max[base.id]:
semi_max[base.id] = p
product_max = defaultdict(float)
for stock, base in list_product:
p = float(stock.raw_material_cost or 0) + float(stock.manual_cost or 0)
if p > product_max[base.id]:
product_max[base.id] = p
highest_price = {}
all_base_ids = set()
for stock, base in list_buy:
all_base_ids.add(base.id)
for stock, base in list_semi:
all_base_ids.add(base.id)
for stock, base in list_product:
all_base_ids.add(base.id)
for base_id in all_base_ids:
price = None
buy_val = buy_max.get(base_id)
if buy_val is not None and buy_val > 0:
price = buy_val
else:
semi_val = semi_max.get(base_id)
if semi_val is not None and semi_val > 0:
price = semi_val
else:
prod_val = product_max.get(base_id)
if prod_val is not None and prod_val > 0:
price = prod_val
highest_price[base_id] = price or 0.0
# 3. 数据整合
all_rows = []
# 处理采购件
for stock, base in list_buy:
# 价格计算
unit_price = float(stock.pre_tax_unit_price or 0)
# 价格计算:使用当前物料基础的最高单价
unit_price = highest_price.get(base.id, 0.0)
tax_rate = float(stock.tax_rate or 0)
price_incl = float(stock.post_tax_unit_price or (unit_price * (1 + tax_rate / 100.0)))
# 根据新单价重新计算含税单价
price_incl = unit_price * (1 + tax_rate / 100.0)
qty = float(stock.stock_quantity or 0)
# 计算不含税总价 = 数量 * 不含税单价
@ -447,13 +492,14 @@ class MaterialBaseService:
# 处理半成品
for stock, base in list_semi:
cost = float(stock.raw_material_cost or 0) + float(stock.manual_cost or 0)
# 使用当前物料基础的最高单价
unit_price = highest_price.get(base.id, 0.0)
qty = float(stock.stock_quantity or 0)
# 半成品不含税总价 = 数量 * 成本
total_val_excl = qty * cost
# 半成品不含税总价 = 数量 * 单价
total_val_excl = qty * unit_price
# 含税总价同上 (税率0)
total_val_incl = qty * cost
total_val_incl = qty * unit_price
ident = stock.batch_number or stock.serial_number or stock.barcode or stock.sku
@ -466,20 +512,21 @@ class MaterialBaseService:
"date": stock.production_date,
"qty": qty,
"avail": float(stock.available_quantity or 0),
"price_excl": cost,
"price_excl": unit_price,
"total_val_excl": total_val_excl,
"tax": 0.0,
"price_incl": cost,
"price_incl": unit_price,
"total_val": total_val_incl
})
# 处理成品
for stock, base in list_product:
cost = float(stock.raw_material_cost or 0) + float(stock.manual_cost or 0)
# 使用当前物料基础的最高单价
unit_price = highest_price.get(base.id, 0.0)
qty = float(stock.stock_quantity or 0)
total_val_excl = qty * cost
total_val_incl = qty * cost
total_val_excl = qty * unit_price
total_val_incl = qty * unit_price
ident = stock.serial_number or stock.barcode or stock.sku
@ -492,10 +539,10 @@ class MaterialBaseService:
"date": stock.production_date,
"qty": qty,
"avail": float(stock.available_quantity or 0),
"price_excl": cost,
"price_excl": unit_price,
"total_val_excl": total_val_excl,
"tax": 0.0,
"price_incl": cost,
"price_incl": unit_price,
"total_val": total_val_incl
})