feat: 新增代理分配套餐上架状态(shelf_status)功能
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m56s
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:
@@ -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)
|
||||
|
||||
@@ -32,6 +32,16 @@ func (s *ShopPackageAllocationStore) GetByID(ctx context.Context, id uint) (*mod
|
||||
return &allocation, nil
|
||||
}
|
||||
|
||||
// GetByIDForSystem 根据ID获取分配记录(不应用数据权限过滤)
|
||||
// 用于 Service 层需要先查到记录再做业务权限校验的场景
|
||||
func (s *ShopPackageAllocationStore) GetByIDForSystem(ctx context.Context, id uint) (*model.ShopPackageAllocation, error) {
|
||||
var allocation model.ShopPackageAllocation
|
||||
if err := s.db.WithContext(ctx).First(&allocation, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &allocation, nil
|
||||
}
|
||||
|
||||
func (s *ShopPackageAllocationStore) GetByShopAndPackage(ctx context.Context, shopID, packageID uint) (*model.ShopPackageAllocation, error) {
|
||||
var allocation model.ShopPackageAllocation
|
||||
query := s.db.WithContext(ctx).Where("shop_id = ? AND package_id = ?", shopID, packageID)
|
||||
@@ -43,6 +53,18 @@ func (s *ShopPackageAllocationStore) GetByShopAndPackage(ctx context.Context, sh
|
||||
return &allocation, nil
|
||||
}
|
||||
|
||||
// GetByShopAndPackageForSystem 根据店铺和套餐查询分配记录(不应用数据权限过滤)
|
||||
// 用于系统内部查询场景(如购买校验),避免因 ctx 权限限制导致无法查到目标记录
|
||||
func (s *ShopPackageAllocationStore) GetByShopAndPackageForSystem(ctx context.Context, shopID, packageID uint) (*model.ShopPackageAllocation, error) {
|
||||
var allocation model.ShopPackageAllocation
|
||||
if err := s.db.WithContext(ctx).
|
||||
Where("shop_id = ? AND package_id = ?", shopID, packageID).
|
||||
First(&allocation).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &allocation, nil
|
||||
}
|
||||
|
||||
func (s *ShopPackageAllocationStore) Update(ctx context.Context, allocation *model.ShopPackageAllocation) error {
|
||||
return s.db.WithContext(ctx).Save(allocation).Error
|
||||
}
|
||||
@@ -106,6 +128,17 @@ func (s *ShopPackageAllocationStore) UpdateStatus(ctx context.Context, id uint,
|
||||
}).Error
|
||||
}
|
||||
|
||||
// UpdateShelfStatus 更新分配记录的上下架状态
|
||||
func (s *ShopPackageAllocationStore) UpdateShelfStatus(ctx context.Context, id uint, shelfStatus int, updater uint) error {
|
||||
return s.db.WithContext(ctx).
|
||||
Model(&model.ShopPackageAllocation{}).
|
||||
Where("id = ?", id).
|
||||
Updates(map[string]interface{}{
|
||||
"shelf_status": shelfStatus,
|
||||
"updater": updater,
|
||||
}).Error
|
||||
}
|
||||
|
||||
func (s *ShopPackageAllocationStore) GetByShopID(ctx context.Context, shopID uint) ([]*model.ShopPackageAllocation, error) {
|
||||
var allocations []*model.ShopPackageAllocation
|
||||
query := s.db.WithContext(ctx).Where("shop_id = ? AND status = 1", shopID)
|
||||
|
||||
Reference in New Issue
Block a user