-- V2A-DB-01: 字段级数据字典落库（6.10）
-- MySQL 5.7：通过 information_schema + PREPARE 方式做幂等加列

-- =========================
-- project 扩展字段
-- =========================
SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'host_enterprise_id');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN host_enterprise_id BIGINT UNSIGNED NULL AFTER enterprise_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'partner_enterprise_id');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN partner_enterprise_id BIGINT UNSIGNED NULL AFTER host_enterprise_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'host_owner_user_id');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN host_owner_user_id BIGINT UNSIGNED NULL AFTER partner_enterprise_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'host_executor_user_id');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN host_executor_user_id BIGINT UNSIGNED NULL AFTER host_owner_user_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'partner_owner_user_id');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN partner_owner_user_id BIGINT UNSIGNED NULL AFTER host_executor_user_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'partner_executor_user_id');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN partner_executor_user_id BIGINT UNSIGNED NULL AFTER partner_owner_user_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'allow_meeting_over_budget');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN allow_meeting_over_budget TINYINT(1) NOT NULL DEFAULT 0 AFTER partner_executor_user_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'over_budget_threshold_ratio');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN over_budget_threshold_ratio DECIMAL(8,6) NOT NULL DEFAULT 0.100000 AFTER allow_meeting_over_budget', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'over_budget_approval_chain_json');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN over_budget_approval_chain_json TEXT NULL AFTER over_budget_threshold_ratio', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'meeting_completed_count');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN meeting_completed_count INT NOT NULL DEFAULT 0 AFTER meeting_total', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'budget_execution_ratio');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN budget_execution_ratio DECIMAL(8,6) NOT NULL DEFAULT 0.000000 AFTER meeting_completed_count', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND COLUMN_NAME = 'risk_flags_json');
SET @sql := IF(@c = 0, 'ALTER TABLE project ADD COLUMN risk_flags_json TEXT NULL AFTER budget_execution_ratio', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @idx := (SELECT COUNT(1) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'project' AND INDEX_NAME = 'idx_tenant_host_partner');
SET @sql := IF(@idx = 0, 'ALTER TABLE project ADD KEY idx_tenant_host_partner (tenant_id, host_enterprise_id, partner_enterprise_id)', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

-- =========================
-- meeting 扩展字段
-- =========================
SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'sub_project_name');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN sub_project_name VARCHAR(128) NULL AFTER topic', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'meeting_category');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN meeting_category VARCHAR(64) NULL AFTER sub_project_name', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'meeting_form');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN meeting_form VARCHAR(64) NULL AFTER meeting_category', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'location');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN location VARCHAR(255) NULL AFTER meeting_form', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'start_time');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN start_time DATETIME NULL AFTER location', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'end_time');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN end_time DATETIME NULL AFTER start_time', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'labor_ratio');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN labor_ratio DECIMAL(8,6) NOT NULL DEFAULT 0.000000 AFTER budget_cent', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'catering_ratio');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN catering_ratio DECIMAL(8,6) NOT NULL DEFAULT 0.000000 AFTER labor_ratio', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'current_audit_node');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN current_audit_node VARCHAR(64) NULL AFTER audit_status', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'last_submit_at');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN last_submit_at DATETIME NULL AFTER current_audit_node', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'last_reject_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN last_reject_reason VARCHAR(500) NULL AFTER last_submit_at', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'overdue_days');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN overdue_days INT NOT NULL DEFAULT 0 AFTER last_reject_reason', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'risk_flags_json');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN risk_flags_json TEXT NULL AFTER overdue_days', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'is_frozen');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN is_frozen TINYINT(1) NOT NULL DEFAULT 0 AFTER risk_flags_json', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND COLUMN_NAME = 'freeze_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting ADD COLUMN freeze_reason VARCHAR(500) NULL AFTER is_frozen', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @idx := (SELECT COUNT(1) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting' AND INDEX_NAME = 'idx_tenant_time');
SET @sql := IF(@idx = 0, 'ALTER TABLE meeting ADD KEY idx_tenant_time (tenant_id, start_time, end_time)', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

-- =========================
-- meeting_material 扩展字段
-- =========================
SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting_material' AND COLUMN_NAME = 'is_latest_version');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting_material ADD COLUMN is_latest_version TINYINT(1) NOT NULL DEFAULT 1 AFTER version_no', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting_material' AND COLUMN_NAME = 'audit_node_status');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting_material ADD COLUMN audit_node_status VARCHAR(32) NULL AFTER status', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting_material' AND COLUMN_NAME = 'audit_aggregate_status');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting_material ADD COLUMN audit_aggregate_status VARCHAR(32) NULL AFTER audit_node_status', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting_material' AND COLUMN_NAME = 'submit_remark');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting_material ADD COLUMN submit_remark VARCHAR(500) NULL AFTER audit_aggregate_status', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting_material' AND COLUMN_NAME = 'reject_count');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting_material ADD COLUMN reject_count INT NOT NULL DEFAULT 0 AFTER submit_remark', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting_material' AND COLUMN_NAME = 'last_reject_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting_material ADD COLUMN last_reject_reason VARCHAR(500) NULL AFTER reject_count', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'meeting_material' AND COLUMN_NAME = 'resubmit_at');
SET @sql := IF(@c = 0, 'ALTER TABLE meeting_material ADD COLUMN resubmit_at DATETIME NULL AFTER last_reject_reason', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

-- =========================
-- 发票结构化新表
-- =========================
CREATE TABLE IF NOT EXISTS meeting_material_invoice_item (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    tenant_id BIGINT UNSIGNED NOT NULL,
    meeting_id BIGINT UNSIGNED NOT NULL,
    material_id BIGINT UNSIGNED DEFAULT NULL,
    expense_type VARCHAR(64) NOT NULL,
    invoice_no VARCHAR(128) DEFAULT NULL,
    invoice_amount_cent BIGINT NOT NULL DEFAULT 0,
    tax_amount_cent BIGINT NOT NULL DEFAULT 0,
    detail_amount_cent BIGINT NOT NULL DEFAULT 0,
    vendor_name VARCHAR(255) DEFAULT NULL,
    occur_date DATE DEFAULT NULL,
    remark VARCHAR(500) DEFAULT NULL,
    is_deleted TINYINT(1) NOT NULL DEFAULT 0,
    created_by BIGINT UNSIGNED NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_by BIGINT UNSIGNED NOT NULL DEFAULT 0,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    KEY idx_tenant_meeting_expense_date (tenant_id, meeting_id, expense_type, occur_date),
    KEY idx_tenant_invoice_no (tenant_id, invoice_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS meeting_material_invoice_file (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    tenant_id BIGINT UNSIGNED NOT NULL,
    meeting_id BIGINT UNSIGNED NOT NULL,
    invoice_item_id BIGINT UNSIGNED DEFAULT NULL,
    file_type VARCHAR(32) NOT NULL COMMENT 'INVOICE/DETAIL/PHOTO/TICKET/OTHER',
    file_name VARCHAR(255) NOT NULL,
    oss_key VARCHAR(512) NOT NULL,
    content_type VARCHAR(128) DEFAULT NULL,
    size BIGINT UNSIGNED NOT NULL DEFAULT 0,
    is_deleted TINYINT(1) NOT NULL DEFAULT 0,
    created_by BIGINT UNSIGNED NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    KEY idx_tenant_meeting_file_type (tenant_id, meeting_id, file_type),
    KEY idx_tenant_invoice_item (tenant_id, invoice_item_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS meeting_invoice_summary (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    tenant_id BIGINT UNSIGNED NOT NULL,
    meeting_id BIGINT UNSIGNED NOT NULL,
    category_amount_cent_json TEXT NOT NULL,
    meeting_total_amount_cent BIGINT NOT NULL DEFAULT 0,
    is_over_budget TINYINT(1) NOT NULL DEFAULT 0,
    is_deleted TINYINT(1) NOT NULL DEFAULT 0,
    created_by BIGINT UNSIGNED NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_by BIGINT UNSIGNED NOT NULL DEFAULT 0,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uk_tenant_meeting (tenant_id, meeting_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- =========================
-- audit_task 扩展字段
-- =========================
SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'audit_task' AND COLUMN_NAME = 'overtime_hours');
SET @sql := IF(@c = 0, 'ALTER TABLE audit_task ADD COLUMN overtime_hours INT NOT NULL DEFAULT 0 AFTER timeout_level', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'audit_task' AND COLUMN_NAME = 'is_overtime');
SET @sql := IF(@c = 0, 'ALTER TABLE audit_task ADD COLUMN is_overtime TINYINT(1) NOT NULL DEFAULT 0 AFTER overtime_hours', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'audit_task' AND COLUMN_NAME = 'transfer_from_user_id');
SET @sql := IF(@c = 0, 'ALTER TABLE audit_task ADD COLUMN transfer_from_user_id BIGINT UNSIGNED NULL AFTER assignee_user_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'audit_task' AND COLUMN_NAME = 'transfer_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE audit_task ADD COLUMN transfer_reason VARCHAR(500) NULL AFTER transfer_from_user_id', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'audit_task' AND COLUMN_NAME = 'return_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE audit_task ADD COLUMN return_reason VARCHAR(500) NULL AFTER transfer_reason', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'audit_task' AND COLUMN_NAME = 'reject_count');
SET @sql := IF(@c = 0, 'ALTER TABLE audit_task ADD COLUMN reject_count INT NOT NULL DEFAULT 0 AFTER return_reason', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'audit_task' AND COLUMN_NAME = 'last_reject_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE audit_task ADD COLUMN last_reject_reason VARCHAR(500) NULL AFTER reject_count', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'audit_task' AND COLUMN_NAME = 'last_action_at');
SET @sql := IF(@c = 0, 'ALTER TABLE audit_task ADD COLUMN last_action_at DATETIME NULL AFTER last_reject_reason', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

-- =========================
-- expert / expert_bank_card 扩展字段
-- =========================
SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert' AND COLUMN_NAME = 'gender');
SET @sql := IF(@c = 0, 'ALTER TABLE expert ADD COLUMN gender VARCHAR(16) NULL AFTER expert_name', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert' AND COLUMN_NAME = 'birthday');
SET @sql := IF(@c = 0, 'ALTER TABLE expert ADD COLUMN birthday DATE NULL AFTER gender', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert' AND COLUMN_NAME = 'id_card_valid_until');
SET @sql := IF(@c = 0, 'ALTER TABLE expert ADD COLUMN id_card_valid_until DATE NULL AFTER id_no', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert' AND COLUMN_NAME = 'status_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE expert ADD COLUMN status_reason VARCHAR(500) NULL AFTER status', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert' AND COLUMN_NAME = 'status_changed_by');
SET @sql := IF(@c = 0, 'ALTER TABLE expert ADD COLUMN status_changed_by BIGINT UNSIGNED NULL AFTER status_reason', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert' AND COLUMN_NAME = 'status_changed_at');
SET @sql := IF(@c = 0, 'ALTER TABLE expert ADD COLUMN status_changed_at DATETIME NULL AFTER status_changed_by', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert' AND COLUMN_NAME = 'export_restricted');
SET @sql := IF(@c = 0, 'ALTER TABLE expert ADD COLUMN export_restricted TINYINT(1) NOT NULL DEFAULT 1 AFTER status_changed_at', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert_bank_card' AND COLUMN_NAME = 'bank_province');
SET @sql := IF(@c = 0, 'ALTER TABLE expert_bank_card ADD COLUMN bank_province VARCHAR(64) NULL AFTER bank_name', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert_bank_card' AND COLUMN_NAME = 'bank_city');
SET @sql := IF(@c = 0, 'ALTER TABLE expert_bank_card ADD COLUMN bank_city VARCHAR(64) NULL AFTER bank_province', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert_bank_card' AND COLUMN_NAME = 'bank_branch_name');
SET @sql := IF(@c = 0, 'ALTER TABLE expert_bank_card ADD COLUMN bank_branch_name VARCHAR(255) NULL AFTER bank_city', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert_bank_card' AND COLUMN_NAME = 'card_status');
SET @sql := IF(@c = 0, 'ALTER TABLE expert_bank_card ADD COLUMN card_status VARCHAR(32) NOT NULL DEFAULT ''ENABLED'' AFTER is_default', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert_bank_card' AND COLUMN_NAME = 'inconsistent_name_approved');
SET @sql := IF(@c = 0, 'ALTER TABLE expert_bank_card ADD COLUMN inconsistent_name_approved TINYINT(1) NOT NULL DEFAULT 0 AFTER card_status', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'expert_bank_card' AND COLUMN_NAME = 'change_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE expert_bank_card ADD COLUMN change_reason VARCHAR(500) NULL AFTER inconsistent_name_approved', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

-- =========================
-- template / template_version 扩展字段
-- =========================
SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'template' AND COLUMN_NAME = 'scope_id');
SET @sql := IF(@c = 0, 'ALTER TABLE template ADD COLUMN scope_id BIGINT UNSIGNED NULL AFTER scope_type', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'template' AND COLUMN_NAME = 'effective_from');
SET @sql := IF(@c = 0, 'ALTER TABLE template ADD COLUMN effective_from DATETIME NULL AFTER current_version_no', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'template' AND COLUMN_NAME = 'effective_to');
SET @sql := IF(@c = 0, 'ALTER TABLE template ADD COLUMN effective_to DATETIME NULL AFTER effective_from', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'template' AND COLUMN_NAME = 'watermark_enabled');
SET @sql := IF(@c = 0, 'ALTER TABLE template ADD COLUMN watermark_enabled TINYINT(1) NOT NULL DEFAULT 0 AFTER effective_to', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'template' AND COLUMN_NAME = 'download_rate_limit_per_hour');
SET @sql := IF(@c = 0, 'ALTER TABLE template ADD COLUMN download_rate_limit_per_hour INT NOT NULL DEFAULT 100 AFTER watermark_enabled', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'template_version' AND COLUMN_NAME = 'is_effective');
SET @sql := IF(@c = 0, 'ALTER TABLE template_version ADD COLUMN is_effective TINYINT(1) NOT NULL DEFAULT 0 AFTER version_status', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

SET @c := (SELECT COUNT(1) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'template_version' AND COLUMN_NAME = 'rollback_reason');
SET @sql := IF(@c = 0, 'ALTER TABLE template_version ADD COLUMN rollback_reason VARCHAR(500) NULL AFTER change_log', 'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

-- =========================
-- finance_meeting_bill 新表
-- =========================
CREATE TABLE IF NOT EXISTS finance_meeting_bill (
    id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    tenant_id BIGINT UNSIGNED NOT NULL,
    project_id BIGINT UNSIGNED NOT NULL,
    meeting_id BIGINT UNSIGNED NOT NULL,
    venue_amount_cent BIGINT NOT NULL DEFAULT 0,
    build_amount_cent BIGINT NOT NULL DEFAULT 0,
    hotel_amount_cent BIGINT NOT NULL DEFAULT 0,
    catering_amount_cent BIGINT NOT NULL DEFAULT 0,
    local_traffic_amount_cent BIGINT NOT NULL DEFAULT 0,
    long_distance_traffic_amount_cent BIGINT NOT NULL DEFAULT 0,
    material_amount_cent BIGINT NOT NULL DEFAULT 0,
    design_amount_cent BIGINT NOT NULL DEFAULT 0,
    labor_payable_amount_cent BIGINT NOT NULL DEFAULT 0,
    labor_actual_amount_cent BIGINT NOT NULL DEFAULT 0,
    finance_review_fee_cent BIGINT NOT NULL DEFAULT 0,
    management_fee_cent BIGINT NOT NULL DEFAULT 0,
    tax_fee_cent BIGINT NOT NULL DEFAULT 0,
    custom_fee_json TEXT NULL,
    paid_amount_cent BIGINT NOT NULL DEFAULT 0,
    unpaid_amount_cent BIGINT NOT NULL DEFAULT 0,
    reconciliation_result VARCHAR(32) DEFAULT NULL,
    reconciliation_diff_amount_cent BIGINT NOT NULL DEFAULT 0,
    reconciliation_diff_reason VARCHAR(500) DEFAULT NULL,
    settlement_no VARCHAR(64) DEFAULT NULL,
    status VARCHAR(32) NOT NULL DEFAULT 'DRAFT',
    is_deleted TINYINT(1) NOT NULL DEFAULT 0,
    created_by BIGINT UNSIGNED NOT NULL DEFAULT 0,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_by BIGINT UNSIGNED NOT NULL DEFAULT 0,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uk_tenant_meeting (tenant_id, meeting_id),
    UNIQUE KEY uk_tenant_settlement_no (tenant_id, settlement_no),
    KEY idx_tenant_project_status (tenant_id, project_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
