feat: 新增代理分配套餐上架状态(shelf_status)功能
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m56s

- 新增数据库迁移:为 shop_package_allocation 表添加 shelf_status 字段
- 更新模型/DTO:ShopPackageAllocation 增加 ShelfStatus 字段及相关枚举
- 更新套餐分配 Service:支持上架/下架状态管理逻辑
- 更新套餐 Store/Service:根据 shelf_status 过滤可售套餐
- 更新购买验证 Service:引入上架状态校验逻辑
- 归档 OpenSpec 变更:2026-03-02-agent-allocation-shelf-status
- 同步更新主规范文档:allocation-shelf-status、package-management、purchase-validation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-02 15:38:54 +08:00
parent 8efe79526a
commit 61155952a7
22 changed files with 677 additions and 44 deletions

View File

@@ -0,0 +1,45 @@
## 1. 数据库迁移
- [x] 1.1 创建迁移文件,为 `tb_shop_package_allocation` 新增 `shelf_status INT NOT NULL DEFAULT 1` 字段,添加字段注释"上架状态 1-上架 2-下架"
- [x] 1.2 执行迁移,确认字段已添加,存量记录 shelf_status 均为 1
## 2. Model 和 Store 层
- [x] 2.1 在 `internal/model/shop_package_allocation.go` 中为 `ShopPackageAllocation` 结构体新增 `ShelfStatus` 字段gorm tag + json tag
- [x] 2.2 在 `internal/store/postgres/shop_package_allocation_store.go` 中新增 `UpdateShelfStatus(ctx, id, shelfStatus, updaterID)` 方法
- [x] 2.3 在 `internal/store/postgres/package_allocation_store_interface.go`(或对应接口文件)中更新接口定义,添加 `UpdateShelfStatus` 方法签名
## 3. 分配上下架能力allocation-shelf-status
- [x] 3.1 在 `internal/service/shop_package_allocation/service.go` 中新增 `UpdateShelfStatus(ctx, allocationID, shelfStatus)` 方法,实现:套餐禁用时拒绝上架(查 Package.status、成功则调用 Store 更新
- [x] 3.2 在 `internal/service/shop_package_allocation/service.go``UpdateStatus()` 方法中加入所有者校验:代理用户需验证 `allocation.allocator_shop_id == caller.shopID`,不匹配则返回 `errors.CodeForbidden`
## 4. 套餐上下架接口角色分流package-management
- [x] 4.1 在 `internal/service/package/service.go``UpdateShelfStatus()` 方法中,增加角色判断:代理用户走分配记录路径(查找并更新 `allocation.shelf_status`),平台/超管走原有套餐路径(更新 `package.shelf_status`
- [x] 4.2 代理路径需处理:分配记录不存在时返回 "该套餐未分配给您,无法操作上下架"Package.status=禁用时拒绝上架
## 5. 代理查询套餐响应agent-available-packages
- [x] 5.1 在 `internal/service/package/service.go``toResponse()``toResponseWithAllocation()` 方法中,代理角色时将响应的 `ShelfStatus` 替换为 `allocation.ShelfStatus`(而非 `package.ShelfStatus`
- [x] 5.2 确认 `PackageStore.List()` 对代理用户的过滤逻辑:不再按 `package.shelf_status` 过滤代理看到的套餐不因平台下架而消失改为代理能看到自己所有已分配allocation.status=启用)的套餐
## 6. 购买校验逻辑package-purchase-validation
- [x] 6.1 在 `internal/service/purchase_validation/service.go` 的套餐状态校验中,增加购买场景判断:代理渠道购买时获取卖家代理的 `allocation.shelf_status` 进行校验,不检查 `package.shelf_status`;平台自营渠道保持检查 `package.shelf_status`
- [x] 6.2 确认 `PurchaseValidationService` 能获取到卖家代理的 shop_id通过 ctx 或参数传入),并调用 `ShopPackageAllocationStore.GetByShopAndPackage()` 获取 allocation 记录
## 7. DTO 更新
- [x] 7.1 在 `internal/model/dto/shop_package_allocation_dto.go` 中为 `ShopPackageAllocationResponse` 新增 `ShelfStatus` 字段(含 description 标签)
- [x] 7.2 新增 `UpdateShopPackageAllocationShelfStatusRequest` DTO 和对应 Params包含路由 ID + body用于 handler 绑定(如未来需要独立路由时备用,当前复用 package 接口的分流即可,此 DTO 可仅用于 service 内部)
## 8. 验证
- [x] 8.1 使用 PostgreSQL MCP 工具确认 `tb_shop_package_allocation` 表含 `shelf_status` 字段,存量数据默认值为 1
- [x] 8.2 调用 `PATCH /api/admin/packages/:id/shelf`(代理身份),验证只更新了 `allocation.shelf_status``tb_package.shelf_status` 不变
- [x] 8.3 调用 `PATCH /api/admin/packages/:id/shelf`(平台身份),验证更新了 `tb_package.shelf_status`allocation 不变
- [x] 8.4 代理下架套餐后,验证另一代理的同一套餐 shelf_status 不受影响
- [x] 8.5 代理下架套餐后,验证其客户下单时购买校验报错"套餐已下架"
- [x] 8.6 平台下架套餐后验证代理仍可在其列表中看到该套餐shelf_status 显示代理自己的状态)
- [x] 8.7 验证代理无法修改别人分配给自己的 allocation.status调用 `PUT /shop-package-allocations/:id/status` 应返回 403