fix(package-series): 将 enable_one_time_commission 字段提升到创建/更新请求顶层
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m5s

- DTO: CreatePackageSeriesRequest 和 UpdatePackageSeriesRequest 添加 EnableOneTimeCommission 字段
- Service: Create/Update 方法处理顶层字段并同步到 JSON config 的 Enable 字段
- 确保顶层字段与 JSON config 内的 enable 保持一致,避免业务逻辑判断出错
This commit is contained in:
2026-02-04 14:38:10 +08:00
parent b18ecfeb55
commit dc84cef2ce
3 changed files with 91 additions and 0 deletions

View File

@@ -28,6 +28,7 @@ type CreatePackageSeriesRequest struct {
SeriesCode string `json:"series_code" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"系列编码"`
SeriesName string `json:"series_name" validate:"required,min=1,max=255" required:"true" minLength:"1" maxLength:"255" description:"系列名称"`
Description string `json:"description" validate:"omitempty,max=500" maxLength:"500" description:"描述"`
EnableOneTimeCommission *bool `json:"enable_one_time_commission" description:"是否启用一次性佣金"`
OneTimeCommissionConfig *SeriesOneTimeCommissionConfigDTO `json:"one_time_commission_config" validate:"omitempty" description:"一次性佣金规则配置"`
}
@@ -35,6 +36,7 @@ type CreatePackageSeriesRequest struct {
type UpdatePackageSeriesRequest struct {
SeriesName *string `json:"series_name" validate:"omitempty,min=1,max=255" minLength:"1" maxLength:"255" description:"系列名称"`
Description *string `json:"description" validate:"omitempty,max=500" maxLength:"500" description:"描述"`
EnableOneTimeCommission *bool `json:"enable_one_time_commission" description:"是否启用一次性佣金"`
OneTimeCommissionConfig *SeriesOneTimeCommissionConfigDTO `json:"one_time_commission_config" validate:"omitempty" description:"一次性佣金规则配置"`
}

View File

@@ -43,8 +43,18 @@ func (s *Service) Create(ctx context.Context, req *dto.CreatePackageSeriesReques
}
series.Creator = currentUserID
if req.EnableOneTimeCommission != nil {
series.EnableOneTimeCommission = *req.EnableOneTimeCommission
}
if req.OneTimeCommissionConfig != nil {
config := s.dtoToModelConfig(req.OneTimeCommissionConfig)
config.Enable = series.EnableOneTimeCommission
if err := series.SetOneTimeCommissionConfig(config); err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "设置一次性佣金配置失败")
}
} else if series.EnableOneTimeCommission {
config := &model.OneTimeCommissionConfig{Enable: true}
if err := series.SetOneTimeCommissionConfig(config); err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "设置一次性佣金配置失败")
}
@@ -88,11 +98,24 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageSer
if req.Description != nil {
series.Description = *req.Description
}
if req.EnableOneTimeCommission != nil {
series.EnableOneTimeCommission = *req.EnableOneTimeCommission
}
if req.OneTimeCommissionConfig != nil {
config := s.dtoToModelConfig(req.OneTimeCommissionConfig)
config.Enable = series.EnableOneTimeCommission
if err := series.SetOneTimeCommissionConfig(config); err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "设置一次性佣金配置失败")
}
} else if req.EnableOneTimeCommission != nil {
existingConfig, _ := series.GetOneTimeCommissionConfig()
if existingConfig == nil {
existingConfig = &model.OneTimeCommissionConfig{}
}
existingConfig.Enable = series.EnableOneTimeCommission
if err := series.SetOneTimeCommissionConfig(existingConfig); err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "设置一次性佣金配置失败")
}
}
series.Updater = currentUserID

View File

@@ -73,9 +73,75 @@ rules:
- 性能敏感操作必须考虑 Redis 缓存
tasks:
# 契约规则
- tasks.md 是契约,不可擅自变更
- 禁止跳过任务、合并任务、简化任务(除非获得许可)
- 必须逐项完成并标记状态
# TDD 工作流(必须遵守)
- "任务组 0 必须是测试准备:生成测试 + 运行确认全部 FAIL"
- "按功能单元组织任务而非按技术层级Store/Service/Handler"
- "每个功能单元完成后必须有验证步骤:运行相关测试确认 PASS"
- "最终验证必须包含:全部验收测试 PASS + 全部流程测试 PASS"
# 任务组结构模板
# ```
# ## 0. 测试准备(实现前执行)
# - [ ] 0.1 生成验收测试和流程测试(/opsx:gen-tests
# - [ ] 0.2 运行测试确认全部 FAIL证明测试有效
#
# ## 1. 基础设施(数据库 + Model
# - [ ] 1.x 创建迁移、Model、DTO
# - [ ] 1.y 验证:编译通过
#
# ## 2. 功能单元 A完整垂直切片
# - [ ] 2.1 Store 层
# - [ ] 2.2 Service 层
# - [ ] 2.3 Handler 层 + 路由
# - [ ] 2.4 **验证:功能 A 相关验收测试 PASS**
#
# ## N. 最终验证
# - [ ] N.1 全部验收测试 PASS
# - [ ] N.2 全部流程测试 PASS
# - [ ] N.3 完整测试套件无回归
# ```
# 其他规则
- 每个任务必须包含验证步骤单元测试、集成测试、lsp_diagnostics
- 数据库变更必须包含迁移文件(使用 golang-migrate
- 新增 Handler 必须更新文档生成器cmd/api/docs.go 和 cmd/gendocs/main.go
# 共识锁定规则
consensus:
- 在 /opsx:explore 讨论后,必须使用 /opsx:lock 锁定共识
- consensus.md 必须包含四个维度:要做什么、不做什么、关键约束、验收标准
- 每个维度必须由用户逐条确认(不能一次性确认全部)
- 验收标准必须是可测量的(禁止模糊表述如"性能要好"
- proposal 生成时必须验证与 consensus 的一致性
# 验收测试规则
acceptance_tests:
- Spec 的每个 Scenario 必须对应一个验收测试用例
- 验收测试在实现前生成,预期全部 FAIL
- 每个测试必须包含"破坏点"注释(说明什么代码变更会导致失败)
- 测试使用 table-driven 模式(同一 API 多场景)
- 测试文件位置tests/acceptance/{capability}_acceptance_test.go
- 验收测试使用 IntegrationTestEnv不要 mock 依赖
# 业务流程测试规则
business_flow_tests:
- Spec 必须包含 Business Flows 部分(多 API 业务场景)
- 每个 Business Flow 对应一个流程测试
- 流程测试的 steps 之间共享状态(如 ID
- 每个 step 必须声明依赖(依赖哪些前置 step
- 每个 step 必须包含"破坏点"注释
- 测试文件位置tests/flows/{capability}_{flow}_flow_test.go
# 测试金字塔比例
test_pyramid:
- 验收测试(单 API 契约30%
- 流程测试(多 API 业务场景15%
- 集成测试组件集成25%
- 单元测试复杂逻辑30%
- 单元测试仅保留:纯函数、状态机、复杂业务规则、边界条件
- 单元测试删除:简单 CRUD、DTO 转换、配置读取