This commit is contained in:
ray zhou
2026-05-29 11:21:40 +08:00
parent 5d6d482efe
commit f71a5c59af
447 changed files with 32245 additions and 116 deletions

View File

@@ -0,0 +1,182 @@
---
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、文案、埋点和验收用例。