CaiWuXiTong/scripts/summarize_product_weighted_average_result.py

83 lines
3.0 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
import argparse
import json
from datetime import datetime
from pathlib import Path
def money(value: object) -> str:
return f"{float(value or 0):,.2f}"
def brief(result: dict) -> str:
status = str(result.get("status") or "failed")
month = str(result.get("report_month") or "")[:7]
if status in {"blocked", "failed"}:
return f"{month or '本月'} 未执行:{result.get('message') or '上游数据不完整'}"
weighted = result.get("weighted_average")
if isinstance(weighted, dict):
weighted_brief = brief(weighted)
cost = result.get("product_cost") or {}
cost_brief = (
f"正常匹配 {int(cost.get('normal_matched_rows') or 0):,} 行;"
f"排除占位 {int(cost.get('placeholder_excluded_rows') or 0):,} 行;"
f"排除组合装主行 {int(cost.get('bundle_parent_excluded_rows') or 0):,} 行;"
f"待核验成本 {int(cost.get('pending_cost_rows') or 0):,} 行 / "
f"{float(cost.get('pending_cost_quantity') or 0):,.2f} 件"
)
return f"{weighted_brief};商品成本:{cost_brief}"
totals = result.get("totals") or {}
inbound = result.get("inbound") or {}
anomalies = result.get("anomalies") or {}
reasons = "、".join(
str(item.get("label") or item.get("code") or "未知异常")
for item in anomalies.get("reasons") or []
)
suffix = f";待复核:{reasons}" if reasons else ""
if status == "already_computed":
prefix = "已完成,本次跳过重算"
elif status == "review_required":
prefix = "计算完成,需人工复核"
else:
prefix = "计算完成"
return (
f"{month} {prefix}:总行数 {int(totals.get('rows') or 0):,};"
f"期初 {float(totals.get('opening_quantity') or 0):,.2f} 件 / "
f"{money(totals.get('opening_amount'))};"
f"入库 {float(inbound.get('matched_quantity') or 0):,.2f} 件 / "
f"{money(inbound.get('matched_amount'))};"
f"加权单价 {int(totals.get('weighted_price_rows') or 0):,} 行;"
f"异常 {int(anomalies.get('affected_rows') or 0):,} 行{suffix}"
)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--input", required=True)
parser.add_argument("--result-json", required=True)
args = parser.parse_args()
result = json.loads(Path(args.input).read_text(encoding="utf-8"))
summary = brief(result)
payload = {
"finished_at": datetime.now().astimezone().isoformat(timespec="seconds"),
"brief": summary,
"result": result,
}
output = Path(args.result_json)
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(
json.dumps(payload, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
print(summary)
return 0 if result.get("status") not in {"blocked", "failed", "missing"} else 1
if __name__ == "__main__":
raise SystemExit(main())