ok
This commit is contained in:
175
plans/Trial config by activity_code-d451269e.plan.md
Normal file
175
plans/Trial config by activity_code-d451269e.plan.md
Normal file
@@ -0,0 +1,175 @@
|
||||
<!-- d451269e-1f41-4d6f-ad1f-e7ac88a4925f -->
|
||||
---
|
||||
todos:
|
||||
- id: "constants"
|
||||
content: "TrialRewardConstants:ACTIVITY_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 表 patch(trial_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` 等,与试玩业务解耦。
|
||||
Reference in New Issue
Block a user