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,176 @@
---
name: 第一档提现或保留余额
overview: 为 Free Credits 第一档定格后首笔金额增加用户二选一沿用现有独立提现或新增「保留到可提现余额」withdraw_balance、不创建打码任务。涉及 slot_wallet 新钱包原子能力、slot_lib RPC、slot_console 新 C 端接口与档位状态同步。
todos:
- id: wallet-first-keep
content: slot_walletWalletLogModel + WalletLogic::freeCreditsFirstCashKeepwithdraw 入账、无 createTask+ 单测
status: completed
- id: slot-lib-rpc
content: slot_lib WalletService 增加 freeCreditsFirstCashKeep RPC
status: completed
- id: console-keep-api
content: slot_consoleFreeCreditsLogic::keepFirstCash + Validator + Controller + 路由
status: completed
- id: console-tests
content: slot_console 单测 FreeCreditsKeepFirstCashTest必要时调整 broadcast action
status: completed
- id: run-phpunit
content: php82 容器跑 console + wallet 相关单测
status: completed
isProject: false
---
# 第一档:提现或保留到可提现余额
## 背景与现状
当前第一档(`package_type=TYPE_FIRST_CASH`)在累计充值解锁后**仅支持**走 [`WithdrawService::applyFreeCreditsFirstCashout`](slot_console/app/service/WithdrawService.php) → Pay 独立提现(`bizType=free_credit_first_cashout`**不经过钱包余额**(需求文档 §15.3)。
后续释放档走 [`FreeCreditsLogic::claim`](slot_console/app/api/logic/FreeCreditsLogic.php) → [`WalletLogic::freeCreditsClaim`](slot_wallet/app/api/logic/WalletLogic.php):入账 **deposit_balance****创建 Y1 打码任务**
新需求:第一档金额用户可二选一:
| 选项 | 行为 |
| --- | --- |
| **Withdraw** | 保持现有 `/api/withdraw/apply` + `package_id` |
| **Keep to balance** | 入账 **withdraw_balance****不** `createTask`,金额立即可参与普通提现规则(无其它未完成打码任务时) |
已确认:保留余额入账 **withdraw_balance**(非 deposit
```mermaid
flowchart TD
firstReady[第一档 status=ready]
firstReady --> withdrawPath["POST /api/withdraw/apply"]
firstReady --> keepPath["POST /api/free-credits/keep-first-cash"]
withdrawPath --> payOrder[Pay 独立提现单]
payOrder --> busCallback[EventBus 提现结果]
busCallback --> pkgDone[package completed]
keepPath --> walletKeep[wallet freeCreditsFirstCashKeep]
walletKeep --> pkgDone
pkgDone --> playerDone[player STATUS_FIRST_CASH_DONE]
```
## 目标契约
### 新接口slot_console
- **路径**`POST /api/free-credits/keep-first-cash`(与现有 `claim` 命名风格一致)
- **入参**`package_id`(必填,`free_credits_package.id`,须为第一档且 `status=ready`
- **成功**`data` 结构同 `status()` / `claim``buildStatus`
- **幂等**`bizId = free_credits_first_keep:{packageId}`;重复请求不重复入账
- **互斥**:同一第一档 `processing/completed` 后不可再提现或 keep提现处理中不可 keep
### 档位与玩家状态(与提现成功对齐)
完成后与 [`handleFirstCashoutResult(success)`](slot_console/app/api/logic/FreeCreditsLogic.php) 一致:
- package → `STATUS_COMPLETED`,写 `completed_time``claim_biz_id` 存幂等键(复用字段,无需改表)
- player → `STATUS_FIRST_CASH_DONE`
- 调用 `refreshPlayerCompletion`
- 首页状态条关闭逻辑与「第一档提现成功」相同C 端仍用 `status` / packages[0] completed
### 钱包slot_wallet
新增 **`freeCreditsFirstCashKeep`**`WalletLogic::run``type` 分发):
- `inc(withdraw=fee, deposit=0, bonus=0)` 增加 **withdraw_balance**
- **不**调用 `createTask`
- 流水:`BIZ_TYPE_FREE_CREDITS_FIRST_KEEP = 'freeCreditsFirstCashKeep'``WALLET_TYPE_GIFT`(与 freeze/claim 一致)
- 事务内完成入账 + `addLog`;成功后 `sendConsoleBus`(可选,用于统计/通知,类型建议 `freeCreditsFirstCashKeep`
对比现有实现:
| 能力 | 入账 | 打码任务 |
| --- | --- | --- |
| `freeCreditsClaim`(后续档) | deposit | Y1 `createTask` |
| **`freeCreditsFirstCashKeep`(新)** | **withdraw** | **无** |
### slot_lib
[`WalletService`](slot_lib/src/services/WalletService.php) 增加常量与方法:
```php
const WALLET_TYPE_FREE_CREDITS_FIRST_KEEP = 'freeCreditsFirstCashKeep';
public function freeCreditsFirstCashKeep($amount, $bizId = ''): Wallet
```
## 实现步骤
### 1. slot_wallet
| 文件 | 改动 |
| --- | --- |
| [`WalletLogModel.php`](slot_wallet/app/model/multi/WalletLogModel.php) | `BIZ_TYPE_FREE_CREDITS_FIRST_KEEP` |
| [`WalletLogic.php`](slot_wallet/app/api/logic/WalletLogic.php) | `freeCreditsFirstCashKeep()`:镜像 `freeCreditsClaim` 事务结构,改为 `inc(fee,0,0)`**删除** `createTask` 调用 |
| 单测 | 新增 `WalletFreeCreditsFirstKeepTest`(或扩展现有 wallet 单测):断言 withdraw 增加、无 task 创建(可 mock `createTask` 不被调用) |
### 2. slot_lib
- [`WalletService.php`](slot_lib/src/services/WalletService.php):常量 + `freeCreditsFirstCashKeep($amount, $bizId)`
### 3. slot_console — Logic
[`FreeCreditsLogic.php`](slot_console/app/api/logic/FreeCreditsLogic.php) 新增 `keepFirstCash(int $uid, int $packageId): array`
1. `assertEligibleParticipant`
2. 查询 package`uid``TYPE_FIRST_CASH``STATUS_READY`
3. `bizId = 'free_credits_first_keep:' . $packageId`
4. package → `STATUS_PROCESSING`,写 `claim_biz_id`
5. `walletService->freeCreditsFirstCashKeep($package->amount_qf, $bizId)`
6. 成功 → package `COMPLETED` + 时间戳player `STATUS_FIRST_CASH_DONE``refreshPlayerCompletion`
7. 失败 → package 回滚 `READY`(同 `claim`
8. 返回 `buildStatus`
**不**改 `advanceByRecharge` / 定格冻结逻辑。
### 4. slot_console — API 层
| 文件 | 改动 |
| --- | --- |
| [`FreeCreditsValidator.php`](slot_console/app/api/validator/FreeCreditsValidator.php) | `SCENE_KEEP_FIRST_CASH``package_id` require\|integer |
| [`FreeCreditsController.php`](slot_console/app/api/controller/FreeCreditsController.php) | `keepFirstCash()` + PHPDoc类注释补充第二路径 |
| 路由配置 | 注册 `POST /api/free-credits/keep-first-cash`(查项目现有 `route` / `config``free-credits` 注册方式,与 `claim` 并列) |
### 5. 广播 / 统计(小改)
- [`buildBroadcastList`](slot_console/app/api/logic/FreeCreditsLogic.php):第一档 completed 若走 keep广播 `action` 可新增 `keep`(或复用 `claim`);与产品确认文案前可先 `keep`
- [`FreeCreditsStatsLogic`](slot_console/app/innerapi/logic/FreeCreditsStatsLogic.php)`first_cashout_*` 按「第一档 completed」统计**keep 与 withdraw 均计入**(无需区分,除非运营后续要拆指标)
### 6. 单测slot_console
| 文件 | 内容 |
| --- | --- |
| 新增 `FreeCreditsKeepFirstCashTest` | harness 注入 mock `WalletService`;断言状态迁移、幂等、非 ready 抛错 |
| 可选集成测 | keep 后 package completed + player `FIRST_CASH_DONE` |
运行:
```bash
docker exec -w /app/www/slot/slot_console php82 ./vendor/bin/phpunit tests/Unit/FreeCreditsKeepFirstCashTest.php
docker exec -w /app/www/slot/slot_wallet php82 ./vendor/bin/phpunit tests/Unit/WalletFreeCreditsFirstKeepTest.php
```
## C 端约定(供联调,本次可不改 PWA
第一档 `packages[0].status === 1` 时展示两个入口:
- **Withdraw** → 现有 `POST /api/withdraw/apply` + `package_id`
- **Keep to Balance** → `POST /api/free-credits/keep-first-cash` + `package_id`
完成后 `packages[0].status === 3`,与提现成功 UI 一致(按钮隐藏 / 成功态)。
## 不在本次范围
- slot_pwa / gateway 前端页面与文案
- 需求文档 §1011 全文修订可后续补「Add to Balance」分支
- 修改后续档 `claim` 的打码规则
- 第一档金额改由后台配置动态展示(仍从 `packages[0].amount` 读取)
## 验收清单
1. 第一档 readykeep 成功 → withdraw_balance 增加对应千分位,**无**新 WagerTask
2. 同一 package 重复 keep幂等不重复加钱
3. keep 成功后package/player 状态与提现成功一致;`status` 接口 packages[0] 为 completed
4. 第一档 processing提现中keep 拒绝
5. 第一档 completedwithdraw / keep 均拒绝
6. 相关单测通过