From f26a796244673638a43051823da0762873e8f09a Mon Sep 17 00:00:00 2001 From: hailin Date: Sun, 11 Jan 2026 06:31:24 -0800 Subject: [PATCH] =?UTF-8?q?fix(contribution-service):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?migration=E4=B8=BA=E5=AE=8C=E6=95=B4=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将增量migration改为完整的初始化migration,包含所有表的CREATE TABLE语句。 原migration使用ALTER TABLE假设表已存在,但这是服务的第一个migration文件。 Co-Authored-By: Claude Opus 4.5 --- .../20260111000000_init/migration.sql | 496 ++++++++++++++++++ .../migration.sql | 158 ------ .../prisma/migrations/migration_lock.toml | 3 + 3 files changed, 499 insertions(+), 158 deletions(-) create mode 100644 backend/services/contribution-service/prisma/migrations/20260111000000_init/migration.sql delete mode 100644 backend/services/contribution-service/prisma/migrations/20260111100000_add_pending_unlock_fields/migration.sql create mode 100644 backend/services/contribution-service/prisma/migrations/migration_lock.toml diff --git a/backend/services/contribution-service/prisma/migrations/20260111000000_init/migration.sql b/backend/services/contribution-service/prisma/migrations/20260111000000_init/migration.sql new file mode 100644 index 00000000..5064cfdf --- /dev/null +++ b/backend/services/contribution-service/prisma/migrations/20260111000000_init/migration.sql @@ -0,0 +1,496 @@ +-- ============================================ +-- Migration: contribution-service 初始化 +-- +-- 包含所有表的创建: +-- 1. CDC 同步表 (synced_users, synced_adoptions, synced_referrals) +-- 2. 算力账户表 (contribution_accounts) +-- 3. 算力明细表 (contribution_records) +-- 4. 解锁事件表 (unlock_events) +-- 5. 未分配算力表 (unallocated_contributions) +-- 6. 系统账户表 (system_accounts, system_contribution_records) +-- 7. 快照与统计表 (daily_contribution_snapshots, user_team_stats) +-- 8. CDC 同步状态表 (cdc_sync_progress, processed_events) +-- 9. 配置表 (contribution_configs, distribution_rate_configs) +-- 10. Outbox 事件表 (outbox_events) +-- ============================================ + +-- ============================================ +-- 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(20), + "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), + "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 TABLE "synced_referrals" ( + "id" BIGSERIAL NOT NULL, + "account_sequence" VARCHAR(20) NOT NULL, + "referrer_account_sequence" VARCHAR(20), + "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"); + +-- ============================================ +-- 2. 算力账户表 +-- ============================================ + +-- 算力账户表(汇总) +-- 设计说明: +-- - 个人算力:自己认种,立即生效 +-- - 层级算力:下级1-15层认种的分成,每层0.5%,共7.5% +-- - 加成算力:团队加成,3档各2.5%,共7.5% +-- 解锁规则: +-- - 自己认种:解锁层级1-5 + 加成第1档 +-- - 直推≥2人认种:解锁加成第2档 +-- - 直推≥3人认种:解锁层级6-10 +-- - 直推≥4人认种:解锁加成第3档 +-- - 直推≥5人认种:解锁层级11-15 +CREATE TABLE "contribution_accounts" ( + "id" BIGSERIAL NOT NULL, + "account_sequence" VARCHAR(20) NOT NULL, + + -- 个人算力(立即生效) + "personal_contribution" DECIMAL(30,10) NOT NULL DEFAULT 0, + + -- 15级层级算力(待解锁) + -- 第1档(1-5级):自己认种解锁 + "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, + -- 第2档(6-10级):直推≥3人认种解锁 + "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, + -- 第3档(11-15级):直推≥5人认种解锁 + "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, + + -- 3档加成算力(待解锁) + "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"); + +-- 添加字段注释 +COMMENT ON COLUMN "contribution_accounts"."level_1_pending" IS '第1级待解锁算力 (0.5%)'; +COMMENT ON COLUMN "contribution_accounts"."level_2_pending" IS '第2级待解锁算力 (0.5%)'; +COMMENT ON COLUMN "contribution_accounts"."level_3_pending" IS '第3级待解锁算力 (0.5%)'; +COMMENT ON COLUMN "contribution_accounts"."level_4_pending" IS '第4级待解锁算力 (0.5%)'; +COMMENT ON COLUMN "contribution_accounts"."level_5_pending" IS '第5级待解锁算力 (0.5%)'; +COMMENT ON COLUMN "contribution_accounts"."level_6_pending" IS '第6级待解锁算力 (0.5%) - 直推≥3人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_7_pending" IS '第7级待解锁算力 (0.5%) - 直推≥3人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_8_pending" IS '第8级待解锁算力 (0.5%) - 直推≥3人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_9_pending" IS '第9级待解锁算力 (0.5%) - 直推≥3人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_10_pending" IS '第10级待解锁算力 (0.5%) - 直推≥3人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_11_pending" IS '第11级待解锁算力 (0.5%) - 直推≥5人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_12_pending" IS '第12级待解锁算力 (0.5%) - 直推≥5人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_13_pending" IS '第13级待解锁算力 (0.5%) - 直推≥5人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_14_pending" IS '第14级待解锁算力 (0.5%) - 直推≥5人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."level_15_pending" IS '第15级待解锁算力 (0.5%) - 直推≥5人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."bonus_tier_1_pending" IS '第1档加成待解锁算力 (2.5%) - 自己认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."bonus_tier_2_pending" IS '第2档加成待解锁算力 (2.5%) - 直推≥2人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."bonus_tier_3_pending" IS '第3档加成待解锁算力 (2.5%) - 直推≥4人认种解锁'; +COMMENT ON COLUMN "contribution_accounts"."unlocked_level_depth" IS '已解锁层级深度: 0=未解锁, 5=1-5级, 10=1-10级, 15=全部'; +COMMENT ON COLUMN "contribution_accounts"."unlocked_bonus_tiers" IS '已解锁加成档位数: 0/1/2/3'; +COMMENT ON COLUMN "contribution_accounts"."effective_contribution" IS '有效算力 = 个人算力 + 已解锁算力'; + +-- ============================================ +-- 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"); + +COMMENT ON COLUMN "contribution_records"."status" IS '状态: PENDING(待解锁)/UNLOCKED(已解锁)/EFFECTIVE(已生效)'; +COMMENT ON COLUMN "contribution_records"."source_type" IS '来源类型: PERSONAL/LEVEL_1~15/BONUS_TIER_1~3'; + +-- ============================================ +-- 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); + +COMMENT ON TABLE "unlock_events" IS '解锁事件记录表 - 记录每次算力解锁的触发原因和结果'; +COMMENT ON COLUMN "unlock_events"."trigger_type" IS '触发类型: SELF_ADOPT(自己认种) / REFERRAL_ADOPT(直推认种)'; +COMMENT ON COLUMN "unlock_events"."unlock_type" IS '解锁类型: LEVEL_1_5/LEVEL_6_10/LEVEL_11_15/BONUS_TIER_1/BONUS_TIER_2/BONUS_TIER_3'; +COMMENT ON COLUMN "unlock_events"."unlock_condition" IS '解锁条件描述,如"自己认种"、"直推认种人数达到3人"'; + +-- ============================================ +-- 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" VARCHAR(20) NOT NULL, + "name" VARCHAR(100) 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_key" ON "system_accounts"("account_type"); + +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, + "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, + "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"); + +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"); + +CREATE TABLE "processed_events" ( + "id" BIGSERIAL NOT NULL, + "event_id" VARCHAR(100) NOT NULL, + "event_type" VARCHAR(50) NOT NULL, + "source_service" VARCHAR(50), + "processed_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "processed_events_pkey" PRIMARY KEY ("id") +); + +CREATE UNIQUE INDEX "processed_events_event_id_key" ON "processed_events"("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"); + +-- ============================================ +-- 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. 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"); diff --git a/backend/services/contribution-service/prisma/migrations/20260111100000_add_pending_unlock_fields/migration.sql b/backend/services/contribution-service/prisma/migrations/20260111100000_add_pending_unlock_fields/migration.sql deleted file mode 100644 index 2388dba2..00000000 --- a/backend/services/contribution-service/prisma/migrations/20260111100000_add_pending_unlock_fields/migration.sql +++ /dev/null @@ -1,158 +0,0 @@ --- ============================================ --- Migration: 添加待解锁算力字段和解锁事件记录 --- --- 业务背景: --- 1. 15级层级算力:每级0.5%,共7.5% --- - 自己认种解锁1-5级 --- - 直推≥3人认种解锁6-10级 --- - 直推≥5人认种解锁11-15级 --- 2. 3档加成算力:每档2.5%,共7.5% --- - 自己认种解锁第1档 --- - 直推≥2人认种解锁第2档 --- - 直推≥4人认种解锁第3档 --- ============================================ - --- 1. 删除旧字段(如果存在) -ALTER TABLE "contribution_accounts" DROP COLUMN IF EXISTS "team_level_contribution"; -ALTER TABLE "contribution_accounts" DROP COLUMN IF EXISTS "team_bonus_contribution"; -ALTER TABLE "contribution_accounts" DROP COLUMN IF EXISTS "total_contribution"; - --- 2. 添加15级层级待解锁字段 -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_1_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_2_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_3_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_4_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_5_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_6_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_7_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_8_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_9_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_10_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_11_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_12_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_13_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_14_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "level_15_pending" DECIMAL(30,10) DEFAULT 0; - --- 3. 添加3档加成待解锁字段 -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "bonus_tier_1_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "bonus_tier_2_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "bonus_tier_3_pending" DECIMAL(30,10) DEFAULT 0; - --- 4. 添加汇总字段 -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "total_level_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "total_bonus_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "total_pending" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "total_unlocked" DECIMAL(30,10) DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "effective_contribution" DECIMAL(30,10) DEFAULT 0; - --- 5. 添加解锁条件状态字段 -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "has_adopted" BOOLEAN DEFAULT false; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "direct_referral_adopted_count" INTEGER DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "unlocked_level_depth" INTEGER DEFAULT 0; -ALTER TABLE "contribution_accounts" ADD COLUMN IF NOT EXISTS "unlocked_bonus_tiers" INTEGER DEFAULT 0; - --- 6. 更新 contribution_records 表添加状态字段 -ALTER TABLE "contribution_records" ADD COLUMN IF NOT EXISTS "status" VARCHAR(20) DEFAULT 'PENDING'; -ALTER TABLE "contribution_records" ADD COLUMN IF NOT EXISTS "unlocked_at" TIMESTAMP(3); -ALTER TABLE "contribution_records" ADD COLUMN IF NOT EXISTS "unlock_reason" VARCHAR(200); -ALTER TABLE "contribution_records" ADD COLUMN IF NOT EXISTS "remark" VARCHAR(500); - --- 7. 创建索引(contribution_accounts) -CREATE INDEX IF NOT EXISTS "contribution_accounts_has_adopted_idx" ON "contribution_accounts"("has_adopted"); -CREATE INDEX IF NOT EXISTS "contribution_accounts_direct_referral_adopted_count_idx" ON "contribution_accounts"("direct_referral_adopted_count"); -CREATE INDEX IF NOT EXISTS "contribution_accounts_effective_contribution_idx" ON "contribution_accounts"("effective_contribution" DESC); - --- 8. 创建索引(contribution_records) -CREATE INDEX IF NOT EXISTS "contribution_records_status_idx" ON "contribution_records"("status"); -CREATE INDEX IF NOT EXISTS "contribution_records_account_status_idx" ON "contribution_records"("account_sequence", "status"); - --- 9. 创建解锁事件记录表 -CREATE TABLE IF NOT EXISTS "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") -); - --- 10. 创建解锁事件索引 -CREATE INDEX IF NOT EXISTS "unlock_events_account_sequence_idx" ON "unlock_events"("account_sequence"); -CREATE INDEX IF NOT EXISTS "unlock_events_trigger_account_sequence_idx" ON "unlock_events"("trigger_account_sequence"); -CREATE INDEX IF NOT EXISTS "unlock_events_trigger_adoption_id_idx" ON "unlock_events"("trigger_adoption_id"); -CREATE INDEX IF NOT EXISTS "unlock_events_unlock_type_idx" ON "unlock_events"("unlock_type"); -CREATE INDEX IF NOT EXISTS "unlock_events_created_at_idx" ON "unlock_events"("created_at" DESC); - --- 11. 更新 unallocated_contributions 表 -ALTER TABLE "unallocated_contributions" ADD COLUMN IF NOT EXISTS "bonus_tier" INTEGER; -ALTER TABLE "unallocated_contributions" ADD COLUMN IF NOT EXISTS "status" VARCHAR(20) DEFAULT 'PENDING'; -ALTER TABLE "unallocated_contributions" ADD COLUMN IF NOT EXISTS "allocated_to_account_sequence" VARCHAR(20); - --- 删除旧的列(如果存在) -ALTER TABLE "unallocated_contributions" DROP COLUMN IF EXISTS "allocated_to_headquarters"; - --- 12. 更新索引 -DROP INDEX IF EXISTS "unallocated_contributions_allocated_to_headquarters_idx"; -CREATE INDEX IF NOT EXISTS "unallocated_contributions_status_idx" ON "unallocated_contributions"("status"); -CREATE INDEX IF NOT EXISTS "unallocated_contributions_would_be_account_sequence_idx" ON "unallocated_contributions"("would_be_account_sequence"); - --- 13. 添加注释 -COMMENT ON TABLE "unlock_events" IS '解锁事件记录表 - 记录每次算力解锁的触发原因和结果'; -COMMENT ON COLUMN "unlock_events"."trigger_type" IS '触发类型: SELF_ADOPT(自己认种) / REFERRAL_ADOPT(直推认种)'; -COMMENT ON COLUMN "unlock_events"."unlock_type" IS '解锁类型: LEVEL_1_5/LEVEL_6_10/LEVEL_11_15/BONUS_TIER_1/BONUS_TIER_2/BONUS_TIER_3'; -COMMENT ON COLUMN "unlock_events"."unlock_condition" IS '解锁条件描述,如"自己认种"、"直推认种人数达到3人"'; - -COMMENT ON COLUMN "contribution_accounts"."level_1_pending" IS '第1级待解锁算力 (0.5%)'; -COMMENT ON COLUMN "contribution_accounts"."level_2_pending" IS '第2级待解锁算力 (0.5%)'; -COMMENT ON COLUMN "contribution_accounts"."level_3_pending" IS '第3级待解锁算力 (0.5%)'; -COMMENT ON COLUMN "contribution_accounts"."level_4_pending" IS '第4级待解锁算力 (0.5%)'; -COMMENT ON COLUMN "contribution_accounts"."level_5_pending" IS '第5级待解锁算力 (0.5%)'; -COMMENT ON COLUMN "contribution_accounts"."level_6_pending" IS '第6级待解锁算力 (0.5%) - 直推≥3人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_7_pending" IS '第7级待解锁算力 (0.5%) - 直推≥3人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_8_pending" IS '第8级待解锁算力 (0.5%) - 直推≥3人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_9_pending" IS '第9级待解锁算力 (0.5%) - 直推≥3人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_10_pending" IS '第10级待解锁算力 (0.5%) - 直推≥3人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_11_pending" IS '第11级待解锁算力 (0.5%) - 直推≥5人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_12_pending" IS '第12级待解锁算力 (0.5%) - 直推≥5人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_13_pending" IS '第13级待解锁算力 (0.5%) - 直推≥5人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_14_pending" IS '第14级待解锁算力 (0.5%) - 直推≥5人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."level_15_pending" IS '第15级待解锁算力 (0.5%) - 直推≥5人认种解锁'; - -COMMENT ON COLUMN "contribution_accounts"."bonus_tier_1_pending" IS '第1档加成待解锁算力 (2.5%) - 自己认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."bonus_tier_2_pending" IS '第2档加成待解锁算力 (2.5%) - 直推≥2人认种解锁'; -COMMENT ON COLUMN "contribution_accounts"."bonus_tier_3_pending" IS '第3档加成待解锁算力 (2.5%) - 直推≥4人认种解锁'; - -COMMENT ON COLUMN "contribution_accounts"."unlocked_level_depth" IS '已解锁层级深度: 0=未解锁, 5=1-5级, 10=1-10级, 15=全部'; -COMMENT ON COLUMN "contribution_accounts"."unlocked_bonus_tiers" IS '已解锁加成档位数: 0/1/2/3'; -COMMENT ON COLUMN "contribution_accounts"."effective_contribution" IS '有效算力 = 个人算力 + 已解锁算力'; - -COMMENT ON COLUMN "contribution_records"."status" IS '状态: PENDING(待解锁)/UNLOCKED(已解锁)/EFFECTIVE(已生效)'; -COMMENT ON COLUMN "contribution_records"."source_type" IS '来源类型: PERSONAL/LEVEL_1~15/BONUS_TIER_1~3'; - --- 注意:挖矿收益分配相关的表(mining_reward_allocations, daily_mining_reward_summaries, headquarters_pending_rewards) --- 已移至 mining-service,由 mining-service 负责创建和管理 diff --git a/backend/services/contribution-service/prisma/migrations/migration_lock.toml b/backend/services/contribution-service/prisma/migrations/migration_lock.toml new file mode 100644 index 00000000..99e4f200 --- /dev/null +++ b/backend/services/contribution-service/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql"