#!/usr/bin/env python3 """将「液体产品数据」导入生产库 crm_product(租户 shanxia2.0)。""" from __future__ import annotations import re import uuid from datetime import datetime from decimal import Decimal from pathlib import Path from urllib.parse import urlparse import pymysql from dotenv import dotenv_values ROOT = Path(__file__).resolve().parents[1] DATA_FILE = Path(__file__).resolve().parent / "液体产品数据" ENV_FILE = ROOT / "backend" / ".env.production" TENANT_NO = "shanxia2.0" UNIT = "dun" PRODUCT_NO_PREFIX = "SXWL" CREATE_BY = "d3000000000000000000000000000001" def parse_rows(text: str) -> list[dict]: rows: list[dict] = [] for i, line in enumerate(text.splitlines()): line = line.strip("\n") if i == 0 and line.startswith("产品名称"): continue if not line.strip(): continue parts = line.split("\t") while len(parts) < 5: parts.append("") name, category, model, tax, hazard = [p.strip() for p in parts[:5]] if not name: continue tax_num = Decimal(re.sub(r"[^\d.]", "", tax) or "13") is_toxic = 1 if "易制毒" in hazard else 0 is_explosive = 1 if "易制爆" in hazard else 0 rows.append( { "product_name": name, "category_name": category, "model": model, "tax_rate": tax_num, "is_toxic": is_toxic, "is_explosive": is_explosive, } ) return rows def connect(): vals = dotenv_values(ENV_FILE) u = urlparse(vals["DATABASE_URL"].replace("mysql+pymysql://", "mysql://")) return pymysql.connect( host=u.hostname, port=u.port or 3306, user=u.username, password=u.password, database=u.path.lstrip("/"), charset="utf8mb4", connect_timeout=15, autocommit=False, ) def main() -> None: rows = parse_rows(DATA_FILE.read_text(encoding="utf-8")) if not rows: raise SystemExit("未解析到任何产品行") conn = connect() cur = conn.cursor() now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") today = datetime.now().strftime("%Y%m%d") try: # 分类:无机原料 cur.execute( """ SELECT id, category_name FROM crm_product_category WHERE tenant_no=%s AND del_flag=0 AND category_name=%s LIMIT 1 """, (TENANT_NO, "无机原料"), ) cat = cur.fetchone() if not cat: raise RuntimeError("未找到分类「无机原料」") category_id, category_name = cat cur.execute( """ SELECT MAX(CAST(SUBSTRING(product_no,5) AS UNSIGNED)) FROM crm_product WHERE tenant_no=%s AND product_no REGEXP '^SXWL[0-9]+$' """, (TENANT_NO,), ) max_seq = int(cur.fetchone()[0] or 0) cur.execute( """ SELECT barcode FROM crm_product WHERE tenant_no=%s AND del_flag=0 AND barcode LIKE %s ORDER BY barcode DESC LIMIT 1 """, (TENANT_NO, f"{today}%"), ) barcode_row = cur.fetchone() if barcode_row and barcode_row[0] and str(barcode_row[0]).startswith(today): try: barcode_seq = int(str(barcode_row[0])[len(today) :]) + 1 except ValueError: barcode_seq = 1 else: barcode_seq = 1 imported = [] for idx, row in enumerate(rows): max_seq += 1 product_no = f"{PRODUCT_NO_PREFIX}{max_seq:06d}" barcode = f"{today}{barcode_seq:06d}" barcode_seq += 1 pid = uuid.uuid4().hex.upper() cur.execute( """ INSERT INTO crm_product ( id, product_no, product_name, category_id, category_name, model, unit, barcode, price, cost_price, stock, low_stock, tax_rate, is_toxic, is_explosive, status, description, images, sale_count, tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag ) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, NULL, NULL, 0, 10, %s, %s, %s, 'on', NULL, NULL, 0, %s, %s, NULL, %s, '', %s, %s, %s, 0 ) """, ( pid, product_no, row["product_name"], category_id, category_name, row["model"] or None, UNIT, barcode, row["tax_rate"], row["is_toxic"], row["is_explosive"], TENANT_NO, idx + 1, CREATE_BY, now, CREATE_BY, now, ), ) imported.append( { "product_no": product_no, "product_name": row["product_name"], "model": row["model"], "unit": UNIT, "tax_rate": str(row["tax_rate"]), "is_toxic": row["is_toxic"], "is_explosive": row["is_explosive"], "category_name": category_name, "id": pid, } ) conn.commit() print(f"target=production/{TENANT_NO}") print(f"category={category_name}({category_id})") print(f"imported={len(imported)}") print("---") for item in imported: hazard = [] if item["is_toxic"]: hazard.append("易制毒") if item["is_explosive"]: hazard.append("易制爆") print( f"{item['product_no']}\t{item['product_name']}\t{item['model']}\t" f"{item['unit']}\t{item['tax_rate']}\t{','.join(hazard) or '-'}" ) except Exception: conn.rollback() raise finally: conn.close() if __name__ == "__main__": main()