Files
datie-bom/browser_login/import_to_sqlite.py
2026-05-25 16:32:53 +08:00

234 lines
8.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.
import sqlite3
import json
from pathlib import Path
import os
from config import OUTPUT_DIR, DB_PATH
RECEIPT_JSON = OUTPUT_DIR / "receipt_details_full_clean.json"
BOM_JSON = OUTPUT_DIR / "bom_cost_full_tree_final.json"
def init_db():
"""初始化数据库并创建表"""
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
# 创建收货明细表
cursor.execute('''
CREATE TABLE IF NOT EXISTS receipt_details (
id INTEGER PRIMARY KEY AUTOINCREMENT,
purchase_order_code TEXT,
row_no INTEGER,
material_code TEXT,
material_name TEXT,
material_specification TEXT,
warehouse_code TEXT,
warehouse_name TEXT,
supplier_code TEXT,
supplier_name TEXT,
unit_name TEXT,
conversion_unit TEXT,
receive_price REAL,
receipt_time TEXT,
purchase_qty REAL,
receive_qty REAL,
total_amount REAL
)
''')
# 为收货明细表创建索引以加速查询
cursor.execute('CREATE INDEX IF NOT EXISTS idx_receipt_material_code ON receipt_details(material_code)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_receipt_supplier_name ON receipt_details(supplier_name)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_receipt_time ON receipt_details(receipt_time)')
# 注意:为了在打包部署时不丢失用户已抓取的数据,改为 IF NOT EXISTS
cursor.execute('''
CREATE TABLE IF NOT EXISTS bom_parent (
id INTEGER PRIMARY KEY AUTOINCREMENT,
parent_material_code TEXT UNIQUE,
parent_material_name TEXT
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS bom_child (
id INTEGER PRIMARY KEY AUTOINCREMENT,
parent_material_code TEXT, -- 归属的最顶层父件
node_material_code TEXT,
node_material_name TEXT,
bom_level INTEGER,
parent_node_id INTEGER, -- 指向上一级子件的 id如果是一级子件则为空
usage_qty REAL DEFAULT 1.0,
FOREIGN KEY(parent_material_code) REFERENCES bom_parent(parent_material_code),
FOREIGN KEY(parent_node_id) REFERENCES bom_child(id)
)
''')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_bom_child_parent_code ON bom_child(parent_material_code)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_bom_child_node_code ON bom_child(node_material_code)')
conn.commit()
return conn
def import_receipt_details(conn):
"""导入收货明细数据"""
if not RECEIPT_JSON.exists():
print(f"找不到收货明细文件: {RECEIPT_JSON}")
return
print("开始导入收货明细数据...")
with open(RECEIPT_JSON, 'r', encoding='utf-8') as f:
data = json.load(f)
cursor = conn.cursor()
# 清空旧数据(如果需要重复运行),并且我们现在要更新表结构
cursor.execute('DROP TABLE IF EXISTS receipt_details')
cursor.execute('''
CREATE TABLE receipt_details (
id INTEGER PRIMARY KEY AUTOINCREMENT,
purchase_order_code TEXT,
row_no INTEGER,
material_code TEXT,
material_name TEXT,
material_specification TEXT,
warehouse_code TEXT,
warehouse_name TEXT,
supplier_code TEXT,
supplier_name TEXT,
unit_name TEXT,
conversion_unit TEXT,
receive_price REAL,
receipt_time TEXT,
purchase_qty REAL,
receive_qty REAL,
total_amount REAL
)
''')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_receipt_material_code ON receipt_details(material_code)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_receipt_supplier_name ON receipt_details(supplier_name)')
cursor.execute('CREATE INDEX IF NOT EXISTS idx_receipt_time ON receipt_details(receipt_time)')
count = 0
for item in data:
p_qty = item.get("进货数量")
r_qty = item.get("收货数量")
cursor.execute('''
INSERT INTO receipt_details (
purchase_order_code, row_no, material_code, material_name,
material_specification, warehouse_code, warehouse_name,
supplier_code, supplier_name, unit_name, conversion_unit,
receive_price, receipt_time,
purchase_qty, receive_qty, total_amount
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
item.get("采购订单号"),
item.get("行号"),
item.get("物料代码"),
item.get("物料名称"),
item.get("物料规格"),
item.get("仓库代码"),
item.get("仓库名称"),
item.get("供应商代码"),
item.get("供应商名称"),
item.get("单位名称"),
item.get("转换单位"),
item.get("收货单价"),
item.get("收货时间"),
p_qty,
r_qty,
item.get("收货总金额")
))
count += 1
conn.commit()
print(f"成功导入 {count} 条收货明细数据!")
def _insert_bom_tree(cursor, parent_material_code, tree_nodes, parent_node_id=None):
"""递归插入 BOM 树节点"""
for node in tree_nodes:
# 提取当前节点信息
node_code = node.get("childMaterialCode")
node_name = node.get("childMaterialName")
bom_level = node.get("bomLevel")
usage_qty = float(node.get("usageQty") or 1.0)
# 插入当前节点
cursor.execute('''
INSERT INTO bom_child (
parent_material_code, node_material_code, node_material_name, bom_level, parent_node_id, usage_qty
) VALUES (?, ?, ?, ?, ?, ?)
''', (parent_material_code, node_code, node_name, bom_level, parent_node_id, usage_qty))
# 获取刚插入的节点 ID作为其子节点的 parent_node_id
current_node_id = cursor.lastrowid
# 如果有子节点,递归插入
sub_items = node.get("sub_items", [])
if sub_items:
_insert_bom_tree(cursor, parent_material_code, sub_items, current_node_id)
def import_bom_data(conn):
"""导入 BOM 成本树状数据"""
if not BOM_JSON.exists():
print(f"找不到 BOM 成本文件: {BOM_JSON}")
return
print("开始导入 BOM 成本数据...")
with open(BOM_JSON, 'r', encoding='utf-8') as f:
data = json.load(f)
cursor = conn.cursor()
# 清空旧数据
cursor.execute('DELETE FROM bom_child')
cursor.execute('DELETE FROM bom_parent')
parent_count = 0
for parent in data:
parent_code = parent.get("parentMaterialCode")
parent_name = parent.get("parentMaterialName")
# 忽略空父件
if not parent_code:
continue
try:
cursor.execute('''
INSERT INTO bom_parent (parent_material_code, parent_material_name)
VALUES (?, ?)
''', (parent_code, parent_name))
parent_count += 1
# 递归处理这棵树
tree = parent.get("bom_cost_tree", [])
if tree:
_insert_bom_tree(cursor, parent_code, tree, parent_node_id=None)
except sqlite3.IntegrityError:
print(f"警告: 父件重复 {parent_code},跳过")
conn.commit()
# 统计插入的子件数量
cursor.execute('SELECT COUNT(*) FROM bom_child')
child_count = cursor.fetchone()[0]
print(f"成功导入 {parent_count} 个 BOM 父件,包含 {child_count} 个子件节点!")
if __name__ == "__main__":
import sys
print(f"数据库文件将保存在: {DB_PATH}")
conn = init_db()
# 允许通过命令行参数单独导入某一部分数据
args = sys.argv[1:]
if "--bom-only" in args:
import_bom_data(conn)
elif "--receipt-only" in args:
import_receipt_details(conn)
else:
# 默认全量导入
import_receipt_details(conn)
import_bom_data(conn)
conn.close()
print("全部导入完成!你可以使用 SQLite 客户端连接 erp_data.db 查看数据。")