Update 2026-06-24 10:47:45
This commit is contained in:
+192
-50
@@ -1,58 +1,200 @@
|
||||
SET client_encoding = 'UTF8';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(255) UNIQUE,
|
||||
name VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
phone VARCHAR(255),
|
||||
role VARCHAR(50),
|
||||
password_hash VARCHAR(255),
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
);
|
||||
-- ============================================================
|
||||
-- 云海财务系统 - 示例数据
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS customers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
address VARCHAR(255),
|
||||
remark TEXT,
|
||||
contact_person VARCHAR(255),
|
||||
phone VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
project_code VARCHAR(255),
|
||||
customer_id INTEGER,
|
||||
project_manager_id INTEGER,
|
||||
contract_amount NUMERIC,
|
||||
status VARCHAR(50),
|
||||
location VARCHAR(255),
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 1. 插入用户数据
|
||||
INSERT INTO users (username, name, email, phone, role, password_hash, created_at, updated_at) VALUES
|
||||
('admin', '系统管理员', 'admin@yunhai.com', '13800000001', 'admin', '$2a$10$xyz', NOW(), NOW()),
|
||||
('finance', '财务专员', 'finance@yunhai.com', '13800000002', 'finance', '$2a$10$xyz', NOW(), NOW()),
|
||||
('manager', '项目经理', 'manager@yunhai.com', '13800000003', 'manager', '$2a$10$xyz', NOW(), NOW()),
|
||||
('employee', '普通员工', 'employee@yunhai.com', '13800000004', 'employee', '$2a$10$xyz', NOW(), NOW())
|
||||
-- 1. 用户
|
||||
INSERT INTO users (username, name, email, phone, role, password_hash, created_at, updated_at) VALUES
|
||||
('admin', '系统管理员', 'admin@xinmi.cloud', '13800000001', 'admin', '$2b$10$XYs6Rc6LVqeFsmY4cMZdmOy.bhSc4Ib3yFfwj5kt.G.oHNiuZSkZm', NOW(), NOW()),
|
||||
('finance', '财务专员', 'finance@xinmi.cloud', '13800000002', 'finance', '$2b$10$XYs6Rc6LVqeFsmY4cMZdmOy.bhSc4Ib3yFfwj5kt.G.oHNiuZSkZm', NOW(), NOW()),
|
||||
('manager', '项目经理', 'manager@xinmi.cloud', '13800000003', 'manager', '$2b$10$XYs6Rc6LVqeFsmY4cMZdmOy.bhSc4Ib3yFfwj5kt.G.oHNiuZSkZm', NOW(), NOW()),
|
||||
('employee', '普通员工', 'employee@xinmi.cloud', '13800000004', 'employee', '$2b$10$XYs6Rc6LVqeFsmY4cMZdmOy.bhSc4Ib3yFfwj5kt.G.oHNiuZSkZm', NOW(), NOW())
|
||||
ON CONFLICT (username) DO NOTHING;
|
||||
|
||||
-- 2. 插入客户数据
|
||||
INSERT INTO customers (name, address, remark, contact_person, phone, email, created_at, updated_at) VALUES
|
||||
-- 2. 客户
|
||||
INSERT INTO customers (name, address, remark, contact_person, phone, email, created_at, updated_at)
|
||||
SELECT * FROM (VALUES
|
||||
('老挝国家电力公司', '万象市', '大客户', 'Somphong', '020-11111111', 'edl@laos.com', NOW(), NOW()),
|
||||
('万象基建集团', '万象市', '长期合作', 'Champa', '020-22222222', 'infra@laos.com', NOW(), NOW()),
|
||||
('琅勃拉邦电力局', '琅勃拉邦', '', 'Keo', '020-33333333', 'lpq@laos.com', NOW(), NOW());
|
||||
('琅勃拉邦电力局', '琅勃拉邦', '', 'Keo', '020-33333333', 'lpq@laos.com', NOW(), NOW())
|
||||
) AS v(name, address, remark, contact_person, phone, email, created_at, updated_at)
|
||||
WHERE NOT EXISTS (SELECT 1 FROM customers WHERE name = v.name);
|
||||
|
||||
-- 3. 插入项目数据 (假设customer_id与上表对应)
|
||||
INSERT INTO projects (name, project_code, customer_id, project_manager_id, contract_amount, status, location, created_at, updated_at) VALUES
|
||||
('万象22kV线路工程', 'P2026-001', 1, 3, 1500000, 'in_progress', '万象市赛塔尼县', NOW(), NOW()),
|
||||
('琅勃拉邦变电站改造', 'P2026-002', 3, 3, 800000, 'planning', '琅勃拉邦', NOW(), NOW()),
|
||||
('南塔电力抢修', 'P2026-003', 1, 3, 300000, 'completed', '南塔省', NOW(), NOW());
|
||||
-- 3. 项目
|
||||
INSERT INTO projects (name, project_code, customer_id, project_manager_id, contract_amount, status, location, start_date, description, created_at, updated_at)
|
||||
SELECT v.name, v.project_code, c.id, u.id, v.contract_amount, v.status, v.location, v.start_date::date, v.description, NOW(), NOW()
|
||||
FROM (VALUES
|
||||
('万象22kV线路工程', 'P2026-001', '老挝国家电力公司', 'manager', 1500000, 'in_progress', '万象市赛塔尼县', '2026-01-15', '22kV架空线路新建工程'),
|
||||
('琅勃拉邦变电站改造', 'P2026-002', '琅勃拉邦电力局', 'manager', 800000, 'planning', '琅勃拉邦', '2026-03-01', '35kV变电站设备更新改造'),
|
||||
('南塔电力抢修', 'P2026-003', '老挝国家电力公司', 'manager', 300000, 'completed', '南塔省', '2025-11-01', '台风后应急抢修工程')
|
||||
) AS v(name, project_code, customer_name, manager_username, contract_amount, status, location, start_date, description)
|
||||
JOIN customers c ON c.name = v.customer_name
|
||||
JOIN users u ON u.username = v.manager_username
|
||||
WHERE NOT EXISTS (SELECT 1 FROM projects WHERE project_code = v.project_code);
|
||||
|
||||
-- 4. 供应商
|
||||
INSERT INTO suppliers (name, address, contact_person, phone, email, product_category, supplier_source, country, remark, created_at, updated_at) VALUES
|
||||
('万象电力器材有限公司', '万象市工业区', 'Bounmy', '020-55551111', 'sales@pole.la', '电杆横担', '老挝', '老挝', '本地电杆供应商', NOW(), NOW()),
|
||||
('昆明电缆集团', '云南省昆明市', 'Zhang Wei', '13888880001', 'export@km-cable.cn', '电缆电线', '中国', '中国', '高压电缆主力供应商', NOW(), NOW()),
|
||||
('深圳开关设备厂', '广东省深圳市', 'Li Ming', '13900001111', 'sales@sz-switch.cn', '开关设备', '中国', '中国', '断路器与隔离开关', NOW(), NOW());
|
||||
|
||||
INSERT INTO contacts (entity_id, entity_type, name, position, phone, is_primary, created_at, updated_at) VALUES
|
||||
(1, 'supplier', 'Bounmy', '销售经理', '020-55551111', 1, NOW(), NOW()),
|
||||
(2, 'supplier', 'Zhang Wei', '出口经理', '13888880001', 1, NOW(), NOW());
|
||||
|
||||
INSERT INTO supplier_payment_infos (supplier_id, account_name, bank_account, bank_name, is_primary, created_at, updated_at) VALUES
|
||||
(1, '万象电力器材有限公司', 'LA0012345678', 'BCEL Bank', 1, NOW(), NOW()),
|
||||
(2, '昆明电缆集团', '6222021234567890', '中国工商银行昆明分行', 1, NOW(), NOW());
|
||||
|
||||
-- 5. 分包商
|
||||
INSERT INTO subcontractors (name, address, contact_person, phone, email, specialty, country, score, remark, created_at, updated_at) VALUES
|
||||
('老挝电力施工一队', '万象市', 'Kham', '020-66662222', 'team1@laos.com', '架空线路施工', '老挝', 95, '经验丰富', NOW(), NOW()),
|
||||
('万象电气安装公司', '万象市', 'Phone', '020-77773333', 'install@laos.com', '变电站安装', '老挝', 100, '新合作方', NOW(), NOW());
|
||||
|
||||
-- 6. 商品分类与商品
|
||||
INSERT INTO product_categories (name, parent_id) VALUES
|
||||
('电杆横担', NULL),
|
||||
('电缆电线', NULL),
|
||||
('开关设备', NULL);
|
||||
|
||||
INSERT INTO product_categories (name, parent_id) VALUES
|
||||
('混凝土电杆', 1),
|
||||
('高压电缆', 2),
|
||||
('断路器', 3);
|
||||
|
||||
INSERT INTO products (name, model, category_id, category_name, unit, cost_price, price, brand, specification, source, stock_quantity, status, created_at, updated_at) VALUES
|
||||
('12米混凝土电杆', 'DP-12M', 4, '混凝土电杆', '根', 850, 1200, '万象建材', 'φ190×12000mm', '老挝', 200, 'active', NOW(), NOW()),
|
||||
('JKLYJ-1-10 架空绝缘导线', 'JKLYJ-10', 5, '高压电缆', '米', 8.5, 12, '昆明电缆', '1×10mm²', '中国', 5000, 'active', NOW(), NOW()),
|
||||
('ZW32-12 真空断路器', 'ZW32-12', 6, '断路器', '台', 8500, 12000, '深圳开关', '12kV户外型', '中国', 15, 'active', NOW(), NOW());
|
||||
|
||||
-- 7. 汇率
|
||||
INSERT INTO exchange_rates (currency_code, to_currency_code, rate, effective_date, created_at) VALUES
|
||||
('CNY', 'LAK', 2900, CURRENT_DATE, NOW()),
|
||||
('CNY', 'USD', 0.143, CURRENT_DATE, NOW()),
|
||||
('CNY', 'THB', 4.8, CURRENT_DATE, NOW()),
|
||||
('USD', 'LAK', 20300, CURRENT_DATE, NOW());
|
||||
|
||||
-- 8. 财务分类
|
||||
INSERT INTO expense_categories (category_level1, category_level2, label, description, sort_order) VALUES
|
||||
('income', 'contract_payment', '项目合同收款', '客户按合同打款到账', 1),
|
||||
('project', 'material', '材料采购', '电杆、导线、电缆等', 1),
|
||||
('project', 'subcontract', '施工分包', '外包施工队费用', 3),
|
||||
('company', 'salary', '工资薪酬', '办公室管理人员工资', 1)
|
||||
ON CONFLICT (category_level1, category_level2) DO NOTHING;
|
||||
|
||||
-- 9. 预支 / 报销 / 付款
|
||||
INSERT INTO advances (applicant_id, project_id, amount, currency, amount_cny, reason, advance_date, advance_code, status, applicant, created_at, updated_at)
|
||||
SELECT u.id, p.id, v.amount, v.currency, v.amount_cny, v.reason, v.advance_date::date, v.advance_code, v.status, v.applicant, NOW(), NOW()
|
||||
FROM (VALUES
|
||||
(4, 1, 5000, 'CNY', 5000, '万象项目现场出差备用金', '2026-02-10', 'ADV-20260210-001', 'approved', '普通员工'),
|
||||
(4, 1, 2000000, 'LAK', 690, '现场零星采购备用金', '2026-03-05', 'ADV-20260305-001', 'pending', '普通员工')
|
||||
) AS v(applicant_id, project_id, amount, currency, amount_cny, reason, advance_date, advance_code, status, applicant)
|
||||
JOIN users u ON u.id = v.applicant_id
|
||||
JOIN projects p ON p.id = v.project_id
|
||||
ON CONFLICT (advance_code) DO NOTHING;
|
||||
|
||||
INSERT INTO reimbursements (user_id, project_id, amount, currency, amount_cny, reason, reimbursement_date, reimbursement_code, status, applicant, expense_type, created_at, updated_at)
|
||||
SELECT u.id, p.id, v.amount, v.currency, v.amount_cny, v.reason, v.reimbursement_date::date, v.reimbursement_code, v.status, v.applicant, v.expense_type, NOW(), NOW()
|
||||
FROM (VALUES
|
||||
(4, 1, 3200, 'CNY', 3200, '万象项目出差住宿费及交通费', '2026-02-20', 'REIM-20260220-001', 'pending', '普通员工', 'travel')
|
||||
) AS v(user_id, project_id, amount, currency, amount_cny, reason, reimbursement_date, reimbursement_code, status, applicant, expense_type)
|
||||
JOIN users u ON u.id = v.user_id
|
||||
JOIN projects p ON p.id = v.project_id
|
||||
ON CONFLICT (reimbursement_code) DO NOTHING;
|
||||
|
||||
INSERT INTO payment_requests (request_code, applicant, payment_date, payee, bank_account, bank_name, amount, currency, reason, status, expense_type, expense_category, project_id, created_at, updated_at)
|
||||
SELECT v.request_code, v.applicant, v.payment_date::date, v.payee, v.bank_account, v.bank_name, v.amount, v.currency, v.reason, v.status, v.expense_type, v.expense_category, p.id, NOW(), NOW()
|
||||
FROM (VALUES
|
||||
('PAY-20260301-001', '财务专员', '2026-03-01', '万象电力器材有限公司', 'LA0012345678', 'BCEL Bank', 120000, 'CNY', '万象项目电杆首付款', 'approved', 'project', 'material', 'P2026-001'),
|
||||
('PAY-20260315-001', '财务专员', '2026-03-15', '办公室房东', '6222009988776655', '中国建设银行', 15000, 'CNY', '2026年3月办公室租金', 'pending', 'company', 'rent', NULL)
|
||||
) AS v(request_code, applicant, payment_date, payee, bank_account, bank_name, amount, currency, reason, status, expense_type, expense_category, project_code)
|
||||
LEFT JOIN projects p ON p.project_code = v.project_code
|
||||
ON CONFLICT (request_code) DO NOTHING;
|
||||
|
||||
-- 10. 采购申请与订单
|
||||
INSERT INTO purchase_requests (request_code, project_id, applicant, request_date, expense_category, purchase_type, total_amount, currency, status, brief_description, remark, created_at, updated_at)
|
||||
SELECT v.request_code, p.id, v.applicant, v.request_date::date, v.expense_category, v.purchase_type, v.total_amount, v.currency, v.status, v.brief_description, v.remark, NOW(), NOW()
|
||||
FROM (VALUES
|
||||
('PUR-20260310-001', 'P2026-001', '项目经理', '2026-03-10', 'material', 'inventory', 144000, 'CNY', 'approved', '万象项目电杆及金具采购', '预计120根12米电杆'),
|
||||
('PUR-20260318-001', 'P2026-002', '项目经理', '2026-03-18', 'equipment', 'inventory', 36000, 'CNY', 'pending', '琅勃拉邦变电站断路器采购', '待询价确认型号')
|
||||
) AS v(request_code, project_code, applicant, request_date, expense_category, purchase_type, total_amount, currency, status, brief_description, remark)
|
||||
JOIN projects p ON p.project_code = v.project_code
|
||||
ON CONFLICT (request_code) DO NOTHING;
|
||||
|
||||
INSERT INTO purchase_orders (code, purchase_request_id, project_id, supplier_id, currency, status, estimated_amount, remark, created_by, created_at, updated_at)
|
||||
SELECT 'PO202603120001', pr.id, p.id, s.id, 'CNY', 'confirmed', 144000, '电杆采购正式订单', 'manager', NOW(), NOW()
|
||||
FROM purchase_requests pr
|
||||
JOIN projects p ON p.project_code = 'P2026-001'
|
||||
JOIN suppliers s ON s.name = '万象电力器材有限公司'
|
||||
WHERE pr.request_code = 'PUR-20260310-001'
|
||||
ON CONFLICT (code) DO NOTHING;
|
||||
|
||||
INSERT INTO purchase_order_items (order_id, product_id, product_name, unit, quantity, unit_price, total_price, created_at) VALUES
|
||||
(1, 1, '12米混凝土电杆', '根', 120, 1200, 144000, NOW());
|
||||
|
||||
INSERT INTO payment_plans (purchase_order_id, project_id, plan_name, stage, planned_date, planned_amount, planned_percentage, status, created_at, updated_at) VALUES
|
||||
(1, 1, '电杆采购首付款', '首付30%', '2026-03-15', 43200, 30, 'pending', NOW(), NOW()),
|
||||
(1, 1, '电杆采购尾款', '尾款70%', '2026-04-15', 100800, 70, 'pending', NOW(), NOW());
|
||||
|
||||
-- 11. 付款节点与记录
|
||||
INSERT INTO payment_nodes (project_id, name, amount, due_date, status, created_at, updated_at) VALUES
|
||||
(1, '合同签订预付款', 450000, '2026-02-01', 'completed', NOW(), NOW()),
|
||||
(1, '材料到场进度款', 450000, '2026-04-01', 'pending', NOW(), NOW()),
|
||||
(1, '竣工验收尾款', 600000, '2026-08-01', 'pending', NOW(), NOW());
|
||||
|
||||
INSERT INTO payment_records (node_id, amount, payment_date, method, status, created_at) VALUES
|
||||
(1, 450000, '2026-02-05', '银行转账', 'completed', NOW());
|
||||
|
||||
-- 12. 物流公司
|
||||
INSERT INTO logistics_companies (code, name, address, phone, status, remark, created_at, updated_at) VALUES
|
||||
('LC-001', '中老跨境物流', '万象市物流园', '020-88889999', 'active', '中国至老挝跨境运输', NOW(), NOW()),
|
||||
('LC-002', '万象本地运输', '万象市', '020-88887777', 'active', '老挝境内二次转运', NOW(), NOW());
|
||||
|
||||
-- 13. 施工日志
|
||||
INSERT INTO construction_logs (project_id, log_date, weather, recorded_by, work_content, next_plan, issues, created_at) VALUES
|
||||
(1, '2026-03-15', '晴', '项目经理', '完成A段电杆基坑开挖20基', '继续B段基坑开挖', '部分场地积水需排水', NOW()),
|
||||
(1, '2026-03-16', '多云', '项目经理', '电杆到货验收120根,合格118根', '组织电杆组立', '2根电杆表面裂纹退回', NOW());
|
||||
|
||||
-- 14. 工程模板
|
||||
INSERT INTO project_type_templates (name, description, phases, is_system, created_at, updated_at) VALUES
|
||||
('架空线路工程', '架空线路项目标准阶段', '[
|
||||
{"order":1,"name":"勘察设计","type":"serial","depends":[],"sub_items":["线路勘察","图纸设计"]},
|
||||
{"order":2,"name":"物资采购","type":"parallel","depends":[1],"sub_items":["电杆采购","导线采购"]},
|
||||
{"order":3,"name":"基础施工","type":"serial","depends":[1],"sub_items":["杆坑开挖","基础浇筑"]},
|
||||
{"order":4,"name":"架线施工","type":"serial","depends":[2,3],"sub_items":["电杆组立","放线紧线"]},
|
||||
{"order":5,"name":"竣工验收","type":"serial","depends":[4],"sub_items":[]}
|
||||
]'::jsonb, true, NOW(), NOW());
|
||||
|
||||
INSERT INTO project_phases (project_id, phase_name, phase_order, phase_type, status, sub_items, created_at) VALUES
|
||||
(1, '勘察设计', 1, 'serial', 'completed', '[{"name":"现场勘察","done":true},{"name":"图纸设计","done":true}]'::jsonb, NOW()),
|
||||
(1, '物资采购', 2, 'parallel', 'in_progress', '[{"name":"电杆采购","done":true},{"name":"导线采购","done":false}]'::jsonb, NOW()),
|
||||
(1, '基础施工', 3, 'serial', 'pending', '[{"name":"杆坑开挖","done":false}]'::jsonb, NOW());
|
||||
|
||||
-- 15. 预算项目
|
||||
INSERT INTO budget_projects (budget_code, name, customer_id, business_manager_id, status, total_amount, currency, survey_notes, remark, created_by, created_at, updated_at)
|
||||
SELECT 'BJ0001', '万象22kV线路工程预算', c.id, u.id, 'approved', 1450000, 'CNY', '初版预算报价', '含材料、施工、运输', u.id, NOW(), NOW()
|
||||
FROM customers c, users u
|
||||
WHERE c.name = '老挝国家电力公司' AND u.username = 'manager'
|
||||
AND NOT EXISTS (SELECT 1 FROM budget_projects WHERE budget_code = 'BJ0001');
|
||||
|
||||
INSERT INTO budget_quotations (budget_project_id, version, quotation_date, amount, currency, notes, status, created_at)
|
||||
SELECT bp.id, 1, '2026-01-10', 1450000, 'CNY', '含材料、施工、运输', 'approved', NOW()
|
||||
FROM budget_projects bp
|
||||
WHERE bp.budget_code = 'BJ0001'
|
||||
AND NOT EXISTS (SELECT 1 FROM budget_quotations WHERE budget_project_id = bp.id);
|
||||
|
||||
-- 16. 财务账本记录
|
||||
INSERT INTO financial_records (record_code, txn_type, category_level1, category_level2, project_id, user_name, amount_original, currency, exchange_rate, amount_cny, record_date, counterparty_name, description, status, created_at, updated_at)
|
||||
SELECT v.record_code, v.txn_type, v.category_level1, v.category_level2, p.id, v.user_name, v.amount_original, v.currency, v.exchange_rate, v.amount_cny, v.record_date::date, v.counterparty_name, v.description, v.status, NOW(), NOW()
|
||||
FROM (VALUES
|
||||
('FR-INC-20260205-001', 'income', 'income', 'contract_payment', 'P2026-001', '财务专员', 450000, 'CNY', 1, 450000, '2026-02-05', '老挝国家电力公司', '万象项目合同预付款到账', 'confirmed'),
|
||||
('FR-EXP-20260312-001', 'expense', 'project', 'material', 'P2026-001', '财务专员', 43200, 'CNY', 1, 43200, '2026-03-12', '万象电力器材有限公司', '电杆采购首付款', 'confirmed'),
|
||||
('FR-EXP-20260315-001', 'expense', 'company', 'rent', NULL, '财务专员', 15000, 'CNY', 1, 15000, '2026-03-15', '办公室房东', '3月办公室租金', 'confirmed')
|
||||
) AS v(record_code, txn_type, category_level1, category_level2, project_code, user_name, amount_original, currency, exchange_rate, amount_cny, record_date, counterparty_name, description, status)
|
||||
LEFT JOIN projects p ON p.project_code = v.project_code
|
||||
ON CONFLICT (record_code) DO NOTHING;
|
||||
|
||||
-- 17. 库存记录
|
||||
INSERT INTO inventory_records (record_type, project_id, purchase_request_id, product_id, quantity, unit_price, total_amount, record_date, operator, remark, created_at) VALUES
|
||||
('in', 1, 1, 1, 118, 1200, 141600, '2026-03-16', '项目经理', '电杆验收入库(2根退回)', NOW());
|
||||
|
||||
@@ -0,0 +1,639 @@
|
||||
SET client_encoding = 'UTF8';
|
||||
|
||||
-- ============================================================
|
||||
-- 云海财务系统 - PostgreSQL 完整表结构
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(255) UNIQUE,
|
||||
name VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
phone VARCHAR(255),
|
||||
role VARCHAR(50),
|
||||
avatar TEXT,
|
||||
passport TEXT,
|
||||
driver_license TEXT,
|
||||
password_hash VARCHAR(255),
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS customers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
address VARCHAR(255),
|
||||
remark TEXT,
|
||||
contact_person VARCHAR(255),
|
||||
phone VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255),
|
||||
project_code VARCHAR(255),
|
||||
customer_id INTEGER REFERENCES customers(id),
|
||||
project_manager_id INTEGER REFERENCES users(id),
|
||||
contract_amount NUMERIC,
|
||||
start_date DATE,
|
||||
end_date DATE,
|
||||
description TEXT,
|
||||
status VARCHAR(50) DEFAULT 'planning',
|
||||
location VARCHAR(255),
|
||||
type_template_id INTEGER,
|
||||
current_phase VARCHAR(50),
|
||||
phase_progress NUMERIC(5,2) DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS contacts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
entity_id INTEGER NOT NULL,
|
||||
entity_type VARCHAR(50) NOT NULL,
|
||||
name VARCHAR(255),
|
||||
position VARCHAR(255),
|
||||
phone VARCHAR(255),
|
||||
is_primary INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS suppliers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
address TEXT,
|
||||
contact_person VARCHAR(255),
|
||||
phone VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
product_category VARCHAR(255),
|
||||
supplier_source VARCHAR(100),
|
||||
supply_category TEXT,
|
||||
country TEXT,
|
||||
remark TEXT,
|
||||
status TEXT DEFAULT 'active',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS supplier_payment_infos (
|
||||
id SERIAL PRIMARY KEY,
|
||||
supplier_id INTEGER REFERENCES suppliers(id) ON DELETE CASCADE,
|
||||
account_name TEXT,
|
||||
bank_account TEXT,
|
||||
bank_name TEXT,
|
||||
qr_code TEXT,
|
||||
is_primary INTEGER DEFAULT 0,
|
||||
is_default BOOLEAN DEFAULT false,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS subcontractors (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
address TEXT,
|
||||
contact_person VARCHAR(255),
|
||||
phone VARCHAR(255),
|
||||
email VARCHAR(255),
|
||||
specialty TEXT,
|
||||
category TEXT,
|
||||
country TEXT,
|
||||
remark TEXT,
|
||||
score INTEGER DEFAULT 100,
|
||||
initial_score INTEGER DEFAULT 100,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS subcontractor_payment_infos (
|
||||
id SERIAL PRIMARY KEY,
|
||||
subcontractor_id INTEGER REFERENCES subcontractors(id) ON DELETE CASCADE,
|
||||
account_name TEXT,
|
||||
bank_name TEXT,
|
||||
bank_account TEXT,
|
||||
qr_code TEXT,
|
||||
is_primary INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS customer_payment_infos (
|
||||
id SERIAL PRIMARY KEY,
|
||||
customer_id INTEGER REFERENCES customers(id) ON DELETE CASCADE,
|
||||
account_name TEXT,
|
||||
bank_name TEXT,
|
||||
bank_account TEXT,
|
||||
qr_code TEXT,
|
||||
is_primary INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS product_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
parent_id INTEGER REFERENCES product_categories(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS products (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
model TEXT,
|
||||
category_id INTEGER REFERENCES product_categories(id),
|
||||
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',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS exchange_rates (
|
||||
id SERIAL PRIMARY KEY,
|
||||
currency_code TEXT NOT NULL,
|
||||
to_currency_code TEXT NOT NULL,
|
||||
rate REAL NOT NULL,
|
||||
effective_date DATE NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS advances (
|
||||
id SERIAL PRIMARY KEY,
|
||||
applicant_id INTEGER REFERENCES users(id),
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
amount REAL NOT NULL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
amount_cny REAL DEFAULT 0,
|
||||
reason TEXT,
|
||||
advance_date DATE,
|
||||
advance_code TEXT UNIQUE,
|
||||
status TEXT DEFAULT 'pending',
|
||||
applicant TEXT,
|
||||
attachments TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reimbursements (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INTEGER REFERENCES users(id),
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
amount REAL NOT NULL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
amount_cny REAL DEFAULT 0,
|
||||
reason TEXT,
|
||||
reimbursement_date DATE,
|
||||
reimbursement_code TEXT UNIQUE,
|
||||
status TEXT DEFAULT 'pending',
|
||||
applicant TEXT,
|
||||
expense_type TEXT,
|
||||
detail_items TEXT,
|
||||
attachments TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_requests (
|
||||
id SERIAL PRIMARY KEY,
|
||||
request_code TEXT UNIQUE,
|
||||
applicant TEXT,
|
||||
payment_date DATE,
|
||||
payee TEXT,
|
||||
bank_account TEXT,
|
||||
bank_name TEXT,
|
||||
amount REAL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
reason TEXT,
|
||||
status TEXT DEFAULT 'pending',
|
||||
detail_items TEXT,
|
||||
attachments TEXT,
|
||||
payee_type TEXT,
|
||||
payee_id INTEGER,
|
||||
expense_type TEXT DEFAULT 'company',
|
||||
expense_category TEXT,
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
purchase_request_id INTEGER,
|
||||
purchase_order_id INTEGER,
|
||||
payment_type TEXT DEFAULT 'company',
|
||||
logistics_company_id INTEGER,
|
||||
logistics_document_url TEXT,
|
||||
driver_phone TEXT,
|
||||
cargo_weight REAL,
|
||||
transport_distance REAL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS verifications (
|
||||
id SERIAL PRIMARY KEY,
|
||||
advance_id INTEGER REFERENCES advances(id),
|
||||
amount REAL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
reason TEXT,
|
||||
verification_date DATE,
|
||||
verification_code TEXT UNIQUE,
|
||||
status TEXT DEFAULT 'pending',
|
||||
applicant TEXT,
|
||||
advance_code TEXT,
|
||||
advance_amount REAL,
|
||||
detail_items TEXT,
|
||||
attachments TEXT,
|
||||
expense_type TEXT,
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
settlement TEXT,
|
||||
settlement_amount REAL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS executions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
apply_id INTEGER,
|
||||
apply_type TEXT,
|
||||
action TEXT,
|
||||
execute_method TEXT,
|
||||
voucher_no TEXT,
|
||||
remark TEXT,
|
||||
reject_reason TEXT,
|
||||
voucher_files TEXT,
|
||||
operator TEXT,
|
||||
operator_role TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS purchase_requests (
|
||||
id SERIAL PRIMARY KEY,
|
||||
request_code TEXT UNIQUE NOT NULL,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id),
|
||||
applicant TEXT,
|
||||
request_date DATE,
|
||||
supplier_id INTEGER REFERENCES suppliers(id),
|
||||
supplier_name TEXT,
|
||||
expense_category TEXT,
|
||||
purchase_type TEXT DEFAULT 'inventory',
|
||||
total_amount REAL NOT NULL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
status TEXT DEFAULT 'pending',
|
||||
remark TEXT,
|
||||
remarks TEXT,
|
||||
brief_description TEXT,
|
||||
attachments TEXT,
|
||||
expected_date DATE,
|
||||
execute_date DATE,
|
||||
execute_method TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS purchase_request_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
purchase_request_id INTEGER NOT NULL REFERENCES purchase_requests(id) ON DELETE CASCADE,
|
||||
product_id INTEGER REFERENCES products(id),
|
||||
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
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS purchase_orders (
|
||||
id SERIAL PRIMARY KEY,
|
||||
code TEXT UNIQUE NOT NULL,
|
||||
purchase_request_id INTEGER REFERENCES purchase_requests(id),
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
supplier_id INTEGER REFERENCES suppliers(id),
|
||||
supplier_country TEXT DEFAULT 'Laos',
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
status TEXT DEFAULT 'draft',
|
||||
estimated_amount REAL DEFAULT 0,
|
||||
paid_amount REAL DEFAULT 0,
|
||||
contract_url TEXT,
|
||||
quotation_url TEXT,
|
||||
actual_delivery_date DATE,
|
||||
expected_delivery_date DATE,
|
||||
receiving_status VARCHAR(20) DEFAULT 'pending',
|
||||
remark TEXT,
|
||||
created_by TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS purchase_order_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
order_id INTEGER NOT NULL REFERENCES purchase_orders(id) ON DELETE CASCADE,
|
||||
product_id INTEGER REFERENCES products(id),
|
||||
product_name TEXT,
|
||||
specification TEXT,
|
||||
unit TEXT,
|
||||
quantity REAL DEFAULT 0,
|
||||
unit_price REAL DEFAULT 0,
|
||||
total_price REAL DEFAULT 0,
|
||||
received_quantity REAL DEFAULT 0,
|
||||
verified_quantity REAL DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_plans (
|
||||
id SERIAL PRIMARY KEY,
|
||||
purchase_order_id INTEGER REFERENCES purchase_orders(id),
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
plan_name TEXT,
|
||||
stage TEXT,
|
||||
planned_date DATE,
|
||||
planned_amount REAL,
|
||||
planned_percentage REAL,
|
||||
actual_amount REAL DEFAULT 0,
|
||||
actual_date DATE,
|
||||
payment_request_id INTEGER,
|
||||
reminder_days INTEGER DEFAULT 3,
|
||||
amount REAL DEFAULT 0,
|
||||
due_date DATE,
|
||||
status TEXT DEFAULT 'pending',
|
||||
remark TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_nodes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
name TEXT,
|
||||
amount REAL DEFAULT 0,
|
||||
due_date DATE,
|
||||
status TEXT DEFAULT 'pending',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment_records (
|
||||
id SERIAL PRIMARY KEY,
|
||||
node_id INTEGER REFERENCES payment_nodes(id),
|
||||
amount REAL DEFAULT 0,
|
||||
payment_date DATE,
|
||||
method TEXT,
|
||||
status TEXT DEFAULT 'completed',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS inventory_records (
|
||||
id SERIAL PRIMARY KEY,
|
||||
record_type TEXT NOT NULL,
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
purchase_request_id INTEGER REFERENCES purchase_requests(id),
|
||||
product_id INTEGER NOT NULL REFERENCES products(id),
|
||||
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
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS logistics_companies (
|
||||
id SERIAL PRIMARY KEY,
|
||||
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 TABLE IF NOT EXISTS logistics_company_contacts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
logistics_company_id INTEGER REFERENCES logistics_companies(id) ON DELETE CASCADE,
|
||||
name TEXT,
|
||||
phone TEXT,
|
||||
position TEXT,
|
||||
is_primary INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS logistics_company_bank_accounts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
logistics_company_id INTEGER REFERENCES logistics_companies(id) ON DELETE CASCADE,
|
||||
account_name TEXT,
|
||||
bank_name TEXT,
|
||||
account_number TEXT,
|
||||
is_default INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS construction_logs (
|
||||
id SERIAL PRIMARY KEY,
|
||||
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
|
||||
log_date DATE NOT NULL,
|
||||
weather TEXT,
|
||||
recorded_by TEXT,
|
||||
work_content TEXT,
|
||||
next_plan TEXT,
|
||||
issues TEXT,
|
||||
photos TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_type_templates (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
phases JSONB NOT NULL DEFAULT '[]',
|
||||
is_system BOOLEAN DEFAULT false,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_phases (
|
||||
id SERIAL PRIMARY KEY,
|
||||
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
|
||||
template_key VARCHAR(50),
|
||||
phase_name VARCHAR(100) NOT NULL,
|
||||
phase_order INTEGER NOT NULL,
|
||||
phase_type VARCHAR(20) DEFAULT 'serial',
|
||||
depends_on INTEGER[],
|
||||
status VARCHAR(20) DEFAULT 'pending',
|
||||
started_at TIMESTAMP,
|
||||
completed_at TIMESTAMP,
|
||||
completed_by INTEGER REFERENCES users(id),
|
||||
remark TEXT,
|
||||
photos TEXT[],
|
||||
sub_items JSONB DEFAULT '[]',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_projects (
|
||||
id SERIAL PRIMARY KEY,
|
||||
budget_code TEXT,
|
||||
name TEXT NOT NULL,
|
||||
customer_id INTEGER REFERENCES customers(id),
|
||||
business_manager_id INTEGER REFERENCES users(id),
|
||||
location TEXT,
|
||||
survey_date DATE,
|
||||
intermediary_name TEXT,
|
||||
intermediary_fee_type TEXT DEFAULT 'fixed',
|
||||
intermediary_fee REAL DEFAULT 0,
|
||||
customer_requirements TEXT,
|
||||
survey_notes TEXT,
|
||||
status TEXT DEFAULT 'draft',
|
||||
total_amount REAL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
remark TEXT,
|
||||
created_by INTEGER REFERENCES users(id),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_quotations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
budget_project_id INTEGER REFERENCES budget_projects(id) ON DELETE CASCADE,
|
||||
version INTEGER DEFAULT 1,
|
||||
quotation_date DATE,
|
||||
amount REAL DEFAULT 0,
|
||||
currency TEXT DEFAULT 'CNY',
|
||||
file_url TEXT,
|
||||
notes TEXT,
|
||||
status TEXT DEFAULT 'draft',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS budget_attachments (
|
||||
id SERIAL PRIMARY KEY,
|
||||
budget_project_id INTEGER REFERENCES budget_projects(id) ON DELETE CASCADE,
|
||||
file_url TEXT,
|
||||
file_type TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_contracts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
|
||||
contract_no TEXT,
|
||||
contract_amount REAL,
|
||||
sign_date DATE,
|
||||
file_url TEXT,
|
||||
remark TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_milestones (
|
||||
id SERIAL PRIMARY KEY,
|
||||
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
|
||||
milestone_name TEXT,
|
||||
amount REAL DEFAULT 0,
|
||||
due_date DATE,
|
||||
status TEXT DEFAULT 'pending',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_receipts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
milestone_id INTEGER REFERENCES project_milestones(id),
|
||||
amount REAL DEFAULT 0,
|
||||
receipt_date DATE,
|
||||
financial_record_id INTEGER,
|
||||
remark TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS subcontractor_events (
|
||||
id SERIAL PRIMARY KEY,
|
||||
subcontractor_id INTEGER REFERENCES subcontractors(id),
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
event_type VARCHAR(10),
|
||||
score_change INTEGER,
|
||||
event_date DATE,
|
||||
title VARCHAR(200),
|
||||
description TEXT,
|
||||
created_by INTEGER REFERENCES users(id),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 财务分类与账本(与 migrations 006/007 一致)
|
||||
CREATE TABLE IF NOT EXISTS expense_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
category_level1 TEXT NOT NULL,
|
||||
category_level2 TEXT NOT NULL,
|
||||
label TEXT NOT NULL,
|
||||
description TEXT,
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(category_level1, category_level2)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS financial_records (
|
||||
id SERIAL PRIMARY KEY,
|
||||
record_code TEXT UNIQUE NOT NULL,
|
||||
txn_type TEXT NOT NULL CHECK (txn_type IN ('income', 'expense')),
|
||||
category_level1 TEXT NOT NULL,
|
||||
category_level2 TEXT NOT NULL,
|
||||
project_id INTEGER REFERENCES projects(id),
|
||||
user_id INTEGER REFERENCES users(id),
|
||||
user_name TEXT,
|
||||
amount_original REAL NOT NULL DEFAULT 0,
|
||||
currency TEXT NOT NULL DEFAULT 'CNY',
|
||||
exchange_rate REAL NOT NULL DEFAULT 1,
|
||||
amount_cny REAL NOT NULL DEFAULT 0,
|
||||
record_date DATE NOT NULL,
|
||||
counterparty_name TEXT,
|
||||
counterparty_type TEXT,
|
||||
counterparty_id INTEGER,
|
||||
source TEXT NOT NULL DEFAULT 'manual',
|
||||
source_id INTEGER,
|
||||
source_code TEXT,
|
||||
description TEXT,
|
||||
voucher_no TEXT,
|
||||
attachments TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'confirmed' CHECK (status IN ('confirmed', 'pending', 'voided')),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_products_category ON products(category_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_requests_project ON purchase_requests(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_financial_records_project ON financial_records(project_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_expense_categories_level1 ON expense_categories(category_level1);
|
||||
|
||||
-- 兼容已存在的旧 projects 表,补充缺失字段
|
||||
ALTER TABLE projects ADD COLUMN IF NOT EXISTS start_date DATE;
|
||||
ALTER TABLE projects ADD COLUMN IF NOT EXISTS end_date DATE;
|
||||
ALTER TABLE projects ADD COLUMN IF NOT EXISTS description TEXT;
|
||||
ALTER TABLE projects ADD COLUMN IF NOT EXISTS type_template_id INTEGER;
|
||||
ALTER TABLE projects ADD COLUMN IF NOT EXISTS current_phase VARCHAR(50);
|
||||
ALTER TABLE projects ADD COLUMN IF NOT EXISTS phase_progress NUMERIC(5,2) DEFAULT 0;
|
||||
|
||||
-- 兼容已存在库:补充路由依赖字段
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS is_active BOOLEAN DEFAULT true;
|
||||
UPDATE users SET is_active = true WHERE is_active IS NULL;
|
||||
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS budget_code TEXT;
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS business_manager_id INTEGER REFERENCES users(id);
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS location TEXT;
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS survey_date DATE;
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS intermediary_name TEXT;
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS intermediary_fee_type TEXT DEFAULT 'fixed';
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS intermediary_fee REAL DEFAULT 0;
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS customer_requirements TEXT;
|
||||
ALTER TABLE budget_projects ADD COLUMN IF NOT EXISTS survey_notes TEXT;
|
||||
|
||||
ALTER TABLE reimbursements ADD COLUMN IF NOT EXISTS approval_remark TEXT;
|
||||
Reference in New Issue
Block a user