This commit is contained in:
ray zhou
2026-06-29 14:51:55 +08:00
parent 225fb2bd28
commit 2dd9f17da9
319 changed files with 29461 additions and 9412 deletions

View File

@@ -0,0 +1,175 @@
<!-- d451269e-1f41-4d6f-ad1f-e7ac88a4925f -->
---
todos:
- id: "constants"
content: "TrialRewardConstantsACTIVITY_CODE + ext 键;移除 center CONFIG_KEY_*"
status: pending
- id: "model"
content: "ActivityModel::findActiveByCode(activity_code, source, now)"
status: pending
- id: "resolver"
content: "新增 TrialRewardActivityResolver从 activity.ext 解析 threshold/cap"
status: pending
- id: "logic"
content: "TrialFirstDepositLogic / queryRecord 改用 resolver去掉 ShareConfig trialReward"
status: pending
- id: "center-cleanup"
content: "删除 slot-center share_config activity.trialReward 块"
status: pending
- id: "seed-sql"
content: "新增 activity 表 patchtrial_reward + ext JSON"
status: pending
- id: "test-e2e"
content: "补 resolver 单测 + 联调验证(不依赖 center 业务配置)"
status: pending
isProject: false
---
# 试玩活动配置center 迁出,按 activity_code 解析
## 结论(对你问题的回应)
**我同意你的方向**,且比当前联调实现更贴合项目既有模式:
- **center 不应承载** `deposit_threshold``trial_withdrawal_cap``activity_id` 等业务参数;它只适合 `walletApiHost` 等基础设施。
- **活动服决定业务规则**:阈值、上限、开关、时间窗应来自 [`activity`](slot-activity/app/model/ActivityModel.php) 表(运营在 slot-admin 维护),与 [`DepositBonusLogic`](slot-activity/app/innerapi/logic/DepositBonusLogic.php) / [`SignInLogic`](slot-activity/app/api/logic/SignInLogic.php) 读 `ext` 的方式一致。
- **按 `activity_code` 定位**:代码里固定 `trial_reward`(你已选 PHP 常量),各环境 DB 里 `activity_id` 可以不同,**发版/切环境不依赖 center 改数字 ID**。
当前临时方案的问题:
```74:82:slot-center/config/share_config.php
'activity' => [
'trialReward' => [
'activity_id' => 9001,
'activity_code' => 'trial_reward',
'deposit_threshold' => 50,
'trial_withdrawal_cap' => 500,
],
],
```
[`TrialFirstDepositLogic`](slot-activity/app/innerapi/logic/TrialFirstDepositLogic.php) 通过 `ShareConfigService` 读上述键,与「活动服自治」冲突。
---
## 目标架构
```mermaid
sequenceDiagram
participant Pay as slot_pay
participant Act as slot_activity
participant DB as activity_table
participant Wal as slot_wallet
Pay->>Act: first_deposit(uid, source, order_no, ...)
Act->>DB: findActiveByCode(trial_reward, source, now)
DB-->>Act: activity_id + ext(deposit_threshold, cap, ...)
Act->>Wal: clearTrialBonusForPool
Act->>Act: persist trial_reward_record(uid, activity_id)
```
| 配置项 | 现位置 | 目标位置 |
|---|---|---|
| activity 身份 | center `trialReward.activity_id` | `activity.activity_code = trial_reward` → 得到 `activity_id` |
| deposit_threshold | center | `activity.ext.deposit_threshold`(美元,入库 *1000 |
| trial_withdrawal_cap | center | `activity.ext.trial_withdrawal_cap` |
| activity_code 常量 | center | [`TrialRewardConstants::ACTIVITY_CODE`](slot-activity/app/constants/TrialRewardConstants.php) |
center 保留:`walletApiHost`[`TrialWalletGatewayService`](slot-activity/app/service/wallet/TrialWalletGatewayService.php) 仍需要)。
---
## 实现步骤
### 1. 定义活动编码与 ext 键slot-activity
改 [`TrialRewardConstants.php`](slot-activity/app/constants/TrialRewardConstants.php)
- 新增 `ACTIVITY_CODE = 'trial_reward'`PHP 常量,跨环境稳定)
- 新增 ext 字段键名常量:`EXT_DEPOSIT_THRESHOLD`、`EXT_TRIAL_WITHDRAWAL_CAP` 等
- **删除** 指向 center 的 `CONFIG_KEY_ACTIVITY_ID / CODE / DEPOSIT_THRESHOLD / WITHDRAWAL_CAP`
- 保留 `DEFAULT_DEPOSIT_THRESHOLD`、`DEFAULT_WITHDRAWAL_CAP` 作为 **ext 缺省兜底**(与 SignIn 读 ext 缺字段时给默认值一致)
### 2. ActivityModel 增加按 code 查询
在 [`ActivityModel.php`](slot-activity/app/model/ActivityModel.php) 新增(对齐现有 `findMatchedSignInBySource` / `findActiveByIdForDeposit` 风格):
```php
public static function findActiveByCode(string $activityCode, string $source, string $now): ?self
```
条件:`activity_code` 精确匹配 + `status=1` + 时间窗 + `source_list` 命中(`all` 或 `$source`)。
可选后续:在 `slot-foundation` 增加 `ActivityType::TRIAL_WITHDRAWAL`admin 筛选用;**本期不强制**code 已足够唯一标识。
### 3. 抽取活动配置解析(避免 Logic 堆 ext 解析)
新增小类,例如 [`TrialRewardActivityResolver.php`](slot-activity/app/service/trial/TrialRewardActivityResolver.php)
- 输入:`source`(来自 [`TrialFirstDepositDto`](slot-activity/app/innerapi/dto/TrialFirstDepositDto.php)
- 输出:`activity_id`、`activity_code`(快照用)、`deposit_threshold`*1000、`trial_withdrawal_cap`*1000
- 活动不存在/未启用/未命中渠道 → 抛业务异常或返回明确 reason如 `activity_not_found`**禁止静默用 center 默认值**
解析规则:
- `activity_id` / `activity_code` 来自 DB 行
- 阈值从 `ext` 读,缺省用 `TrialRewardConstants::DEFAULT_*`,再 `MoneyTool::bigUnitToSmallUnit`
### 4. 改造 TrialFirstDepositLogic
改 [`TrialFirstDepositLogic.php`](slot-activity/app/innerapi/logic/TrialFirstDepositLogic.php)
- `handleFirstDeposit()`:先 `resolveActivity($dto->source)`,再用返回的 `activity_id` 查/建 `trial_reward_record`
- `persistPool()``activity_code`、阈值、cap 均来自 resolver**移除所有 `ShareConfigService::get(trialReward.*)`**
- `queryRecord()`:同样按 `ACTIVITY_CODE` resolve 后再 `findByUidActivity`
- `resolveThresholdAmount()` / `resolveWithdrawalCap()`:改为接收已解析的 Activity 或 config DTO不再读 center
失败语义建议:
| reason | 含义 |
|---|---|
| `activity_not_found` | 无生效的 trial_reward 活动 |
| `wallet_clear_failed` | wallet 清零失败(保持现有) |
| `duplicate` / `success` | 不变 |
### 5. 移除 center 试玩业务配置
改 [`slot-center/config/share_config.php`](slot-center/config/share_config.php)
- **删除整个 `activity.trialReward` 块**(不是只删 threshold
- 重启 center本地 dev 已习惯 `php webman restart -d`
### 6. 联调/上线数据activity 表种子
新增 SQL 补丁,例如 [`slot-activity/db/patch_trial_reward_activity.sql`](slot-activity/db/patch_trial_reward_activity.sql)(插入/更新 `activity` 行,`activity_code=trial_reward`
```json
{
"deposit_threshold": 50,
"trial_withdrawal_cap": 500,
"trial_bonus_amount": 20
}
```
字段建议:`status=1`、`new_user_only=1`、`first_deposit_only=0`(首充事件另管 Pool、`source_list=["all"]`、合理 `start_time/end_time`。`activity_id` 自增即可,**各环境可以不同**。
### 7. 测试调整
- 单测 [`TrialFirstDepositStatusTest`](slot-activity/tests/Unit/Logic/TrialFirstDepositStatusTest.php):纯状态机不变
- 新增 resolver 单测mock `ActivityModel` 或测 ext 解析私有方法ext 有/无字段、美元→*1000
- 联调:在 **slotMysql.s_activity** 执行 activity 种子后,重跑首充 happy-path不再依赖 center trialReward
---
## 不变更范围(刻意不做)
- **slot-pay**:仍只调 `/innerapi/trial-reward/first-deposit`,不传 `activity_id`符合「pay 只报事件activity 解析活动」)
- **slot-wallet / slot-sdk**:无改动
- **slot-admin 后台表单**:本期可先用 SQL 种子 + ext JSON完整 07 子需求的可视化配置可后续单独做
---
## 风险与注意
1. **必须先有 activity 行**:删掉 center 配置后,若 DB 无 `trial_reward` 活动,首充会 `activity_not_found`(比误用 9001 更安全)。
2. **历史联调数据**:若 `trial_reward_record` 里是 `activity_id=9001`,新环境 activity 自增 ID 不同;新用户无影响,老测试 uid 需清数据或对齐 activity_id。
3. **ShareConfigService 仍保留**:仅用于 `walletApiHost` 等,与试玩业务解耦。