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

6.0 KiB
Raw Blame History

name, overview, todos, isProject
name overview todos isProject
DailyRebateLogic重构 按 `php-code` 规范重构每日返水领取链路:`claim` 编排化、BusinessException、Model 条件更新;同步调整 Controller 异常映射。`settleDate`/`info` 仅做必要小抽取,不改业务语义。
id content status
model-mark-claimed DailyRebateRecordModel 增加 markClaimedIfClaimable + PHPDoc pending
id content status
logic-claim-refactor DailyRebateLogicclaim 拆 assert/perform/formatBusinessException pending
id content status
logic-info-helper 可选isClaimableRecord 供 info 与 assert 复用 pending
id content status
controller-exception DailyRebateControllercatch BusinessException → FAILED pending
id content status
verify-smoke 跑 verify-slot-backend.sh确认无 RuntimeException 新增 pending
false

DailyRebateLogic 规范重构

范围AskQuestion 中断,按推荐默认)

  • 必做claimDailyRebateController::claimDailyRebateRecordModel
  • 轻量info() 抽取「是否可领」判断为 privateassertClaimableRecord 复用逻辑
  • 不改语义settleDate / expireDueRecords / Redis 结算逻辑保持行为一致,仅在有重复代码时抽 1 个 private可选

现状问题(对照 php-code

claim L92157

  • 6 段 RuntimeException if 墙
  • CAS 写在 Logic 内联,未沉淀 Model
  • Controller catch RuntimeException + PARAMS_ERRORverify 会拦新增行)

参照:FreeCreditsLogic::claimassert* + BusinessException + 状态更新)

目标结构

sequenceDiagram
  participant C as DailyRebateController
  participant L as DailyRebateLogic
  participant M as DailyRebateRecordModel
  participant W as WalletService

  C->>L: claim(uid, source, statDate)
  L->>L: assertActivityEnabled
  L->>L: assertUserDeposited
  L->>M: findByUidAndDate
  L->>L: assertClaimableRecord
  L->>M: markClaimedIfClaimable
  L->>W: gift(rebate, DAILY_REBATE, remark)
  L-->>C: formatClaimResult

1. Model条件更新

DailyRebateRecordModel 新增:

/**
 * 待领取状态下标记为已领取CAS *
 * @return int 影响行数1 表示成功
 */
public static function markClaimedIfClaimable(int $id): int

实现:where id + where status = STATUS_CLAIMABLESTATUS_CLAIMED + claimed_at

2. Logicclaim 拆分为编排 + assert + perform

方法 职责
claim() public 编排 ≤20 行:resolveSource → 默认 statDate → assert → performClaim → 返回
assertActivityEnabled(string $source) 活动未开 → BusinessException
assertUserDeposited(int $uid) 未充值 → BusinessException
assertClaimableRecord(?DailyRebateRecordModel $record) 不存在/状态/金额/过期 → 各一条 BusinessException(合并原 4 条 if
performClaim(int $uid, DailyRebateRecordModel $record, string $statDate) 事务:markClaimedIfClaimableWalletService::gift → commitaffected !== 1 或 wallet 空 → BusinessException
formatClaimResult(...) 返回 stat_date / rebate_amount / display / balance
  • 使用 support\exception\BusinessException(与 FreeCredits 一致)
  • @throws 改为 BusinessException\Throwable(钱包失败)
  • 钱包 biz_idWalletService::gift() 内部已 generateOrderIdslot_lib/src/services/WalletService.php L262265幂等依赖 记录 CASremark 保持 每日返水 {statDate} 便于对账

3. Logicinfo 轻量复用(可选)

抽取 isClaimableRecord(DailyRebateRecordModel $record): boolstatus + amount + expireinfo()claimable 块与 assertClaimableRecord 共用,避免两套判断漂移。

4. Controller异常映射

DailyRebateController::claim

} catch (BusinessException $e) {
    return $this->errorCode(ErrorCode::FAILED, $e->getMessage());
}
  • 对齐 SignController(业务失败 FAILED + 文案)
  • API 变更code40003PARAMS_ERROR变为 1FAILED文案仍为中文业务提示。若 PWA 强依赖 40003,可在计划中改为保留 PARAMS_ERROR(实现时二选一,默认 FAILED

不采用 FreeCredits「无 catch、走全局 Handler」方式避免未捕获时变成 SYSTEM_ERROR50001

5. 不动 / 谨慎

  • 事务边界:维持「先 CAS 再 gift 再 commit」不在此 PR 改为「先 wallet 后 DB」或 Outbox
  • settleDate:逻辑不变;可选抽 settleOneUserFromRedis(...) 降低 foreach 嵌套(非必须)

文件清单

文件 变更
slot_console/app/model/common/DailyRebateRecordModel.php +markClaimedIfClaimable
slot_console/app/api/logic/DailyRebateLogic.php 重构 claim;可选 isClaimableRecord
slot_console/app/api/controller/DailyRebateController.php BusinessException + FAILED

验收

  1. docker exec -w /app/www/slot/slot_console php82 php webman dailyRebateSettle --date=...(如有环境)结算后,已充值用户可领昨日返水
  2. 重复领取 → 业务错误文案DB 仍为 CLAIMED,不重复入账
  3. ~/.cursor/hooks/verify-slot-backend.sh → PASS无新增 RuntimeException 业务态)
  4. 最终回复含 PHPDoc: checked(触及符号补全 @throws BusinessException

风险与回滚

  • PWA 错误码:若前端按 code===40003 分支,需同步前端或 Controller 保留 PARAMS_ERROR
  • 回滚:还原 3 个文件即可