rwadurian/backend/services/contribution-service/prisma/migrations/0001_init/migration.sql

474 lines
21 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- ============================================================================
-- 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");