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

@@ -58,11 +58,13 @@ func (s *PackageStore) List(ctx context.Context, opts *store.QueryOptions, filte
query := s.db.WithContext(ctx).Model(&model.Package{})
// 代理用户额外过滤:只能看到已分配的套餐
// 代理用户额外过滤:只能看到已分配allocation.status=启用)的套餐
// 不按 tb_package.shelf_status 过滤,代理套餐可见性由 allocation.shelf_status 决定
userType := middleware.GetUserTypeFromContext(ctx)
shopID := middleware.GetShopIDFromContext(ctx)
if userType == constants.UserTypeAgent && shopID > 0 {
query = query.Joins("INNER JOIN tb_shop_package_allocation ON tb_shop_package_allocation.package_id = tb_package.id").
isAgent := userType == constants.UserTypeAgent && shopID > 0
if isAgent {
query = query.Joins("INNER JOIN tb_shop_package_allocation ON tb_shop_package_allocation.package_id = tb_package.id AND tb_shop_package_allocation.deleted_at IS NULL").
Where("tb_shop_package_allocation.shop_id = ? AND tb_shop_package_allocation.status = ?",
shopID, constants.StatusEnabled)
}
@@ -77,7 +79,12 @@ func (s *PackageStore) List(ctx context.Context, opts *store.QueryOptions, filte
query = query.Where("tb_package.status = ?", status)
}
if shelfStatus, ok := filters["shelf_status"]; ok {
query = query.Where("tb_package.shelf_status = ?", shelfStatus)
if isAgent {
// 代理用户按自己的 allocation.shelf_status 过滤,不使用平台全局值
query = query.Where("tb_shop_package_allocation.shelf_status = ?", shelfStatus)
} else {
query = query.Where("tb_package.shelf_status = ?", shelfStatus)
}
}
if packageType, ok := filters["package_type"].(string); ok && packageType != "" {
query = query.Where("tb_package.package_type = ?", packageType)