新内容

This commit is contained in:
Jimmy
2026-04-27 15:23:00 +08:00
parent fc8f14b301
commit 29954a7af0
8 changed files with 1072 additions and 2 deletions

View File

@@ -0,0 +1,227 @@
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)')
# 创建 BOM 成本表(父件表)
cursor.execute('DROP TABLE IF EXISTS bom_child')
cursor.execute('DROP TABLE IF EXISTS bom_parent')
cursor.execute('''
CREATE TABLE bom_parent (
id INTEGER PRIMARY KEY AUTOINCREMENT,
parent_material_code TEXT UNIQUE,
parent_material_name TEXT
)
''')
# 创建 BOM 成本表(子件明细表)
# 由于是树状结构,我们采用“邻接表”模型,记录每个节点的 parent_id
cursor.execute('''
CREATE TABLE 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__":
print(f"数据库文件将保存在: {DB_PATH}")
conn = init_db()
import_receipt_details(conn)
import_bom_data(conn)
conn.close()
print("全部导入完成!你可以使用 SQLite 客户端连接 erp_data.db 查看数据。")