refactor(utils): 修复密码哈希比较逻辑错误 feat(user): 新增按状态筛选优惠券接口 docs: 添加虚拟发货与任务中心相关文档 fix(wechat): 修正Code2Session上下文传递问题 test: 补充订单折扣与积分转换测试用例 build: 更新配置文件与构建脚本 style: 清理多余的空行与注释
87 lines
6.9 KiB
Markdown
87 lines
6.9 KiB
Markdown
## 背景
|
||
- 当前不启用数据库外键约束(FK),删除由业务逻辑驱动。
|
||
- 现有删除实现多为单表删除,未做级联:如删除活动 `internal/service/activity/activity_delete.go:9`、删除期 `internal/service/activity/issue_delete.go:9`、删除用户 `internal/service/user/batch_user.go:32`。
|
||
- GORM 初始化未声明外键或级联:`internal/repository/mysql/mysql.go:97`。
|
||
|
||
## 目标
|
||
- 在业务层实现“逻辑级联删除”,保证删除主实体时,同步清理其关联业务数据,且性能与可控性优于 FK 级联。
|
||
|
||
## 级联清单
|
||
### 删除活动(Activities.ID)
|
||
- 删除活动期:`activity_issues` 按 `activity_id`(`internal/repository/mysql/model/activity_issues.gen.go:18`)
|
||
- 期下配置与承诺:
|
||
- 奖励配置 `activity_reward_settings` 按 `issue_id`(`internal/repository/mysql/model/activity_reward_settings.gen.go:18`)
|
||
- 活动承诺字段:`activities.commitment_*`(活动维度,已统一使用活动级承诺,不存在期级承诺表)
|
||
- 期下抽奖相关:
|
||
- 抽奖日志 `activity_draw_logs` 按 `issue_id`(`internal/repository/mysql/model/activity_draw_logs.gen.go:18`)
|
||
- 抽奖效果 `activity_draw_effects` 按 `draw_log_id`/`issue_id`(`internal/repository/mysql/model/activity_draw_effects.gen.go:17,29`)
|
||
- 抽奖凭据 `activity_draw_receipts` 按 `draw_log_id`(`internal/repository/mysql/model/activity_draw_receipts.gen.go:17`)
|
||
- 活动范围效果与道具:
|
||
- 用户道具使用记录 `user_item_cards` 按 `used_activity_id` / `used_issue_id` / `used_draw_log_id`(`internal/repository/mysql/model/user_item_cards.gen.go:24,25,23`)
|
||
- 抽奖效果快照 `activity_draw_effects` 按 `activity_id`/`issue_id`(`internal/repository/mysql/model/activity_draw_effects.gen.go:28,29`)
|
||
- 资产与日志:
|
||
- 用户资产 `user_inventory` 按 `activity_id`(`internal/repository/mysql/model/user_inventory.gen.go:21`)
|
||
- 公会贡献日志 `guild_contribute_logs` 按 `activity_id` / `issues_id`(`internal/repository/mysql/model/guild_contribute_logs.gen.go:19,20`)
|
||
- 系统模板:
|
||
- 系统道具卡 `system_item_cards` 按 `activity_id` / `issue_id`(`internal/repository/mysql/model/system_item_cards.gen.go:23,24`)
|
||
- 系统优惠券 `system_coupons` 按 `activity_id`(`internal/repository/mysql/model/system_coupons.gen.go:20`)
|
||
- 最后删除活动主表:`activities`(`internal/repository/mysql/model/activities.gen.go:15`)
|
||
|
||
### 删除用户(Users.ID)
|
||
- 用户身份与权益:
|
||
- 头衔 `user_titles` 按 `user_id`(`internal/repository/mysql/model/user_titles.gen.go:16`)
|
||
- 领取型权益限流 `user_title_effect_claims` 按 `user_id`(`internal/repository/mysql/model/user_title_effect_claims.gen.go:16`)
|
||
- 用户账户与地址:
|
||
- 地址 `user_addresses` 按 `user_id`(`internal/repository/mysql/model/user_addresses.gen.go:18`)
|
||
- 积分余额 `user_points` 按 `user_id`(`internal/repository/mysql/model/user_points.gen.go:18`)
|
||
- 积分流水 `user_points_ledger` 按 `user_id`(`internal/repository/mysql/model/user_points_ledger.gen.go:17`)
|
||
- 用户订单与优惠:
|
||
- 订单 `orders` 按 `user_id`(`internal/repository/mysql/model/orders.gen.go:18`)
|
||
- 用户优惠券 `user_coupons` 按 `user_id`(`internal/repository/mysql/model/user_coupons.gen.go:18`)
|
||
- 用户资产与道具:
|
||
- 用户资产 `user_inventory` 按 `user_id`(`internal/repository/mysql/model/user_inventory.gen.go:18`)
|
||
- 用户道具卡 `user_item_cards` 按 `user_id`(`internal/repository/mysql/model/user_item_cards.gen.go:18`)
|
||
- 与抽奖相关:
|
||
- 抽奖效果 `activity_draw_effects` 按 `user_id` 或关联 `draw_log_id`(`internal/repository/mysql/model/activity_draw_effects.gen.go:18,17`)
|
||
- 抽奖凭据 `activity_draw_receipts` 关联 `draw_log_id`(`internal/repository/mysql/model/activity_draw_receipts.gen.go:17`)
|
||
- 抽奖日志 `activity_draw_logs` 按 `user_id`(`internal/repository/mysql/model/activity_draw_logs.gen.go:17`)
|
||
- 公会关联:
|
||
- 公会成员 `guild_members` 按 `user_id`(`internal/repository/mysql/model/guild_members.gen.go:18`)
|
||
- 公会贡献日志 `guild_contribute_logs` 按 `user_id`(`internal/repository/mysql/model/guild_contribute_logs.gen.go:18`)
|
||
- 履约/发货:
|
||
- 发货记录 `shipping_records` 按 `user_id`(`internal/repository/mysql/model/shipping_records.gen.go:18`)
|
||
- 运营发货统计 `ops_shipping_stats` 按 `user_id`(`internal/repository/mysql/model/ops_shipping_stats.gen.go:21`)
|
||
- 最后软删用户:`users.deleted_at`(`internal/repository/mysql/model/users.gen.go:20`)
|
||
|
||
## 删除顺序(事务内)
|
||
- 统一采用“从叶到根”的顺序:
|
||
1) 以日志/效果/凭据等子表为先(`activity_draw_effects`、`activity_draw_receipts`、`activity_draw_logs`)
|
||
2) 再清理资产/权益/模板(`user_inventory`、`user_item_cards`、`user_titles`、`system_*`)
|
||
3) 清理期与期下配置(`activity_issues`、`activity_reward_settings`)
|
||
4) 删除根实体(`activities` 或软删 `users`)
|
||
- 全过程包裹在单事务中,任何一步失败则回滚。
|
||
|
||
## 实现策略
|
||
- 新增业务服务方法:
|
||
- `DeleteActivityCascade(ctx, activityID)`:按“删除活动”清单顺序删除
|
||
- `DeleteUserCascade(ctx, userID)`:按“删除用户”清单顺序删除
|
||
- 技术要点:
|
||
- 批量删除使用分批(如 5k/批)避免长事务与大锁;必要时按时间/ID 片段迭代
|
||
- 统一 `WHERE` 条件与索引列(`user_id`/`activity_id`/`issue_id`/`draw_log_id`)确保扫描性能
|
||
- 软删与硬删:保留用户软删(合规与审计),其余按当前表定义硬删;如需统一软删,可后续逐表补充 `gorm.DeletedAt`
|
||
- 幂等性:每个子删除操作按条件删除,无记录时直接通过;重复调用不报错
|
||
- 审计:记录操作日志(操作者、对象ID、影响行数),便于回溯
|
||
|
||
## 验收标准
|
||
- 删除活动时,任一期及其抽奖日志/效果/凭据、奖励配置、承诺、资产、贡献日志与相关模板均被清理;根活动删除成功。
|
||
- 删除用户时,地址/订单/优惠券/积分(余额+流水)/资产/道具/抽奖相关/公会关系/发货记录及统计均被清理;根用户软删成功。
|
||
- 全流程事务保障、失败回滚;批量删除性能稳定,无显著锁表或超时。
|
||
|
||
## 需要改造的现有入口(参考)
|
||
- 活动删除入口:`internal/service/activity/activity_delete.go:9` → 升级为调用 `DeleteActivityCascade`
|
||
- 期删除入口:`internal/service/activity/issue_delete.go:9` → 被 `DeleteActivityCascade` 内部调用(或保留独立级联)
|
||
- 用户删除入口:`internal/service/user/batch_user.go:32` → 升级为调用 `DeleteUserCascade`
|
||
|
||
## 后续动作
|
||
- 我将基于以上清单与顺序,补充两套事务级联删除实现,并为关键入口替换调用;同时补充单元测试覆盖正常/边界/异常三类用例,验证幂等与性能。
|