Files
cursor/plans/free_credits_release_902566c9.plan.md
ray zhou f71a5c59af ok
2026-05-29 11:21:40 +08:00

182 lines
12 KiB
Markdown
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.

---
name: free credits release
overview: 为“首充前免费余额定格与分档释放”准备开发方案,按钱包账务、充值提现事件、客户端 API、后台配置统计分阶段落地。重点遵循现有后端分层规则避免把业务编排错误地下沉到 Service。
todos:
- id: confirm-wallet-fields
content: 按已确认口径使用 deposit_balance + withdraw_balance 作为免费余额
status: completed
- id: design-schema
content: 设计独立 Free Credits 活动主表、档位明细表、流水关联和旧活动 ID 关联
status: completed
- id: implement-console-core
content: 在 slot_console 实现活动领域模型、定格、解锁、Claim 和状态查询 Logic
status: pending
- id: wire-recharge
content: 接入 slot_pay/slot_console 充值成功链路并保证首充定格幂等
status: completed
- id: wire-cashout
content: 实现第一档独立提现订单和回调状态同步
status: completed
- id: add-console-apis
content: 补充大厅状态、活动入口、后台配置统计相关 API
status: completed
- id: test-acceptance
content: 按需求文档核心规则和账务验收补测试/联调用例
status: completed
isProject: false
---
# 首充前免费余额定格与分档释放开发准备
## 目标范围
本次需求核心实现应以后端账务和状态机为主,前端展示依赖新增/扩展 API。主要涉及
- [`/Users/ray/Documents/project/www/slot/slot_console`](slot_console)Free Credits 活动领域模型、Pool、档位、状态机、定格/释放/Claim 编排、大厅/提现页接口、活动入口、配置读取、后台统计入口。
- [`/Users/ray/Documents/project/www/slot/slot_wallet`](slot_wallet):只提供钱包原子能力,例如余额扣减/入账、钱包流水、Deposit Balance 入账、Y1 流水任务创建;不放活动领域模型和活动状态机。
- [`/Users/ray/Documents/project/www/slot/slot_pay`](slot_pay):充值成功异步通知、第一档独立提现订单。
- [`/Users/ray/Documents/project/www/slot/backend/slot_admin`](backend/slot_admin):运营后台配置和统计页,如该项目负责管理端。
- 客户端 UI 由前端人员在其它仓库实现,本仓库只提供后端接口和状态数据。
已有统一活动管理表可作为关联来源:
- `s_common.s_recharge_gift_config`:现有充值赠送活动主表。
- `recharge_gift_player`:现有充值赠送活动参与玩家表。
本需求不直接复用这两张表承载 Free Credits 账务状态,采用独立 Free Credits 表设计,并保留与旧活动 ID 的关联,避免把“首充前免费余额定格”与已有充值赠送活动规则混在同一张参与表里。
## 数据表 DDL 草案
金额字段建议沿用现有活动表中的 `_qf` 口径,按千分位整数保存,避免小数精度问题。
```sql
CREATE TABLE `free_credits_player` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`activity_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '关联 s_recharge_gift_config.id',
`uid` bigint unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
`source` varchar(64) NOT NULL DEFAULT '' COMMENT '渠道',
`model_id` int unsigned NOT NULL DEFAULT '0' COMMENT '游戏模型ID',
`home_withdraw_unlocked` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '首页Withdraw是否已解锁 0否 1是',
`frozen_amount_qf` bigint unsigned NOT NULL DEFAULT '0' COMMENT '首充时定格金额,千分位',
`first_cash_amount_qf` bigint unsigned NOT NULL DEFAULT '0' COMMENT '第一档免打码提现金额,千分位',
`first_recharge_order_id` varchar(64) NOT NULL DEFAULT '' COMMENT '触发定格的首笔充值订单号',
`first_recharge_time` datetime DEFAULT NULL COMMENT '首笔充值成功时间',
`first_cashout_order_id` varchar(64) NOT NULL DEFAULT '' COMMENT '第一档独立提现订单号',
`status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '主状态 0未开始 1首页已解锁 2已定格 3待充值解锁 4第一档可提现 5第一档提现中 6第一档已提现 7后续释放中 10全部完成',
`completed_time` datetime DEFAULT NULL COMMENT '全部完成时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_activity_uid` (`activity_id`,`uid`),
KEY `idx_uid` (`uid`),
KEY `idx_activity_status` (`activity_id`,`status`),
KEY `idx_first_recharge_order` (`first_recharge_order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Free Credits用户活动主表';
```
```sql
CREATE TABLE `free_credits_package` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`player_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'free_credits_player.id',
`activity_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '关联 s_recharge_gift_config.id',
`uid` bigint unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
`package_no` int unsigned NOT NULL DEFAULT '0' COMMENT '档位序号从1开始',
`package_type` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '档位类型 1第一档免打码提现 2后续释放档',
`amount_qf` bigint unsigned NOT NULL DEFAULT '0' COMMENT '档位金额,千分位',
`status` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '档位状态 0锁定 1可操作 2处理中 3已完成 4失败 5风控拒绝',
`withdraw_order_id` varchar(64) NOT NULL DEFAULT '' COMMENT '第一档提现订单号',
`claim_biz_id` varchar(64) NOT NULL DEFAULT '' COMMENT '后续档Claim入账幂等业务号',
`unlocked_time` datetime DEFAULT NULL COMMENT '解锁时间',
`claimed_time` datetime DEFAULT NULL COMMENT '领取时间',
`completed_time` datetime DEFAULT NULL COMMENT '完成时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_player_package` (`player_id`,`package_no`),
UNIQUE KEY `uniq_claim_biz` (`claim_biz_id`),
KEY `idx_uid_status` (`uid`,`status`),
KEY `idx_activity_status` (`activity_id`,`status`),
KEY `idx_withdraw_order` (`withdraw_order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Free Credits档位明细表';
```
## 建议数据流
```mermaid
flowchart TD
preDepositUser["未首充用户"] --> winThreshold["免费余额曾达到门槛"]
winThreshold --> homeUnlocked["首页 Withdraw 解锁"]
preDepositUser --> firstRecharge["任意入口首笔真实充值成功"]
firstRecharge --> freezeFreeCredits["定格当前免费余额"]
freezeFreeCredits --> freeCreditsPool["slot_console 保存 Free Credits Pool 与档位"]
firstRecharge --> walletTotalRecharge["查询钱包累计充值总额"]
walletTotalRecharge --> firstReady["累计充值满门槛释放第一档"]
firstReady --> firstCashout["第一档独立提现"]
firstCashout --> laterPackages["后续档位按充值解锁"]
laterPackages --> claimToWallet["Claim 入 Deposit Balance"]
claimToWallet --> y1Task["创建 Y1 流水任务"]
```
## 后端落地方案
1.`slot_console` 新增独立 Free Credits 活动领域模型。
- 新增用户池主表,保存 `activity_id``uid`、定格金额、首充订单、主状态、首页解锁标记、完成时间等;主表不保存累计充值。
- 新增档位明细表,一档一行,保存序号、类型、金额、状态、关联提现单/Claim 流水、解锁/完成时间。
- `activity_id` 关联现有 `s_common.s_recharge_gift_config` 或后台活动配置 ID但 Free Credits 的进度、档位和账务状态不写入 `recharge_gift_player`
- 表归属按 `slot_console` 现有业务库和活动模块规范处理;`slot_wallet` 不新增 Free Credits 活动表。
2.`slot_console` 增加 Logic 编排定格、解锁、Claim。
- Controller 只做请求接收、Validate、DTO、统一响应。
- Validate 处理参数必填/类型/枚举。
- DTO 只承载已校验字段。
- Logic 负责首充定格、查询钱包累计充值总额、档位状态流转、事务和幂等。
- Model 负责查询/写入和状态条件更新。
- Service 仅用于已有公共能力,如调用钱包原子 API、配置读取、外部系统封装不新增单纯转发 Service。
- 调用 `slot_wallet` 时只请求余额变更、钱包流水、入 Deposit Balance、创建 Y1 任务等钱包能力,不把活动状态写入钱包服务。
3. 接入充值成功链路。
- 现有充值成功链路在 [`/Users/ray/Documents/project/www/slot/slot_pay/app/command/EventRecharge.php`](slot_pay/app/command/EventRecharge.php) 调用钱包充值入账。
- 充值成功后由 `slot_pay` 或事件消费者通知 `slot_console`,由 `slot_console` 判断是否首笔真实充值并触发定格。
- 定格需要调用 `slot_wallet` 原子能力扣减当前免费余额并写钱包流水,再由 `slot_console` 落 Free Credits Pool 和档位。
- 第一档门槛通过调用钱包查询用户累计充值总额判断;`slot_console` 主表不保存累计充值,也不新增充值事件明细表。
4. 实现第一档独立提现。
- 第一档不进入普通钱包余额,创建独立提现订单类型 `free_credit_first_cashout`
- 需要在 `slot_pay` 的提现订单模型/实体中支持新订单类型,提现处理中防重复,成功/失败/拒绝回写档位状态。
- 第一档提现成功后关闭首页状态条,但活动入口保留到所有档位完成。
5. 实现后续档位解锁和 Claim。
- 后续每笔符合条件真实充值最多解锁下一档,按配置控制最小充值金额和每笔最多解锁档数。
- Claim 由 `slot_console` 校验档位状态和顺序后,调用 `slot_wallet` 将档位金额入 `Deposit Balance`,创建 Deposit Lot 和 Y1 Wager Task。
- `slot_console` 负责 Claim 幂等和档位状态流转;`slot_wallet` 负责钱包入账幂等和流水一致性。失败时档位保持 `ready`,重复点击不能重复入账。
6. 增加客户端查询与操作 API。
- 查询用户活动状态首页状态条、活动入口、Free Play to Go 弹窗需要同一份状态数据。
- 操作 API第一档提现、后续 Claim、后续 Unlock 跳充值。
- `slot_console` 可在 [`/Users/ray/Documents/project/www/slot/slot_console/app/napi/controller/LobbyController.php`](slot_console/app/napi/controller/LobbyController.php) 或独立 API 暴露大厅所需数据。
7. 增加后台配置与统计。
- 配置项优先绑定到现有统一活动管理的活动 IDFree Credits 专属配置包括活动开关、首笔赢取门槛、充值解锁门槛、免打码提现额、拆分金额、后续最小充值、每笔最多解锁档数、Y1 倍数、Banner。
- 统计项:定格人数、完成提现人数、全部完成人数、定格总金额、已提现金额、已领取金额、待释放金额。
- 筛选排序按文档要求实现。
## 已确认口径
- 免费余额 = `deposit_balance + withdraw_balance`,即钱包余额。
- 第一档不需要流水,完全绕开普通可提现余额计算。
- 第一档解锁通过充值成功异步通知驱动,并调用钱包查询累计充值总额判断是否达到门槛。
- Free Credits 定格逻辑以独立活动配置为准。
- 客户端 UI 由前端人员处理,本仓库不包含对应页面代码。
## 关键风险与需确认点
- 文档中的 `Deposite Balance / Deposite Lot` 建议统一确认是否为历史命名还是拼写问题。
## 建议开发顺序
1. 先实现 `slot_console` 活动数据模型、配置读取、状态机和只读查询接口。
2. 梳理并补齐 `slot_wallet` 需要暴露的钱包原子能力,包括查询累计充值总额、冻结/扣减免费余额、入 Deposit Balance、创建 Y1 任务和幂等流水。
3. 接入充值成功链路,完成 `slot_pay``slot_console` 的事件通知、首充定格和调用钱包累计充值总额解锁第一档。
4. 实现第一档独立提现链路和提现回调到 `slot_console` 的状态同步。
5. 实现后续档位解锁、Claim 调用钱包入账和 Y1 流水任务创建。
6. 补 `slot_console` 大厅/活动入口接口、后台统计、客户端 UI、文案、埋点和验收用例。