90 lines
3.2 KiB
Python
90 lines
3.2 KiB
Python
from collections import defaultdict
|
|
from hashlib import sha256
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
from sqlalchemy import select
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from app.database import SessionLocal # noqa: E402
|
|
from app.models import Product # noqa: E402
|
|
|
|
|
|
def ratio(name: str, salt: str) -> float:
|
|
digest = sha256(f"{name}|{salt}".encode("utf-8")).hexdigest()
|
|
return int(digest[:8], 16) / 0xFFFFFFFF
|
|
|
|
|
|
def generated_values(product_name: str) -> tuple[float, float, float, float]:
|
|
name = product_name or ""
|
|
if "纵梁" in name and "加强板" not in name:
|
|
net = 2.6 + ratio(name, "net") * 1.8
|
|
elif "吸能盒" in name:
|
|
net = 0.75 + ratio(name, "net") * 0.65
|
|
elif "加强板" in name:
|
|
net = 0.55 + ratio(name, "net") * 0.65
|
|
elif any(keyword in name for keyword in ("安装板", "连接板", "端板", "盖板", "封板")):
|
|
net = 0.32 + ratio(name, "net") * 0.62
|
|
else:
|
|
net = 0.85 + ratio(name, "net") * 1.05
|
|
|
|
gross_factor = 1.08 + ratio(name, "gross") * 0.1
|
|
scrap_rate = 0.012 + ratio(name, "scrap") * 0.016
|
|
waste_price = 12.0 + ratio(name, "price") * 2.6
|
|
return (
|
|
round(net, 3),
|
|
round(net * gross_factor, 3),
|
|
round(scrap_rate, 4),
|
|
round(waste_price, 2),
|
|
)
|
|
|
|
|
|
def valid_positive(value) -> float | None:
|
|
if value is None:
|
|
return None
|
|
number = float(value)
|
|
return number if number > 0 else None
|
|
|
|
|
|
def valid_waste_price(value) -> float | None:
|
|
number = valid_positive(value)
|
|
if number is None or number > 25:
|
|
return None
|
|
return number
|
|
|
|
|
|
def group_values(product_name: str, items: list[Product]) -> tuple[float, float, float, float]:
|
|
generated = generated_values(product_name)
|
|
net = next((value for item in items if (value := valid_positive(item.product_net_weight_kg)) is not None), generated[0])
|
|
gross = next((value for item in items if (value := valid_positive(item.product_gross_weight_kg)) is not None), generated[1])
|
|
scrap_rate = next((value for item in items if (value := valid_positive(item.scrap_loss_rate)) is not None), generated[2])
|
|
waste_price = next((value for item in items if (value := valid_waste_price(item.waste_price_yuan_per_kg)) is not None), generated[3])
|
|
return net, gross, scrap_rate, waste_price
|
|
|
|
|
|
def main() -> None:
|
|
with SessionLocal() as db:
|
|
products = db.scalars(select(Product).order_by(Product.product_name, Product.process_name)).all()
|
|
groups: dict[str, list[Product]] = defaultdict(list)
|
|
for product in products:
|
|
groups[product.product_name].append(product)
|
|
|
|
updated_rows = 0
|
|
for product_name, items in groups.items():
|
|
net, gross, scrap_rate, waste_price = group_values(product_name, items)
|
|
for product in items:
|
|
product.product_net_weight_kg = net
|
|
product.product_gross_weight_kg = gross
|
|
product.scrap_loss_rate = scrap_rate
|
|
product.waste_price_yuan_per_kg = waste_price
|
|
updated_rows += 1
|
|
|
|
db.commit()
|
|
print(f"backfilled {updated_rows} product rows, {len(groups)} product names")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|