Files
2026-06-24 10:47:45 +08:00

640 lines
19 KiB
SQL

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;