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 # 需要 pip install openpyxl
from openpyxl import Workbook from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill from openpyxl.styles import Font, Alignment, Border, Side, PatternFill
from collections import defaultdict
class MaterialBaseService: class MaterialBaseService:
@ -411,15 +412,59 @@ class MaterialBaseService:
query_product = query_product.filter(cond) query_product = query_product.filter(cond)
list_product = query_product.all() 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. 数据整合 # 3. 数据整合
all_rows = [] all_rows = []
# 处理采购件 # 处理采购件
for stock, base in list_buy: 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) 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) qty = float(stock.stock_quantity or 0)
# 计算不含税总价 = 数量 * 不含税单价 # 计算不含税总价 = 数量 * 不含税单价
@ -447,13 +492,14 @@ class MaterialBaseService:
# 处理半成品 # 处理半成品
for stock, base in list_semi: 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) qty = float(stock.stock_quantity or 0)
# 半成品不含税总价 = 数量 * 成本 # 半成品不含税总价 = 数量 * 单价
total_val_excl = qty * cost total_val_excl = qty * unit_price
# 含税总价同上 (税率0) # 含税总价同上 (税率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 ident = stock.batch_number or stock.serial_number or stock.barcode or stock.sku
@ -466,20 +512,21 @@ class MaterialBaseService:
"date": stock.production_date, "date": stock.production_date,
"qty": qty, "qty": qty,
"avail": float(stock.available_quantity or 0), "avail": float(stock.available_quantity or 0),
"price_excl": cost, "price_excl": unit_price,
"total_val_excl": total_val_excl, "total_val_excl": total_val_excl,
"tax": 0.0, "tax": 0.0,
"price_incl": cost, "price_incl": unit_price,
"total_val": total_val_incl "total_val": total_val_incl
}) })
# 处理成品 # 处理成品
for stock, base in list_product: 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) qty = float(stock.stock_quantity or 0)
total_val_excl = qty * cost total_val_excl = qty * unit_price
total_val_incl = qty * cost total_val_incl = qty * unit_price
ident = stock.serial_number or stock.barcode or stock.sku ident = stock.serial_number or stock.barcode or stock.sku
@ -492,10 +539,10 @@ class MaterialBaseService:
"date": stock.production_date, "date": stock.production_date,
"qty": qty, "qty": qty,
"avail": float(stock.available_quantity or 0), "avail": float(stock.available_quantity or 0),
"price_excl": cost, "price_excl": unit_price,
"total_val_excl": total_val_excl, "total_val_excl": total_val_excl,
"tax": 0.0, "tax": 0.0,
"price_incl": cost, "price_incl": unit_price,
"total_val": total_val_incl "total_val": total_val_incl
}) })