#!/usr/bin/env python3 """导入 2026-06-11 库存数据""" import sys, os, csv, json, subprocess, pymysql from datetime import datetime sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import importlib.util spec = importlib.util.spec_from_file_location("config", "config.py") config = importlib.util.module_from_spec(spec) spec.loader.exec_module(config) DB_CONFIG = config.DB_CONFIG TMP_DIR = "tmp_csv" os.makedirs(TMP_DIR, exist_ok=True) def parse_int(val): if val is None or val == '' or str(val).upper() == 'NA': return 0 try: return int(float(val)) except: return 0 def parse_float(val): if val is None or val == '' or str(val).upper() == 'NA': return 0.0 try: return float(val) except: return 0.0 def parse_datetime(val): if not val or val == '' or str(val).upper() == 'NA': return None try: return datetime.strptime(val.strip(), '%Y-%m-%d %H:%M:%S') except: try: return datetime.strptime(val.strip(), '%Y-%m-%d') except: return None FILES = [ ("20260611-wdt-kcmx-01", "2026-06-11", "01", "yQod3RxJKG0y54ygF467yORxJkb4Mw9r"), ("20260611-wdt-kcmx-02", "2026-06-11", "02", "l6Pm2Db8D4znYAnxt9kvqaOD8xLq0Ee4"), ("20260611-wdt-kcmx-03", "2026-06-11", "03", "pYLaezmVNe3rBDrNCGE94M5mWrMqPxX6"), ("20260611-wdt-kcmx-04", "2026-06-11", "04", "9bN7RYPWdM970O7GtkM4ogZnVZd1wyK0"), ("20260611-wdt-kcmx-05", "2026-06-11", "05", "OG9lyrgJPzx5KM5ACz0kBwyPWzN67Mw4"), ("20260611-wdt-kcmx-06", "2026-06-11", "06", "X6GRezwJlApOwMOZtrKOnyql8dqbropQ"), ("20260611-wdt-kcmx-07", "2026-06-11", "07", "l6Pm2Db8D4znYAnxt9kvndyo8xLq0Ee4"), ("20260611-wdt-kcmx-08", "2026-06-11", "08", "OG9lyrgJPzx5KM5ACz0k9l26WzN67Mw4"), ("20260611-wdt-kcmx-09", "2026-06-11", "09", "1DKw2zgV2PdeDAe0HPa0LaaD8B5r9YAn"), ("20260611-wdt-kcmx-10", "2026-06-11", "10", "b9Y4gmKWrPnBK2BwHjbgavQxJGXn6lpz"), ("20260611-wdt-kcmx-11", "2026-06-11", "11", "vNG4YZ7JnPzwqNwLH90wZ9XKW2LD0oRE"), ("20260611-wdt-kcmx-12", "2026-06-11", "12", "4lgGw3P8vRrBDmBeUpb9de4R85daZ90D"), ("20260611-wdt-kcmx-13", "2026-06-11", "13", "X6GRezwJlApOwMOZtrKOnYlb8dqbropQ"), ("20260611-wdt-kcmx-15", "2026-06-11", "15", "ndMj49yWjXkyODyehwveX5P1J3pmz5aA"), ("20260611-wdt-kcmx-16", "2026-06-11", "16", "4lgGw3P8vRrBDmBeUpb9GA7985daZ90D"), ("20260611-wdt-kcmx-20", "2026-06-11", "20", "dxXB52LJqnmBErB3tM7LnGeb8qjMp697"), ("20260611-wdt-kcmx-22", "2026-06-11", "22", "0eMKjyp813eL9ALkC45vdYgvVxAZB1Gv"), ("20260611-wdt-kcmx-23", "2026-06-11", "23", "QBnd5ExVEvZ73d7xC251k3gkJyeZqMmz"), ("20260611-wdt-kcmx-24", "2026-06-11", "24", "l6Pm2Db8D4znYAnxt9kvqGAX8xLq0Ee4"), ] total_imported = 0 success = 0 for i, (name, data_date, wh_code, node_id) in enumerate(FILES, 1): print(f"\n[{i}/{len(FILES)}] {name} (仓库:{wh_code})") # 下载 result = subprocess.run( ["dws", "doc", "download", "--node", node_id, "--output", "/dev/stdout", "--format", "json"], capture_output=True, text=True, timeout=30 ) try: url = json.loads(result.stdout).get('resourceUrl') if not url: print(f" ❌ 无法获取下载链接"); continue except: print(f" ❌ 解析下载响应失败"); continue local_path = os.path.join(TMP_DIR, f"{name}.csv") subprocess.run(["curl", "-sL", url, "-o", local_path], capture_output=True, timeout=30) if not os.path.exists(local_path) or os.path.getsize(local_path) < 50: print(f" ❌ 下载失败或文件过小"); continue # 编码处理 r = subprocess.run(["file", local_path], capture_output=True, text=True, timeout=5) if 'ISO' in r.stdout or '8859' in r.stdout: utf8_path = local_path.replace('.csv', '_utf8.csv') subprocess.run(["iconv", "-f", "GBK", "-t", "UTF-8", local_path, "-o", utf8_path], capture_output=True, timeout=10) os.replace(utf8_path, local_path) # 导入 conn = pymysql.connect(**DB_CONFIG, cursorclass=pymysql.cursors.DictCursor) inserted = 0 try: with open(local_path, 'r', encoding='utf-8-sig') as f: reader = csv.DictReader(f) rows = list(reader) with conn.cursor() as cur: for row in rows: try: cur.execute(""" INSERT INTO inventory_detail (data_date, source, warehouse_code, goods_code, product_code, product_name, brand, cost_price, available_qty, production_in_transit, purchase_in_transit, category1, category2, category3, created_time) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """, ( data_date, 'wdt', wh_code, row.get('商家编码', '').strip(), row.get('货品编号', '').strip(), row.get('货品名称', '').strip(), row.get('品牌', '').strip(), parse_float(row.get('成本价', 0)), parse_int(row.get('可用库存', 0)), parse_int(row.get('生产在途量', 0)), parse_int(row.get('采购在途', 0)), row.get('一级类目', '').strip(), row.get('二级类目', '').strip(), row.get('三级类目', '').strip(), parse_datetime(row.get('单品创建时间', '')) )) inserted += 1 except Exception as e: pass conn.commit() print(f" ✅ 导入 {inserted} 条") total_imported += inserted success += 1 except Exception as e: conn.rollback() print(f" ❌ 导入异常: {e}") finally: conn.close() print(f"\n{'='*50}") print(f"库存导入完成! 成功: {success}/{len(FILES)} 个文件, {total_imported} 条记录") print(f"{'='*50}")