135 lines
4.3 KiB
Python
135 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
||
"""导入成品提货表到数据库"""
|
||
import os, sys, re
|
||
import openpyxl
|
||
import pymysql
|
||
from config import DB_CONFIG
|
||
|
||
EXCEL_PATH = "/home/gxd/.openclaw/workspace-dingtalk-assistant/media/inbound/成品提货表(跟单)6-17-1781683586060.xlsx"
|
||
|
||
COLUMNS = [
|
||
("序号", "INT"),
|
||
("品类", "VARCHAR(100)"),
|
||
("货品编号", "VARCHAR(100)"),
|
||
("货品名称", "VARCHAR(500)"),
|
||
("供应商", "VARCHAR(200)"),
|
||
("可用库存", "INT"),
|
||
("昨日销量", "VARCHAR(50)"),
|
||
("3天均销量", "VARCHAR(50)"),
|
||
("7天均销量", "VARCHAR(50)"),
|
||
("15天均销量", "VARCHAR(50)"),
|
||
("支撑天数", "VARCHAR(50)"),
|
||
("采购总数量", "INT"),
|
||
("生产在途", "INT"),
|
||
("采购在途", "INT"),
|
||
("国内下单表进度", "VARCHAR(200)"),
|
||
("海外下单表进度", "VARCHAR(200)"),
|
||
("产品进度", "VARCHAR(200)"),
|
||
("包材库存", "INT"),
|
||
("采购跟单", "VARCHAR(500)"),
|
||
("采购计划", "VARCHAR(200)"),
|
||
("备注", "TEXT"),
|
||
]
|
||
|
||
CREATE_SQL = """
|
||
CREATE TABLE IF NOT EXISTS finished_products (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
{fields},
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||
"""
|
||
|
||
def main():
|
||
conn = pymysql.connect(**DB_CONFIG)
|
||
cur = conn.cursor()
|
||
|
||
field_defs = ", ".join([f"`{name}` {dtype} DEFAULT NULL" for name, dtype in COLUMNS])
|
||
cur.execute(CREATE_SQL.format(fields=field_defs))
|
||
print("✅ 表 finished_products 已就绪")
|
||
|
||
cur.execute("TRUNCATE TABLE finished_products")
|
||
print("✅ 已清空旧数据")
|
||
|
||
wb = openpyxl.load_workbook(EXCEL_PATH, data_only=True)
|
||
ws = wb.active
|
||
|
||
headers = []
|
||
for col in range(1, ws.max_column + 1):
|
||
val = ws.cell(row=1, column=col).value
|
||
headers.append(str(val).strip() if val else "")
|
||
|
||
expected = [c[0] for c in COLUMNS]
|
||
mismatch = []
|
||
for i, (h, e) in enumerate(zip(headers, expected)):
|
||
if h != e:
|
||
mismatch.append(f" 列{i+1}: 期望'{e}' 实际'{h}'")
|
||
if mismatch:
|
||
print("⚠️ 表头不匹配:")
|
||
for m in mismatch:
|
||
print(m)
|
||
return
|
||
|
||
col_types = [c[1] for c in COLUMNS]
|
||
|
||
def clean_val(val, dtype):
|
||
if val is None: return None
|
||
s = str(val).strip()
|
||
if not s: return None
|
||
if dtype.startswith('INT'):
|
||
nums = re.sub(r'[^0-9\-]', '', s)
|
||
if nums and nums != '-':
|
||
try: return int(nums)
|
||
except: return None
|
||
return None
|
||
if dtype.startswith('DECIMAL'):
|
||
clean = re.sub(r'[^0-9\.\-]', '', s)
|
||
if clean and clean != '.':
|
||
try: return float(clean)
|
||
except: return None
|
||
return None
|
||
return s if s else None
|
||
|
||
placeholders = ", ".join(["%s"] * len(COLUMNS))
|
||
col_names = ", ".join([f"`{c[0]}`" for c in COLUMNS])
|
||
insert_sql = f"INSERT INTO finished_products ({col_names}) VALUES ({placeholders})"
|
||
|
||
total = 0
|
||
batch = []
|
||
for row_idx in range(2, ws.max_row + 1):
|
||
row_data = []
|
||
has_data = False
|
||
for col_idx in range(1, len(COLUMNS) + 1):
|
||
val = ws.cell(row=row_idx, column=col_idx).value
|
||
cleaned = clean_val(val, col_types[col_idx - 1])
|
||
row_data.append(cleaned)
|
||
if cleaned is not None:
|
||
has_data = True
|
||
if not has_data:
|
||
continue
|
||
batch.append(tuple(row_data))
|
||
total += 1
|
||
if len(batch) >= 500:
|
||
cur.executemany(insert_sql, batch)
|
||
conn.commit()
|
||
print(f" 已导入 {total} 行...")
|
||
batch = []
|
||
|
||
if batch:
|
||
cur.executemany(insert_sql, batch)
|
||
conn.commit()
|
||
|
||
print(f"✅ 导入完成,共 {total} 行")
|
||
|
||
cur.execute("SELECT COUNT(*) FROM finished_products")
|
||
print(f"📊 数据库记录数: {cur.fetchone()[0]}")
|
||
|
||
cur.execute("SELECT `货品编号`,`货品名称`,`可用库存`,`供应商`,`品类` FROM finished_products WHERE `货品编号` IS NOT NULL AND `货品编号` != '' ORDER BY `序号` LIMIT 5")
|
||
print("\n前5条记录:")
|
||
for r in cur.fetchall():
|
||
print(f" {r[0]} | {r[1][:25]}... | 库存{r[2]} | {r[3]} | {r[4]}")
|
||
|
||
conn.close()
|
||
|
||
if __name__ == "__main__":
|
||
main()
|