备份:修复前完整项目快照 2026-04-19
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
-- ============================================
|
||||
-- 商品管理改造 - 数据库迁移脚本
|
||||
-- 支持二级分类树状结构
|
||||
-- ============================================
|
||||
|
||||
-- 1. 创建新的分类表(树状结构)
|
||||
CREATE TABLE IF NOT EXISTS category_tree (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL, -- 分类名称
|
||||
parent_id INTEGER DEFAULT NULL, -- 父分类ID(NULL表示一级分类)
|
||||
level INTEGER DEFAULT 1, -- 层级(1=一级,2=二级)
|
||||
sort_order INTEGER DEFAULT 0, -- 排序
|
||||
description TEXT, -- 描述
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (parent_id) REFERENCES category_tree(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_category_parent ON category_tree(parent_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_category_level ON category_tree(level);
|
||||
|
||||
-- 2. 修改商品表,支持新字段和二级分类
|
||||
-- 先备份原表
|
||||
ALTER TABLE products RENAME TO products_backup;
|
||||
|
||||
-- 创建新的商品表
|
||||
CREATE TABLE products (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL, -- 商品名称
|
||||
model TEXT, -- 型号
|
||||
category_id INTEGER, -- 二级分类ID(关联category_tree)
|
||||
category_name TEXT, -- 分类名称(冗余,方便查询)
|
||||
unit TEXT DEFAULT '件', -- 单位
|
||||
cost_price REAL, -- 成本单价(可为空)
|
||||
price REAL DEFAULT 0, -- 销售单价
|
||||
brand TEXT, -- 品牌
|
||||
specification TEXT, -- 规格参数
|
||||
source TEXT DEFAULT '老挝', -- 来源(中国/老挝)
|
||||
remark TEXT, -- 备注
|
||||
stock_quantity REAL DEFAULT 0, -- 库存数量
|
||||
stock_warning REAL DEFAULT 0, -- 库存预警值
|
||||
status TEXT DEFAULT 'active', -- 状态:active/disabled
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (category_id) REFERENCES category_tree(id)
|
||||
);
|
||||
|
||||
-- 迁移旧数据(简化版,不处理旧数据迁移)
|
||||
-- 直接创建空的新表结构
|
||||
-- INSERT INTO products (
|
||||
-- id, name, model, category_id, category_name, unit,
|
||||
-- price, brand, specification, remark, status, created_at, updated_at
|
||||
-- )
|
||||
-- SELECT
|
||||
-- p.id,
|
||||
-- p.name,
|
||||
-- NULL as model,
|
||||
-- NULL as category_id,
|
||||
-- NULL as category_name,
|
||||
-- COALESCE(p.unit, '件'),
|
||||
-- COALESCE(p.price, 0),
|
||||
-- NULL as brand,
|
||||
-- NULL as specification,
|
||||
-- p.remark,
|
||||
-- 'active',
|
||||
-- p.created_at,
|
||||
-- p.updated_at
|
||||
-- FROM products_backup p;
|
||||
|
||||
-- 删除备份表
|
||||
DROP TABLE products_backup;
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_products_category ON products(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_products_name ON products(name);
|
||||
CREATE INDEX IF NOT EXISTS idx_products_status ON products(status);
|
||||
|
||||
-- 3. 删除旧的categories表(数据已迁移到category_tree)
|
||||
-- 注意:先检查是否还有其他表依赖categories
|
||||
-- DROP TABLE IF EXISTS categories;
|
||||
|
||||
-- ============================================
|
||||
-- 初始化默认分类数据
|
||||
-- ============================================
|
||||
|
||||
-- 插入一级分类
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description) VALUES
|
||||
('电杆横担', NULL, 1, 1, '电杆、横担及相关配件'),
|
||||
('电缆电线', NULL, 1, 2, '各类电缆、电线产品'),
|
||||
('变压器', NULL, 1, 3, '变压器及相关设备'),
|
||||
('开关设备', NULL, 1, 4, '开关、断路器等设备'),
|
||||
('金具', NULL, 1, 5, '电力金具、连接件'),
|
||||
('工具仪器', NULL, 1, 6, '施工工具、检测仪器'),
|
||||
('劳保用品', NULL, 1, 7, '安全防护用品'),
|
||||
('其他材料', NULL, 1, 99, '其他未分类材料');
|
||||
|
||||
-- 插入二级分类(电杆横担)
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '混凝土电杆', id, 2, 1, '混凝土材质电杆'
|
||||
FROM category_tree WHERE name = '电杆横担' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '钢管电杆', id, 2, 2, '钢管材质电杆'
|
||||
FROM category_tree WHERE name = '电杆横担' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '横担', id, 2, 3, '各类横担'
|
||||
FROM category_tree WHERE name = '电杆横担' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '抱箍', id, 2, 4, '电杆抱箍'
|
||||
FROM category_tree WHERE name = '电杆横担' AND level = 1;
|
||||
|
||||
-- 插入二级分类(电缆电线)
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '高压电缆', id, 2, 1, '高压电力电缆'
|
||||
FROM category_tree WHERE name = '电缆电线' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '低压电缆', id, 2, 2, '低压电力电缆'
|
||||
FROM category_tree WHERE name = '电缆电线' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '架空导线', id, 2, 3, '架空绝缘导线'
|
||||
FROM category_tree WHERE name = '电缆电线' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '控制电缆', id, 2, 4, '控制用电缆'
|
||||
FROM category_tree WHERE name = '电缆电线' AND level = 1;
|
||||
|
||||
-- 插入二级分类(变压器)
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '配电变压器', id, 2, 1, '配电用变压器'
|
||||
FROM category_tree WHERE name = '变压器' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '箱式变电站', id, 2, 2, '箱式变电站'
|
||||
FROM category_tree WHERE name = '变压器' AND level = 1;
|
||||
|
||||
-- 插入二级分类(开关设备)
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '断路器', id, 2, 1, '各类断路器'
|
||||
FROM category_tree WHERE name = '开关设备' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '隔离开关', id, 2, 2, '隔离开关'
|
||||
FROM category_tree WHERE name = '开关设备' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '熔断器', id, 2, 3, '熔断器'
|
||||
FROM category_tree WHERE name = '开关设备' AND level = 1;
|
||||
|
||||
-- 插入二级分类(金具)
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '耐张线夹', id, 2, 1, '耐张线夹'
|
||||
FROM category_tree WHERE name = '金具' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '悬垂线夹', id, 2, 2, '悬垂线夹'
|
||||
FROM category_tree WHERE name = '金具' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '连接金具', id, 2, 3, '连接金具'
|
||||
FROM category_tree WHERE name = '金具' AND level = 1;
|
||||
|
||||
-- 插入二级分类(工具仪器)
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '施工工具', id, 2, 1, '电力施工工具'
|
||||
FROM category_tree WHERE name = '工具仪器' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '检测仪器', id, 2, 2, '检测测试仪器'
|
||||
FROM category_tree WHERE name = '工具仪器' AND level = 1;
|
||||
|
||||
-- 插入二级分类(劳保用品)
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '安全帽', id, 2, 1, '安全帽'
|
||||
FROM category_tree WHERE name = '劳保用品' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '安全带', id, 2, 2, '安全带'
|
||||
FROM category_tree WHERE name = '劳保用品' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '绝缘手套', id, 2, 3, '绝缘手套'
|
||||
FROM category_tree WHERE name = '劳保用品' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '绝缘鞋', id, 2, 4, '绝缘鞋'
|
||||
FROM category_tree WHERE name = '劳保用品' AND level = 1;
|
||||
|
||||
-- 插入二级分类(其他材料)
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '标识标牌', id, 2, 1, '标识标牌'
|
||||
FROM category_tree WHERE name = '其他材料' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '接地材料', id, 2, 2, '接地装置材料'
|
||||
FROM category_tree WHERE name = '其他材料' AND level = 1;
|
||||
|
||||
INSERT INTO category_tree (name, parent_id, level, sort_order, description)
|
||||
SELECT '其他', id, 2, 99, '其他未分类'
|
||||
FROM category_tree WHERE name = '其他材料' AND level = 1;
|
||||
|
||||
-- ============================================
|
||||
-- 创建触发器:自动更新updated_at
|
||||
-- ============================================
|
||||
CREATE TRIGGER IF NOT EXISTS update_category_tree_timestamp
|
||||
AFTER UPDATE ON category_tree
|
||||
BEGIN
|
||||
UPDATE category_tree SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS update_products_timestamp
|
||||
AFTER UPDATE ON products
|
||||
BEGIN
|
||||
UPDATE products SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
END;
|
||||
|
||||
-- ============================================
|
||||
-- 迁移完成
|
||||
-- ============================================
|
||||
SELECT '数据库迁移完成' as message;
|
||||
SELECT '商品表已更新,支持二级分类' as message;
|
||||
SELECT '分类表已创建,支持树状结构' as message;
|
||||
@@ -0,0 +1,77 @@
|
||||
-- 采购付款分离改造:数据库迁移脚本
|
||||
-- 创建时间:2026-03-25
|
||||
|
||||
-- ============================================
|
||||
-- 表1:采购申请表 (purchase_requests)
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS purchase_requests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
request_code TEXT UNIQUE NOT NULL,
|
||||
project_id INTEGER NOT NULL,
|
||||
applicant TEXT NOT NULL,
|
||||
request_date DATE NOT NULL,
|
||||
supplier_id INTEGER,
|
||||
supplier_name TEXT,
|
||||
expense_category TEXT NOT NULL,
|
||||
total_amount REAL NOT NULL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
status TEXT DEFAULT 'pending',
|
||||
remark TEXT,
|
||||
attachments TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id),
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id)
|
||||
);
|
||||
|
||||
-- ============================================
|
||||
-- 表2:采购明细表 (purchase_request_items)
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS purchase_request_items (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
purchase_request_id INTEGER NOT NULL,
|
||||
product_id INTEGER,
|
||||
product_name TEXT NOT NULL,
|
||||
specification TEXT,
|
||||
unit TEXT,
|
||||
quantity REAL NOT NULL DEFAULT 0,
|
||||
unit_price REAL NOT NULL DEFAULT 0,
|
||||
total_price REAL NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (purchase_request_id) REFERENCES purchase_requests(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (product_id) REFERENCES products(id)
|
||||
);
|
||||
|
||||
-- ============================================
|
||||
-- 表3:库存记录表 (inventory_records)
|
||||
-- ============================================
|
||||
CREATE TABLE IF NOT EXISTS inventory_records (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
record_type TEXT NOT NULL,
|
||||
project_id INTEGER,
|
||||
purchase_request_id INTEGER,
|
||||
product_id INTEGER NOT NULL,
|
||||
quantity REAL NOT NULL DEFAULT 0,
|
||||
unit_price REAL,
|
||||
total_amount REAL,
|
||||
record_date DATE NOT NULL,
|
||||
operator TEXT,
|
||||
remark TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id),
|
||||
FOREIGN KEY (purchase_request_id) REFERENCES purchase_requests(id),
|
||||
FOREIGN KEY (product_id) REFERENCES products(id)
|
||||
);
|
||||
|
||||
-- ============================================
|
||||
-- 修改:为付款申请表添加采购单关联字段
|
||||
-- ============================================
|
||||
ALTER TABLE payment_requests ADD COLUMN purchase_request_id INTEGER;
|
||||
ALTER TABLE payment_requests ADD COLUMN payment_type TEXT DEFAULT 'company';
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_requests_project ON purchase_requests(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_requests_status ON purchase_requests(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_request_items_request ON purchase_request_items(purchase_request_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_inventory_records_product ON inventory_records(product_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_inventory_records_project ON inventory_records(project_id);
|
||||
@@ -0,0 +1,280 @@
|
||||
-- ============================================
|
||||
-- 采购-付款-物流-退库一体化流程 - 数据库迁移脚本
|
||||
-- 版本:v1.0
|
||||
-- 日期:2026-04-07
|
||||
-- 遵循设计方案:采购-付款-物流-退库一体化流程设计方案.md
|
||||
-- ============================================
|
||||
|
||||
-- ============================================
|
||||
-- 第一部分:创建新表
|
||||
-- ============================================
|
||||
|
||||
-- 表1:跨境物流公司表 (logistics_companies)
|
||||
-- 设计方案章节:9.9 跨境物流公司表
|
||||
CREATE TABLE IF NOT EXISTS logistics_companies (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT UNIQUE NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
address TEXT,
|
||||
phone TEXT,
|
||||
email TEXT,
|
||||
quotation_description TEXT,
|
||||
status TEXT DEFAULT 'active',
|
||||
remark TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_logistics_companies_code ON logistics_companies(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_logistics_companies_status ON logistics_companies(status);
|
||||
|
||||
-- 表2:物流公司收款信息表 (logistics_company_payment_infos)
|
||||
-- 设计方案章节:9.10 物流公司收款信息表
|
||||
CREATE TABLE IF NOT EXISTS logistics_company_payment_infos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
logistics_company_id INTEGER NOT NULL,
|
||||
account_name TEXT,
|
||||
account_number TEXT,
|
||||
bank_name TEXT,
|
||||
qr_code TEXT,
|
||||
is_default INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (logistics_company_id) REFERENCES logistics_companies(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_lc_payment_infos_company ON logistics_company_payment_infos(logistics_company_id);
|
||||
|
||||
-- 表3:物流单表 (logistics_records)
|
||||
-- 设计方案章节:9.4 物流单表
|
||||
CREATE TABLE IF NOT EXISTS logistics_records (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT UNIQUE NOT NULL,
|
||||
purchase_order_id INTEGER NOT NULL,
|
||||
|
||||
ship_from TEXT DEFAULT 'Laos',
|
||||
|
||||
logistics_company_id INTEGER,
|
||||
logistics_company TEXT,
|
||||
tracking_number TEXT,
|
||||
ship_date DATE,
|
||||
ship_location TEXT,
|
||||
estimated_arrival_date DATE,
|
||||
|
||||
customs_arrival_date DATE,
|
||||
customs_clearance_date DATE,
|
||||
|
||||
use_hub INTEGER DEFAULT 0,
|
||||
hub_arrival_date DATE,
|
||||
hub_receiver TEXT,
|
||||
hub_verified_quantity REAL,
|
||||
second_ship_date DATE,
|
||||
|
||||
primary_freight REAL DEFAULT 0,
|
||||
primary_freight_currency TEXT DEFAULT 'CNY',
|
||||
primary_freight_status TEXT DEFAULT 'pending',
|
||||
primary_freight_document TEXT,
|
||||
|
||||
secondary_freight REAL DEFAULT 0,
|
||||
secondary_freight_currency TEXT DEFAULT 'LAK',
|
||||
secondary_freight_status TEXT DEFAULT 'pending',
|
||||
driver_phone TEXT,
|
||||
cargo_weight REAL,
|
||||
transport_distance REAL,
|
||||
|
||||
final_arrival_date DATE,
|
||||
final_location TEXT,
|
||||
|
||||
status TEXT DEFAULT 'pending',
|
||||
remark TEXT,
|
||||
created_by TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (purchase_order_id) REFERENCES purchase_orders(id),
|
||||
FOREIGN KEY (logistics_company_id) REFERENCES logistics_companies(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_logistics_records_code ON logistics_records(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_logistics_records_order ON logistics_records(purchase_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_logistics_records_status ON logistics_records(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_logistics_records_company ON logistics_records(logistics_company_id);
|
||||
|
||||
-- 表4:验收单表 (verification_records)
|
||||
-- 设计方案章节:9.5 验收单表
|
||||
CREATE TABLE IF NOT EXISTS verification_records (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT UNIQUE NOT NULL,
|
||||
purchase_order_id INTEGER NOT NULL,
|
||||
logistics_record_id INTEGER,
|
||||
|
||||
verification_type TEXT DEFAULT 'direct',
|
||||
verification_date DATE NOT NULL,
|
||||
verifier TEXT NOT NULL,
|
||||
|
||||
items TEXT,
|
||||
|
||||
total_ordered REAL,
|
||||
total_received REAL,
|
||||
total_verified REAL,
|
||||
total_rejected REAL DEFAULT 0,
|
||||
|
||||
project_id INTEGER,
|
||||
storage_type TEXT,
|
||||
|
||||
status TEXT DEFAULT 'pending',
|
||||
remark TEXT,
|
||||
attachments TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (purchase_order_id) REFERENCES purchase_orders(id),
|
||||
FOREIGN KEY (logistics_record_id) REFERENCES logistics_records(id),
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_verification_records_code ON verification_records(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_verification_records_order ON verification_records(purchase_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_verification_records_status ON verification_records(status);
|
||||
|
||||
-- 表5:退库单表 (return_records)
|
||||
-- 设计方案章节:9.6 退库单表
|
||||
CREATE TABLE IF NOT EXISTS return_records (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT UNIQUE NOT NULL,
|
||||
project_id INTEGER NOT NULL,
|
||||
|
||||
return_type TEXT DEFAULT 'warehouse',
|
||||
return_date DATE NOT NULL,
|
||||
applicant TEXT NOT NULL,
|
||||
|
||||
items TEXT,
|
||||
|
||||
total_quantity REAL,
|
||||
total_amount REAL,
|
||||
|
||||
cost_adjustment REAL DEFAULT 0,
|
||||
refund_amount REAL DEFAULT 0,
|
||||
|
||||
status TEXT DEFAULT 'pending',
|
||||
remark TEXT,
|
||||
attachments TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_return_records_code ON return_records(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_return_records_project ON return_records(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_return_records_status ON return_records(status);
|
||||
|
||||
-- 表6:材料价格历史表 (material_price_history)
|
||||
-- 设计方案章节:9.7 材料价格历史表
|
||||
CREATE TABLE IF NOT EXISTS material_price_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
product_id INTEGER NOT NULL,
|
||||
purchase_order_id INTEGER,
|
||||
supplier_id INTEGER,
|
||||
supplier_country TEXT,
|
||||
|
||||
unit_price REAL NOT NULL,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
quantity REAL,
|
||||
purchase_date DATE NOT NULL,
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (product_id) REFERENCES products(id),
|
||||
FOREIGN KEY (purchase_order_id) REFERENCES purchase_orders(id),
|
||||
FOREIGN KEY (supplier_id) REFERENCES suppliers(id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_material_price_history_product ON material_price_history(product_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_material_price_history_supplier ON material_price_history(supplier_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_material_price_history_date ON material_price_history(purchase_date);
|
||||
|
||||
-- 表7:项目材料库存表 (project_material_inventory)
|
||||
-- 设计方案章节:9.8 项目材料库存表
|
||||
CREATE TABLE IF NOT EXISTS project_material_inventory (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
project_id INTEGER NOT NULL,
|
||||
product_id INTEGER NOT NULL,
|
||||
product_name TEXT,
|
||||
unit TEXT,
|
||||
|
||||
purchased_quantity REAL DEFAULT 0,
|
||||
received_quantity REAL DEFAULT 0,
|
||||
used_quantity REAL DEFAULT 0,
|
||||
returned_quantity REAL DEFAULT 0,
|
||||
current_quantity REAL DEFAULT 0,
|
||||
|
||||
total_amount REAL DEFAULT 0,
|
||||
average_price REAL DEFAULT 0,
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id),
|
||||
FOREIGN KEY (product_id) REFERENCES products(id),
|
||||
UNIQUE(project_id, product_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_project_material_inventory_project ON project_material_inventory(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_project_material_inventory_product ON project_material_inventory(product_id);
|
||||
|
||||
-- ============================================
|
||||
-- 第二部分:扩展现有表字段(SQLite不支持IF NOT EXISTS,需要手动处理)
|
||||
-- ============================================
|
||||
|
||||
-- 扩展 purchase_orders 表
|
||||
-- 设计方案章节:9.1 采购订单表
|
||||
ALTER TABLE purchase_orders ADD COLUMN project_id INTEGER;
|
||||
ALTER TABLE purchase_orders ADD COLUMN supplier_country TEXT DEFAULT 'Laos';
|
||||
ALTER TABLE purchase_orders ADD COLUMN estimated_amount REAL DEFAULT 0;
|
||||
ALTER TABLE purchase_orders ADD COLUMN paid_amount REAL DEFAULT 0;
|
||||
ALTER TABLE purchase_orders ADD COLUMN contract_url TEXT;
|
||||
ALTER TABLE purchase_orders ADD COLUMN quotation_url TEXT;
|
||||
ALTER TABLE purchase_orders ADD COLUMN actual_delivery_date DATE;
|
||||
ALTER TABLE purchase_orders ADD COLUMN remark TEXT;
|
||||
|
||||
-- 扩展 purchase_order_items 表
|
||||
-- 设计方案章节:9.2 采购订单明细表
|
||||
ALTER TABLE purchase_order_items ADD COLUMN received_quantity REAL DEFAULT 0;
|
||||
ALTER TABLE purchase_order_items ADD COLUMN verified_quantity REAL DEFAULT 0;
|
||||
|
||||
-- 扩展 payment_plans 表
|
||||
-- 设计方案章节:9.3 付款计划表
|
||||
ALTER TABLE payment_plans ADD COLUMN stage TEXT;
|
||||
ALTER TABLE payment_plans ADD COLUMN planned_date DATE;
|
||||
ALTER TABLE payment_plans ADD COLUMN planned_amount REAL;
|
||||
ALTER TABLE payment_plans ADD COLUMN planned_percentage REAL;
|
||||
ALTER TABLE payment_plans ADD COLUMN actual_amount REAL DEFAULT 0;
|
||||
ALTER TABLE payment_plans ADD COLUMN actual_date DATE;
|
||||
ALTER TABLE payment_plans ADD COLUMN payment_request_id INTEGER;
|
||||
ALTER TABLE payment_plans ADD COLUMN reminder_days INTEGER DEFAULT 3;
|
||||
ALTER TABLE payment_plans ADD COLUMN remark TEXT;
|
||||
|
||||
-- 扩展 payment_requests 表
|
||||
-- 设计方案章节:9.12 付款申请表扩展
|
||||
ALTER TABLE payment_requests ADD COLUMN payment_type TEXT DEFAULT 'material';
|
||||
ALTER TABLE payment_requests ADD COLUMN purchase_order_id INTEGER;
|
||||
ALTER TABLE payment_requests ADD COLUMN logistics_company_id INTEGER;
|
||||
ALTER TABLE payment_requests ADD COLUMN logistics_document_url TEXT;
|
||||
ALTER TABLE payment_requests ADD COLUMN driver_phone TEXT;
|
||||
ALTER TABLE payment_requests ADD COLUMN cargo_weight REAL;
|
||||
ALTER TABLE payment_requests ADD COLUMN transport_distance REAL;
|
||||
|
||||
-- 扩展 suppliers 表
|
||||
-- 设计方案章节:9.13 供应商表扩展
|
||||
ALTER TABLE suppliers ADD COLUMN supply_category TEXT;
|
||||
ALTER TABLE suppliers ADD COLUMN country TEXT;
|
||||
ALTER TABLE suppliers ADD COLUMN address TEXT;
|
||||
ALTER TABLE suppliers ADD COLUMN phone TEXT;
|
||||
ALTER TABLE suppliers ADD COLUMN email TEXT;
|
||||
ALTER TABLE suppliers ADD COLUMN status TEXT DEFAULT 'active';
|
||||
|
||||
-- 扩展 purchase_requests 表
|
||||
-- 设计方案章节:9.14 采购申请表扩展
|
||||
ALTER TABLE purchase_requests ADD COLUMN expected_date DATE;
|
||||
|
||||
-- 创建新索引
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_orders_project ON purchase_orders(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_orders_supplier_country ON purchase_orders(supplier_country);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_requests_type ON payment_requests(payment_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_payment_requests_order ON payment_requests(purchase_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_country ON suppliers(country);
|
||||
CREATE INDEX IF NOT EXISTS idx_suppliers_status ON suppliers(status);
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 添加物流公司联系人表迁移脚本
|
||||
* 修复物流公司详情获取失败的问题
|
||||
* 日期:2026-04-08
|
||||
*/
|
||||
|
||||
const db = require('../db-sqlite');
|
||||
|
||||
async function createLogisticsCompanyContactsTable() {
|
||||
try {
|
||||
console.log('开始创建物流公司联系人表...');
|
||||
|
||||
// 创建物流公司联系人表
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS logistics_company_contacts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
logistics_company_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
phone TEXT,
|
||||
email TEXT,
|
||||
position TEXT,
|
||||
is_primary INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (logistics_company_id) REFERENCES logistics_companies(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
// 创建索引
|
||||
await db.query('CREATE INDEX IF NOT EXISTS idx_lc_contacts_company ON logistics_company_contacts(logistics_company_id)');
|
||||
await db.query('CREATE INDEX IF NOT EXISTS idx_lc_contacts_primary ON logistics_company_contacts(is_primary)');
|
||||
|
||||
console.log('物流公司联系人表创建成功!');
|
||||
|
||||
// 检查是否有现有的物流公司,为它们添加默认联系人
|
||||
const companies = await db.query('SELECT id, name FROM logistics_companies');
|
||||
|
||||
if (companies.rows.length > 0) {
|
||||
console.log(`为 ${companies.rows.length} 个物流公司添加默认联系人...`);
|
||||
|
||||
for (const company of companies.rows) {
|
||||
// 检查是否已有联系人
|
||||
const existingContacts = await db.query(
|
||||
'SELECT COUNT(*) as count FROM logistics_company_contacts WHERE logistics_company_id = ?',
|
||||
[company.id]
|
||||
);
|
||||
|
||||
if (existingContacts.rows[0].count === 0) {
|
||||
// 添加默认联系人
|
||||
await db.query(`
|
||||
INSERT INTO logistics_company_contacts
|
||||
(logistics_company_id, name, phone, email, position, is_primary, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, 1, datetime('now'))
|
||||
`, [company.id, '默认联系人', '', '', '联系人']);
|
||||
|
||||
console.log(`为物流公司 "${company.name}" 添加了默认联系人`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('迁移完成!');
|
||||
return { success: true, message: '物流公司联系人表创建成功' };
|
||||
} catch (error) {
|
||||
console.error('创建物流公司联系人表失败:', error);
|
||||
return { success: false, message: '创建物流公司联系人表失败', error: error.message };
|
||||
}
|
||||
}
|
||||
|
||||
// 如果直接运行此脚本
|
||||
if (require.main === module) {
|
||||
createLogisticsCompanyContactsTable()
|
||||
.then(result => {
|
||||
if (result.success) {
|
||||
console.log('✅ 迁移成功:', result.message);
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.error('❌ 迁移失败:', result.message);
|
||||
process.exit(1);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('❌ 迁移执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = createLogisticsCompanyContactsTable;
|
||||
@@ -0,0 +1,29 @@
|
||||
-- 创建分包商收款信息表
|
||||
CREATE TABLE IF NOT EXISTS subcontractor_payment_infos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
subcontractor_id INTEGER NOT NULL,
|
||||
account_name TEXT NOT NULL,
|
||||
bank_account TEXT NOT NULL,
|
||||
bank_name TEXT NOT NULL,
|
||||
qr_code TEXT,
|
||||
is_primary INTEGER DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (subcontractor_id) REFERENCES subcontractors(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_subcontractor_payment_infos_subcontractor_id ON subcontractor_payment_infos(subcontractor_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_subcontractor_payment_infos_is_primary ON subcontractor_payment_infos(is_primary);
|
||||
|
||||
-- 添加注释
|
||||
COMMENT ON TABLE subcontractor_payment_infos IS '分包商收款信息表';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.id IS '主键ID';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.subcontractor_id IS '分包商ID';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.account_name IS '账户名称';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.bank_account IS '银行账号';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.bank_name IS '银行名称';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.qr_code IS '二维码图片路径';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.is_primary IS '是否为主账户(0:否,1:是)';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN subcontractor_payment_infos.updated_at IS '更新时间';
|
||||
@@ -0,0 +1,66 @@
|
||||
// 数据库迁移:添加 password_hash 字段到 users 表
|
||||
const db = require('../db-sqlite');
|
||||
const { hashPassword } = require('../utils/auth');
|
||||
|
||||
async function migrate() {
|
||||
try {
|
||||
console.log('开始迁移:添加 password_hash 字段...');
|
||||
|
||||
// 检查 password_hash 字段是否已存在
|
||||
const result = await db.query("PRAGMA table_info(users)");
|
||||
const hasPasswordHash = result.rows.some(row => row.name === 'password_hash');
|
||||
|
||||
if (hasPasswordHash) {
|
||||
console.log('✅ password_hash 字段已存在,跳过迁移');
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加 password_hash 字段
|
||||
await db.query("ALTER TABLE users ADD COLUMN password_hash TEXT");
|
||||
console.log('✅ password_hash 字段添加成功');
|
||||
|
||||
// 获取所有用户,为现有用户设置默认密码哈希
|
||||
// 注意:这会使用密码 '123456' 为所有用户生成哈希
|
||||
// 首次登录后需要提示用户修改密码
|
||||
const defaultPassword = '123456';
|
||||
const defaultHash = hashPassword(defaultPassword);
|
||||
|
||||
// 更新所有现有用户,将 plaintext password 迁移到 password_hash
|
||||
const usersResult = await db.query("SELECT id, password FROM users WHERE password_hash IS NULL");
|
||||
console.log(`找到 ${usersResult.rows.length} 个需要迁移的用户`);
|
||||
|
||||
for (const user of usersResult.rows) {
|
||||
// 如果已有明文密码,使用相同的密码生成哈希
|
||||
// 如果没有明文密码,使用默认密码
|
||||
const passwordToHash = user.password || defaultPassword;
|
||||
const hashedPassword = hashPassword(passwordToHash);
|
||||
|
||||
await db.query(
|
||||
"UPDATE users SET password_hash = ? WHERE id = ?",
|
||||
[hashedPassword, user.id]
|
||||
);
|
||||
console.log(` 用户 ID ${user.id} 密码已迁移`);
|
||||
}
|
||||
|
||||
console.log('✅ 密码迁移完成');
|
||||
console.log('');
|
||||
console.log('⚠️ 重要提示:');
|
||||
console.log(' - 现有用户密码已迁移(或使用默认密码 123456)');
|
||||
console.log(' - 建议通知所有用户首次登录后修改密码');
|
||||
console.log(' - 新注册用户的密码将自动使用哈希存储');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 迁移失败:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是直接运行此脚本
|
||||
if (require.main === module) {
|
||||
migrate().then(() => {
|
||||
console.log('\n迁移完成');
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { migrate };
|
||||
Reference in New Issue
Block a user