-- ============================================================
-- 测试环境 crm 库 schema 补齐（opportunity / opportunity_customer）
-- 背景 20260901：导表后两表为残缺混合结构（缺 party_a_clear 等列，
--   实体映射全列 SELECT/INSERT → SQLSyntaxErrorException → 50001）。
-- 用法：Navicat 整段执行 / mysql -uroot -p crm < opp-schema-migration.sql
-- 幂等：列已存在自动跳过（information_schema 判存 + 动态 SQL，MySQL 8 无 ADD COLUMN IF NOT EXISTS）。
-- 对齐实体：Opportunity.java（L40-230）+ OpportunityCustomer.java + BaseEntity.java。
-- 更省事的替代：重启 crm-app 容器即可，jpa.hibernate.ddl-auto=update 会自动补齐全部缺列。
-- ============================================================

DELIMITER $$

DROP PROCEDURE IF EXISTS crm_add_column $$
CREATE PROCEDURE crm_add_column(
    IN p_table VARCHAR(64), IN p_column VARCHAR(64), IN p_ddl TEXT)
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.COLUMNS
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = p_table AND COLUMN_NAME = p_column
    ) THEN
        SET @s = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_ddl);
        PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
        SELECT CONCAT('ADD ', p_table, '.', p_column) AS applied;
    END IF;
END $$

DELIMITER ;

-- ---------- opportunity 主表 ----------
CALL crm_add_column('opportunity','opp_name',            "varchar(200) NOT NULL COMMENT '商机名称'");
CALL crm_add_column('opportunity','opp_source',          "varchar(64) NOT NULL COMMENT '商机来源字典code'");
CALL crm_add_column('opportunity','opp_type',            "varchar(64) NOT NULL COMMENT '商机类型字典code'");
CALL crm_add_column('opportunity','industry_code',       "varchar(64) NOT NULL COMMENT '行业字典code'");
CALL crm_add_column('opportunity','bid_form',            "varchar(64) NOT NULL COMMENT '招标形式字典code'");
CALL crm_add_column('opportunity','locality_type',       "varchar(64) NOT NULL COMMENT '项目属地字典code'");
CALL crm_add_column('opportunity','party_a_clear',       "tinyint NOT NULL DEFAULT 0 COMMENT '甲方是否明确'");
CALL crm_add_column('opportunity','party_a',             "varchar(200) NULL COMMENT '甲方名称'");
CALL crm_add_column('opportunity','province_code',       "varchar(12) NOT NULL COMMENT '省份国标code'");
CALL crm_add_column('opportunity','city_code',           "varchar(12) NOT NULL COMMENT '市/区国标code'");
CALL crm_add_column('opportunity','remark',              "text NULL COMMENT '备注'");
CALL crm_add_column('opportunity','project_amount',      "decimal(14,2) NULL COMMENT '项目金额'");
CALL crm_add_column('opportunity','address',             "varchar(255) NULL COMMENT '项目详细地址'");
CALL crm_add_column('opportunity','owner_user_id',       "bigint NULL COMMENT '领取人ID'");
CALL crm_add_column('opportunity','owner_name_snapshot', "varchar(64) NULL COMMENT '领取人姓名快照'");
CALL crm_add_column('opportunity','owner_dept_id',       "bigint NULL COMMENT '领取人部门快照'");
CALL crm_add_column('opportunity','origin_dept_id',      "bigint NULL COMMENT '原始血缘部门'");
CALL crm_add_column('opportunity','pool_reason',         "varchar(32) NULL COMMENT '进入公海原因'");
CALL crm_add_column('opportunity','creator_user_id',     "bigint NOT NULL COMMENT '创建人ID'");
CALL crm_add_column('opportunity','opp_status',          "tinyint NOT NULL COMMENT '商机状态'");
CALL crm_add_column('opportunity','current_stage_id',    "bigint NOT NULL COMMENT '当前阶段节点ID'");
CALL crm_add_column('opportunity','stage_template_id',   "bigint NOT NULL COMMENT '阶段模板版本行ID'");
CALL crm_add_column('opportunity','stage_template_version', "varchar(20) NOT NULL COMMENT '阶段模板版本号冗余'");
CALL crm_add_column('opportunity','source_lead_id',      "bigint NULL COMMENT '来源线索ID'");
CALL crm_add_column('opportunity','source_lead_name',    "varchar(200) NULL COMMENT '线索名快照'");
CALL crm_add_column('opportunity','source_phone',        "varchar(32) NULL COMMENT '联系电话快照'");
CALL crm_add_column('opportunity','source_product_code', "varchar(64) NULL COMMENT '需求产品码快照'");
CALL crm_add_column('opportunity','claim_time',          "datetime NULL COMMENT '领取时刻'");
CALL crm_add_column('opportunity','last_valid_follow_time', "datetime NULL COMMENT '最近有效跟进时间'");
CALL crm_add_column('opportunity','primary_customer_id', "bigint NULL COMMENT '主要意向客户ID'");
CALL crm_add_column('opportunity','primary_customer_name_snapshot', "varchar(200) NULL COMMENT '主客户名快照'");
CALL crm_add_column('opportunity','key_contact_id',      "bigint NULL COMMENT '商机关键联系人ID'");
CALL crm_add_column('opportunity','key_contact_name_snapshot', "varchar(200) NULL COMMENT '商机关键联系人姓名快照'");
CALL crm_add_column('opportunity','key_contact_company_snapshot', "varchar(200) NULL COMMENT '关键人所在公司快照'");
CALL crm_add_column('opportunity','scheme_budget',       "decimal(18,2) NULL COMMENT '方案卡预算快照'");
CALL crm_add_column('opportunity','scheme_card_status',  "int NULL COMMENT '方案卡状态快照'");
CALL crm_add_column('opportunity','pause_time',          "datetime NULL COMMENT '暂缓开始时刻'");
CALL crm_add_column('opportunity','pause_reason',        "varchar(32) NULL COMMENT '暂缓原因'");
CALL crm_add_column('opportunity','pause_expected_restart_date', "date NULL COMMENT '预计重启日期'");
CALL crm_add_column('opportunity','pause_remark',        "varchar(500) NULL COMMENT '暂缓补充说明'");
CALL crm_add_column('opportunity','version',             "int NOT NULL DEFAULT 0 COMMENT '乐观锁版本号'");
-- BaseEntity 公共列（通常都在，幂等兜底）
CALL crm_add_column('opportunity','creator_id',          "varchar(50) NULL COMMENT '创建用户id'");
CALL crm_add_column('opportunity','updater_id',          "varchar(50) NULL COMMENT '更新用户id'");
CALL crm_add_column('opportunity','create_time',         "datetime NULL COMMENT '创建时间'");
CALL crm_add_column('opportunity','update_time',         "datetime NULL COMMENT '更新时间'");
CALL crm_add_column('opportunity','delete_key',          "tinyint NOT NULL DEFAULT 0 COMMENT '逻辑删除位'");

-- ---------- opportunity_customer 关联客户表 ----------
CALL crm_add_column('opportunity_customer','opportunity_id',   "bigint NOT NULL COMMENT '所属商机ID'");
CALL crm_add_column('opportunity_customer','customer_id',      "bigint NOT NULL COMMENT '客户ID'");
CALL crm_add_column('opportunity_customer','customer_name_snapshot', "varchar(200) NOT NULL COMMENT '客户名快照'");
CALL crm_add_column('opportunity_customer','customer_role',    "varchar(32) NULL COMMENT '客户角色字典code'");
CALL crm_add_column('opportunity_customer','is_primary_intended', "tinyint NOT NULL DEFAULT 0 COMMENT '是否主要意向客户'");
CALL crm_add_column('opportunity_customer','delete_key',       "bigint NOT NULL DEFAULT 0 COMMENT '软删除复用键'");
CALL crm_add_column('opportunity_customer','creator_id',       "varchar(50) NULL COMMENT '创建用户id'");
CALL crm_add_column('opportunity_customer','updater_id',       "varchar(50) NULL COMMENT '更新用户id'");
CALL crm_add_column('opportunity_customer','create_time',      "datetime NULL COMMENT '创建时间'");
CALL crm_add_column('opportunity_customer','update_time',      "datetime NULL COMMENT '更新时间'");

-- ---------- 索引/约束补齐（不阻塞运行，建议顺手执行） ----------
SET @ix := (SELECT COUNT(*) FROM information_schema.STATISTICS
            WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'opportunity' AND INDEX_NAME = 'idx_source_lead');
SET @sql := IF(@ix = 0,
    'ALTER TABLE `opportunity` ADD UNIQUE INDEX `idx_source_lead` (`source_lead_id`)',
    'SELECT 1');
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;

SET @ix := (SELECT COUNT(*) FROM information_schema.STATISTICS
            WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'opportunity' AND INDEX_NAME = 'idx_owner_status');
SET @sql := IF(@ix = 0,
    'ALTER TABLE `opportunity` ADD INDEX `idx_owner_status` (`owner_user_id`, `opp_status`)',
    'SELECT 1');
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;

SET @ix := (SELECT COUNT(*) FROM information_schema.STATISTICS
            WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'opportunity' AND INDEX_NAME = 'idx_owner_dept_status');
SET @sql := IF(@ix = 0,
    'ALTER TABLE `opportunity` ADD INDEX `idx_owner_dept_status` (`owner_dept_id`, `opp_status`)',
    'SELECT 1');
PREPARE st FROM @sql; EXECUTE st; DEALLOCATE PREPARE st;

DROP PROCEDURE crm_add_column;

-- 执行完核对（应全部返回 0 行 = 缺列已补齐）：
--   SELECT TABLE_NAME, COLUMN_NAME FROM information_schema.COLUMNS
--   WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME IN ('opportunity','opportunity_customer')
--     AND COLUMN_NAME IN ('party_a_clear','project_amount','address','key_contact_id',
--                         'key_contact_name_snapshot','key_contact_company_snapshot',
--                         'customer_role','is_primary_intended');
