-- ============================================================================
-- contribution-service 初始化 migration
-- 合并自: 0001_init, 0002_add_transactional_idempotency, 20250120000001_add_region_to_system_accounts
-- ============================================================================

-- ============================================
-- 1. CDC 同步数据表
-- ============================================

-- 同步的用户数据
CREATE TABLE "synced_users" (
    "id" BIGSERIAL NOT NULL,
    "account_sequence" VARCHAR(20) NOT NULL,
    "original_user_id" BIGINT NOT NULL,
    "phone" VARCHAR(20),
    "status" VARCHAR(20),
    "source_sequence_num" BIGINT NOT NULL,
    "synced_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "contribution_calculated" BOOLEAN NOT NULL DEFAULT false,
    "contribution_calculated_at" TIMESTAMP(3),
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "synced_users_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "synced_users_account_sequence_key" ON "synced_users"("account_sequence");
CREATE INDEX "synced_users_original_user_id_idx" ON "synced_users"("original_user_id");
CREATE INDEX "synced_users_contribution_calculated_idx" ON "synced_users"("contribution_calculated");

-- 同步的认种数据
CREATE TABLE "synced_adoptions" (
    "id" BIGSERIAL NOT NULL,
    "original_adoption_id" BIGINT NOT NULL,
    "account_sequence" VARCHAR(20) NOT NULL,
    "tree_count" INTEGER NOT NULL,
    "adoption_date" DATE NOT NULL,
    "status" VARCHAR(30),
    "selected_province" VARCHAR(10),
    "selected_city" VARCHAR(10),
    "contribution_per_tree" DECIMAL(20,10) NOT NULL,
    "source_sequence_num" BIGINT NOT NULL,
    "synced_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "contribution_distributed" BOOLEAN NOT NULL DEFAULT false,
    "contribution_distributed_at" TIMESTAMP(3),
    "distribution_summary" TEXT,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "synced_adoptions_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "synced_adoptions_original_adoption_id_key" ON "synced_adoptions"("original_adoption_id");
CREATE INDEX "synced_adoptions_account_sequence_idx" ON "synced_adoptions"("account_sequence");
CREATE INDEX "synced_adoptions_adoption_date_idx" ON "synced_adoptions"("adoption_date");
CREATE INDEX "synced_adoptions_contribution_distributed_idx" ON "synced_adoptions"("contribution_distributed");
CREATE INDEX "synced_adoptions_selected_province_selected_city_idx" ON "synced_adoptions"("selected_province", "selected_city");

-- 同步的推荐关系数据
CREATE TABLE "synced_referrals" (
    "id" BIGSERIAL NOT NULL,
    "account_sequence" VARCHAR(20) NOT NULL,
    "referrer_account_sequence" VARCHAR(20),
    "referrer_user_id" BIGINT,
    "original_user_id" BIGINT,
    "ancestor_path" TEXT,
    "depth" INTEGER NOT NULL DEFAULT 0,
    "source_sequence_num" BIGINT NOT NULL,
    "synced_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "synced_referrals_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "synced_referrals_account_sequence_key" ON "synced_referrals"("account_sequence");
CREATE INDEX "synced_referrals_referrer_account_sequence_idx" ON "synced_referrals"("referrer_account_sequence");
CREATE INDEX "synced_referrals_referrer_user_id_idx" ON "synced_referrals"("referrer_user_id");
CREATE INDEX "synced_referrals_original_user_id_idx" ON "synced_referrals"("original_user_id");

-- ============================================
-- 2. 算力账户表
-- ============================================

CREATE TABLE "contribution_accounts" (
    "id" BIGSERIAL NOT NULL,
    "account_sequence" VARCHAR(20) NOT NULL,
    "personal_contribution" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_1_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_2_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_3_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_4_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_5_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_6_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_7_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_8_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_9_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_10_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_11_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_12_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_13_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_14_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "level_15_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "bonus_tier_1_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "bonus_tier_2_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "bonus_tier_3_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "total_level_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "total_bonus_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "total_pending" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "total_unlocked" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "effective_contribution" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "has_adopted" BOOLEAN NOT NULL DEFAULT false,
    "direct_referral_adopted_count" INTEGER NOT NULL DEFAULT 0,
    "unlocked_level_depth" INTEGER NOT NULL DEFAULT 0,
    "unlocked_bonus_tiers" INTEGER NOT NULL DEFAULT 0,
    "version" INTEGER NOT NULL DEFAULT 1,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "contribution_accounts_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "contribution_accounts_account_sequence_key" ON "contribution_accounts"("account_sequence");
CREATE INDEX "contribution_accounts_effective_contribution_idx" ON "contribution_accounts"("effective_contribution" DESC);
CREATE INDEX "contribution_accounts_has_adopted_idx" ON "contribution_accounts"("has_adopted");
CREATE INDEX "contribution_accounts_direct_referral_adopted_count_idx" ON "contribution_accounts"("direct_referral_adopted_count");

-- ============================================
-- 3. 算力明细表
-- ============================================

CREATE TABLE "contribution_records" (
    "id" BIGSERIAL NOT NULL,
    "account_sequence" VARCHAR(20) NOT NULL,
    "source_type" VARCHAR(30) NOT NULL,
    "source_adoption_id" BIGINT NOT NULL,
    "source_account_sequence" VARCHAR(20) NOT NULL,
    "tree_count" INTEGER NOT NULL,
    "base_contribution" DECIMAL(20,10) NOT NULL,
    "distribution_rate" DECIMAL(10,6) NOT NULL,
    "level_depth" INTEGER,
    "bonus_tier" INTEGER,
    "amount" DECIMAL(30,10) NOT NULL,
    "status" VARCHAR(20) NOT NULL DEFAULT 'PENDING',
    "unlocked_at" TIMESTAMP(3),
    "unlock_reason" VARCHAR(200),
    "effective_date" DATE NOT NULL,
    "expire_date" DATE NOT NULL,
    "is_expired" BOOLEAN NOT NULL DEFAULT false,
    "expired_at" TIMESTAMP(3),
    "remark" VARCHAR(500),
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "contribution_records_pkey" PRIMARY KEY ("id")
);

CREATE INDEX "contribution_records_account_sequence_status_idx" ON "contribution_records"("account_sequence", "status");
CREATE INDEX "contribution_records_account_sequence_created_at_idx" ON "contribution_records"("account_sequence", "created_at" DESC);
CREATE INDEX "contribution_records_source_adoption_id_idx" ON "contribution_records"("source_adoption_id");
CREATE INDEX "contribution_records_source_account_sequence_idx" ON "contribution_records"("source_account_sequence");
CREATE INDEX "contribution_records_source_type_idx" ON "contribution_records"("source_type");
CREATE INDEX "contribution_records_status_idx" ON "contribution_records"("status");
CREATE INDEX "contribution_records_expire_date_idx" ON "contribution_records"("expire_date");
CREATE INDEX "contribution_records_is_expired_idx" ON "contribution_records"("is_expired");

-- ============================================
-- 4. 解锁事件表
-- ============================================

CREATE TABLE "unlock_events" (
    "id" BIGSERIAL NOT NULL,
    "account_sequence" VARCHAR(20) NOT NULL,
    "trigger_type" VARCHAR(30) NOT NULL,
    "trigger_adoption_id" BIGINT NOT NULL,
    "trigger_account_sequence" VARCHAR(20) NOT NULL,
    "unlock_type" VARCHAR(30) NOT NULL,
    "unlock_condition" VARCHAR(100) NOT NULL,
    "before_direct_referral_count" INTEGER NOT NULL,
    "after_direct_referral_count" INTEGER NOT NULL,
    "before_unlocked_level_depth" INTEGER NOT NULL,
    "after_unlocked_level_depth" INTEGER NOT NULL,
    "before_unlocked_bonus_tiers" INTEGER NOT NULL,
    "after_unlocked_bonus_tiers" INTEGER NOT NULL,
    "unlocked_amount" DECIMAL(30,10) NOT NULL,
    "unlocked_record_count" INTEGER NOT NULL,
    "remark" VARCHAR(500),
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "unlock_events_pkey" PRIMARY KEY ("id")
);

CREATE INDEX "unlock_events_account_sequence_idx" ON "unlock_events"("account_sequence");
CREATE INDEX "unlock_events_trigger_account_sequence_idx" ON "unlock_events"("trigger_account_sequence");
CREATE INDEX "unlock_events_trigger_adoption_id_idx" ON "unlock_events"("trigger_adoption_id");
CREATE INDEX "unlock_events_unlock_type_idx" ON "unlock_events"("unlock_type");
CREATE INDEX "unlock_events_created_at_idx" ON "unlock_events"("created_at" DESC);

-- ============================================
-- 5. 未分配算力表
-- ============================================

CREATE TABLE "unallocated_contributions" (
    "id" BIGSERIAL NOT NULL,
    "source_adoption_id" BIGINT NOT NULL,
    "source_account_sequence" VARCHAR(20) NOT NULL,
    "unalloc_type" VARCHAR(30) NOT NULL,
    "would_be_account_sequence" VARCHAR(20),
    "level_depth" INTEGER,
    "bonus_tier" INTEGER,
    "amount" DECIMAL(30,10) NOT NULL,
    "reason" VARCHAR(200),
    "status" VARCHAR(20) NOT NULL DEFAULT 'PENDING',
    "allocated_at" TIMESTAMP(3),
    "allocated_to_account_sequence" VARCHAR(20),
    "effective_date" DATE NOT NULL,
    "expire_date" DATE NOT NULL,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "unallocated_contributions_pkey" PRIMARY KEY ("id")
);

CREATE INDEX "unallocated_contributions_source_adoption_id_idx" ON "unallocated_contributions"("source_adoption_id");
CREATE INDEX "unallocated_contributions_would_be_account_sequence_idx" ON "unallocated_contributions"("would_be_account_sequence");
CREATE INDEX "unallocated_contributions_unalloc_type_idx" ON "unallocated_contributions"("unalloc_type");
CREATE INDEX "unallocated_contributions_status_idx" ON "unallocated_contributions"("status");

-- ============================================
-- 6. 系统账户表
-- ============================================

CREATE TABLE "system_accounts" (
    "id" BIGSERIAL NOT NULL,
    "account_type" TEXT NOT NULL,
    "region_code" TEXT,
    "name" TEXT NOT NULL,
    "contribution_balance" DECIMAL(30,10) NOT NULL DEFAULT 0,
    "contribution_never_expires" BOOLEAN NOT NULL DEFAULT false,
    "version" INTEGER NOT NULL DEFAULT 1,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "system_accounts_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "system_accounts_account_type_region_code_key" ON "system_accounts"("account_type", "region_code");
CREATE INDEX "system_accounts_account_type_idx" ON "system_accounts"("account_type");
CREATE INDEX "system_accounts_region_code_idx" ON "system_accounts"("region_code");

CREATE TABLE "system_contribution_records" (
    "id" BIGSERIAL NOT NULL,
    "system_account_id" BIGINT NOT NULL,
    "source_adoption_id" BIGINT NOT NULL,
    "source_account_sequence" VARCHAR(20) NOT NULL,
    -- 来源类型: FIXED_RATE(固定比例) / LEVEL_OVERFLOW(层级溢出) / LEVEL_NO_ANCESTOR(无上线) / BONUS_TIER_1/2/3(团队奖励未解锁)
    "source_type" VARCHAR(30) NOT NULL,
    -- 层级深度（1-15），仅对 LEVEL_OVERFLOW 和 LEVEL_NO_ANCESTOR 类型有效
    "level_depth" INTEGER,
    "distribution_rate" DECIMAL(10,6) NOT NULL,
    "amount" DECIMAL(30,10) NOT NULL,
    "effective_date" DATE NOT NULL,
    "expire_date" DATE,
    "is_expired" BOOLEAN NOT NULL DEFAULT false,
    -- 软删除时间戳
    "deleted_at" TIMESTAMP(3),
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "system_contribution_records_pkey" PRIMARY KEY ("id")
);

CREATE INDEX "system_contribution_records_system_account_id_idx" ON "system_contribution_records"("system_account_id");
CREATE INDEX "system_contribution_records_source_adoption_id_idx" ON "system_contribution_records"("source_adoption_id");
CREATE INDEX "system_contribution_records_source_type_idx" ON "system_contribution_records"("source_type");
CREATE INDEX "system_contribution_records_deleted_at_idx" ON "system_contribution_records"("deleted_at");

ALTER TABLE "system_contribution_records" ADD CONSTRAINT "system_contribution_records_system_account_id_fkey" FOREIGN KEY ("system_account_id") REFERENCES "system_accounts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- ============================================
-- 7. 快照与统计表
-- ============================================

CREATE TABLE "daily_contribution_snapshots" (
    "id" BIGSERIAL NOT NULL,
    "snapshot_date" DATE NOT NULL,
    "account_sequence" VARCHAR(20) NOT NULL,
    "effective_contribution" DECIMAL(30,10) NOT NULL,
    "network_total_contribution" DECIMAL(30,10) NOT NULL,
    "contribution_ratio" DECIMAL(30,18) NOT NULL,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "daily_contribution_snapshots_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "daily_contribution_snapshots_snapshot_date_account_sequence_key" ON "daily_contribution_snapshots"("snapshot_date", "account_sequence");
CREATE INDEX "daily_contribution_snapshots_snapshot_date_idx" ON "daily_contribution_snapshots"("snapshot_date");
CREATE INDEX "daily_contribution_snapshots_account_sequence_idx" ON "daily_contribution_snapshots"("account_sequence");

CREATE TABLE "user_team_stats" (
    "id" BIGSERIAL NOT NULL,
    "account_sequence" VARCHAR(20) NOT NULL,
    "stats_date" DATE NOT NULL,
    "level_1_trees" INTEGER NOT NULL DEFAULT 0,
    "level_2_trees" INTEGER NOT NULL DEFAULT 0,
    "level_3_trees" INTEGER NOT NULL DEFAULT 0,
    "level_4_trees" INTEGER NOT NULL DEFAULT 0,
    "level_5_trees" INTEGER NOT NULL DEFAULT 0,
    "level_6_trees" INTEGER NOT NULL DEFAULT 0,
    "level_7_trees" INTEGER NOT NULL DEFAULT 0,
    "level_8_trees" INTEGER NOT NULL DEFAULT 0,
    "level_9_trees" INTEGER NOT NULL DEFAULT 0,
    "level_10_trees" INTEGER NOT NULL DEFAULT 0,
    "level_11_trees" INTEGER NOT NULL DEFAULT 0,
    "level_12_trees" INTEGER NOT NULL DEFAULT 0,
    "level_13_trees" INTEGER NOT NULL DEFAULT 0,
    "level_14_trees" INTEGER NOT NULL DEFAULT 0,
    "level_15_trees" INTEGER NOT NULL DEFAULT 0,
    "total_team_trees" INTEGER NOT NULL DEFAULT 0,
    "direct_adopted_referrals" INTEGER NOT NULL DEFAULT 0,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "user_team_stats_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "user_team_stats_account_sequence_stats_date_key" ON "user_team_stats"("account_sequence", "stats_date");
CREATE INDEX "user_team_stats_account_sequence_idx" ON "user_team_stats"("account_sequence");
CREATE INDEX "user_team_stats_stats_date_idx" ON "user_team_stats"("stats_date");

-- ============================================
-- 8. CDC 同步状态表
-- ============================================

CREATE TABLE "cdc_sync_progress" (
    "id" BIGSERIAL NOT NULL,
    "source_topic" VARCHAR(100) NOT NULL,
    "last_sequence_num" BIGINT NOT NULL DEFAULT 0,
    "last_synced_at" TIMESTAMP(3),
    "updated_at" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "cdc_sync_progress_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "cdc_sync_progress_source_topic_key" ON "cdc_sync_progress"("source_topic");

-- 2.0 服务间 Outbox 事件幂等表
CREATE TABLE "processed_events" (
    "id" BIGSERIAL NOT NULL,
    "event_id" VARCHAR(100) NOT NULL,
    "event_type" VARCHAR(50) NOT NULL,
    "source_service" VARCHAR(100) NOT NULL,
    "processed_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "processed_events_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "processed_events_source_service_event_id_key" ON "processed_events"("source_service", "event_id");
CREATE INDEX "processed_events_event_type_idx" ON "processed_events"("event_type");
CREATE INDEX "processed_events_processed_at_idx" ON "processed_events"("processed_at");

-- 1.0 CDC 事件幂等表
CREATE TABLE "processed_cdc_events" (
    "id" BIGSERIAL NOT NULL,
    "source_topic" VARCHAR(200) NOT NULL,
    "offset" BIGINT NOT NULL,
    "table_name" VARCHAR(100) NOT NULL,
    "operation" VARCHAR(10) NOT NULL,
    "processed_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "processed_cdc_events_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "processed_cdc_events_source_topic_offset_key" ON "processed_cdc_events"("source_topic", "offset");
CREATE INDEX "processed_cdc_events_processed_at_idx" ON "processed_cdc_events"("processed_at");

-- ============================================
-- 9. 配置表
-- ============================================

CREATE TABLE "contribution_configs" (
    "id" BIGSERIAL NOT NULL,
    "base_contribution" DECIMAL(20,10) NOT NULL DEFAULT 22617,
    "increment_percentage" DECIMAL(10,6) NOT NULL DEFAULT 0.003,
    "unit_size" INTEGER NOT NULL DEFAULT 100,
    "start_tree_number" INTEGER NOT NULL DEFAULT 1000,
    "is_active" BOOLEAN NOT NULL DEFAULT true,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "contribution_configs_pkey" PRIMARY KEY ("id")
);

CREATE INDEX "contribution_configs_is_active_idx" ON "contribution_configs"("is_active");

CREATE TABLE "distribution_rate_configs" (
    "id" BIGSERIAL NOT NULL,
    "rate_type" VARCHAR(30) NOT NULL,
    "rate_value" DECIMAL(10,6) NOT NULL,
    "description" VARCHAR(100),
    "is_active" BOOLEAN NOT NULL DEFAULT true,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "distribution_rate_configs_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "distribution_rate_configs_rate_type_key" ON "distribution_rate_configs"("rate_type");
CREATE INDEX "distribution_rate_configs_is_active_idx" ON "distribution_rate_configs"("is_active");

-- ============================================
-- 10. 全网进度表
-- ============================================

CREATE TABLE "network_adoption_progress" (
    "id" BIGSERIAL NOT NULL,
    "total_tree_count" INTEGER NOT NULL DEFAULT 0,
    "total_adoption_orders" INTEGER NOT NULL DEFAULT 0,
    "total_adopted_users" INTEGER NOT NULL DEFAULT 0,
    "current_unit" INTEGER NOT NULL DEFAULT 0,
    "current_multiplier" DECIMAL(10,6) NOT NULL DEFAULT 1.0,
    "current_contribution_per_tree" DECIMAL(20,10) NOT NULL DEFAULT 22617,
    "next_unit_tree_count" INTEGER NOT NULL DEFAULT 1000,
    "last_adoption_id" BIGINT,
    "last_adoption_date" DATE,
    "updated_at" TIMESTAMP(3) NOT NULL,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT "network_adoption_progress_pkey" PRIMARY KEY ("id")
);

CREATE TABLE "daily_contribution_rates" (
    "id" BIGSERIAL NOT NULL,
    "effective_date" DATE NOT NULL,
    "start_tree_count" INTEGER NOT NULL DEFAULT 0,
    "start_unit" INTEGER NOT NULL DEFAULT 0,
    "start_multiplier" DECIMAL(10,6) NOT NULL DEFAULT 1.0,
    "contribution_per_tree" DECIMAL(20,10) NOT NULL,
    "end_tree_count" INTEGER,
    "end_unit" INTEGER,
    "end_multiplier" DECIMAL(10,6),
    "daily_tree_count" INTEGER NOT NULL DEFAULT 0,
    "daily_adoption_orders" INTEGER NOT NULL DEFAULT 0,
    "daily_adopted_users" INTEGER NOT NULL DEFAULT 0,
    "is_closed" BOOLEAN NOT NULL DEFAULT false,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "daily_contribution_rates_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX "daily_contribution_rates_effective_date_key" ON "daily_contribution_rates"("effective_date");
CREATE INDEX "daily_contribution_rates_effective_date_idx" ON "daily_contribution_rates"("effective_date");
CREATE INDEX "daily_contribution_rates_is_closed_idx" ON "daily_contribution_rates"("is_closed");

-- ============================================
-- 11. Outbox 事件表
-- ============================================

CREATE TABLE "outbox_events" (
    "outbox_id" BIGSERIAL NOT NULL,
    "event_type" VARCHAR(100) NOT NULL,
    "topic" VARCHAR(100) NOT NULL,
    "key" VARCHAR(200) NOT NULL,
    "payload" JSONB NOT NULL,
    "aggregate_id" VARCHAR(100) NOT NULL,
    "aggregate_type" VARCHAR(50) NOT NULL,
    "status" VARCHAR(20) NOT NULL DEFAULT 'PENDING',
    "retry_count" INTEGER NOT NULL DEFAULT 0,
    "max_retries" INTEGER NOT NULL DEFAULT 5,
    "last_error" TEXT,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "published_at" TIMESTAMP(3),
    "next_retry_at" TIMESTAMP(3),

    CONSTRAINT "outbox_events_pkey" PRIMARY KEY ("outbox_id")
);

CREATE INDEX "outbox_events_status_created_at_idx" ON "outbox_events"("status", "created_at");
CREATE INDEX "outbox_events_status_next_retry_at_idx" ON "outbox_events"("status", "next_retry_at");
CREATE INDEX "outbox_events_aggregate_type_aggregate_id_idx" ON "outbox_events"("aggregate_type", "aggregate_id");
CREATE INDEX "outbox_events_topic_idx" ON "outbox_events"("topic");
