dy-dashboard/import_purchase_order.py
2026-10-28 11:14:17 +08:00

138 lines
4.0 KiB
Python
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
"""
导入采购订单参考表 → 更新 products 表的 supplier_name_match 和 cost_price
匹配规则:
1. 物料编码 精确匹配 product_code
2. 若未命中,去掉已知后缀后再匹配
"""
import csv
import pymysql
import sys
CSV_FILE = "/home/gxd/.openclaw/workspace-dingtalk-assistant/media/inbound/采购订单-20260531-1780213945661.csv"
# 已知后缀(顺序重要:长后缀优先)
SUFFIXES = [
'-FM/GZ', '-TMGJ-NL', '-ALJK-BT', '-ALJK-FM/GZ',
'-TM-BT', '-TM-PZ', '-TM-CH', '-TM-BQ', '-TM-SSM',
'-TM-HMT', '-TM-RG', '-TM-GZ', '-TM-FM/GZ',
'-PDD-BT', '-PDD-PZ', '-PDD-CH', '-PDD-HMT',
'-NL', '-BT', '-PZ', '-CH', '-BQ', '-SSM', '-HMT',
'-RG', '-GZ', '-JD', '-PDD', '-ALJK', '-TM',
'-WPH', '-DW', '-WPH-BT', '-WPH-PZ', '-WPH-CH', '-WPH-BQ',
'-WPH-MD', '-WPH-RG',
]
def strip_suffix(code):
"""去掉已知后缀,返回 base_code;没有匹配返回原 code"""
code = code.strip()
for s in SUFFIXES:
if code.endswith(s):
base = code[:-len(s)]
if base:
return base
return code
def main():
conn = pymysql.connect(
host="127.0.0.1",
port=3306,
user="dy_app",
password="dy_data_2026",
database="dy_data",
charset="utf8mb4"
)
cur = conn.cursor()
# 加载所有 product_code → id 映射
cur.execute("SELECT product_code, id FROM products")
all_products = {}
exact_index = {}
for code, pid in cur.fetchall():
code = code.strip()
all_products[code] = pid
exact_index[code] = pid
print(f"DB 中产品总数: {len(all_products)}")
# 读取 CSV
csv_rows = []
with open(CSV_FILE, encoding="utf-8-sig") as f:
reader = csv.DictReader(f)
for row in reader:
code = row["物料编码"].strip()
supplier = row["供应商"].strip()
price_str = row["含税单价"].strip()
try:
price = float(price_str) if price_str else None
except ValueError:
price = None
csv_rows.append({
"code": code,
"supplier": supplier,
"price": price,
})
print(f"CSV 总行数: {len(csv_rows)}")
print(f"CSV 唯一物料编码数: {len(set(r['code'] for r in csv_rows))}")
# 统计匹配
exact_hits = 0
prefix_hits = 0
no_hits = 0
# 批量更新
update_sql = "UPDATE products SET supplier_name_match=%s, cost_price=%s WHERE id=%s"
updates = []
seen_products = set()
for row in csv_rows:
code = row["code"]
# 1. 精确匹配
if code in exact_index:
pid = exact_index[code]
match_type = "exact"
else:
# 2. 剥离后缀后匹配
base = strip_suffix(code)
if base in exact_index:
pid = exact_index[base]
match_type = "prefix"
else:
# no match
no_hits += 1
continue
if match_type == "exact":
exact_hits += 1
else:
prefix_hits += 1
# 同一个 product 可能被 CSV 多行命中;保留最后一条(或可按需取最小价格)
updates.append((row["supplier"], row["price"], pid))
seen_products.add(pid)
print(f"\n======== 匹配结果 ========")
print(f"精确匹配: {exact_hits}")
print(f"后缀剥离后匹配: {prefix_hits}")
print(f"未匹配: {no_hits}")
print(f"涉及去重后产品数: {len(seen_products)}")
# 执行更新
updated = 0
batch_size = 500
for i in range(0, len(updates), batch_size):
batch = updates[i:i+batch_size]
cur.executemany(update_sql, batch)
conn.commit()
updated += len(batch)
print(f" 已更新 {updated}/{len(updates)}")
conn.close()
print(f"\n✅ 完成!共更新 {updated} 条记录")
if __name__ == "__main__":
main()