Files
junhong_cmp_fiber/internal/store/postgres/enterprise_store.go
break 3b7b856e48
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m9s
企业授权增强与资产列表扩展
- 企业卡授权唯一约束:新增 DB 迁移(000154),卡级部分唯一索引防止同一张卡被多个企业同时持有,Service 层新增跨企业冲突检测
- 单卡列表新增 network_status 过滤参数
- 单卡/设备列表新增 asset_status、asset_status_name、generation 响应字段
- 单卡/设备列表新增企业维度过滤(authorized_enterprise_id、is_authorized_to_enterprise)及响应中企业授权信息(批量加载,无 N+1)
- 主钱包流水/退款列表新增 asset_identifier 精确过滤参数
- 企业卡授权/收回接口升级为三模式(list/range/filter),企业设备授权/收回升级为双模式(list/filter)
- 升级 sonic v1.14.2 → v1.15.2 以兼容 Go 1.26

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:23:03 +09:00

182 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package postgres
import (
"context"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/store"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
)
// EnterpriseStore 企业数据访问层
type EnterpriseStore struct {
db *gorm.DB
redis *redis.Client
}
// NewEnterpriseStore 创建企业 Store
func NewEnterpriseStore(db *gorm.DB, redis *redis.Client) *EnterpriseStore {
return &EnterpriseStore{
db: db,
redis: redis,
}
}
// Create 创建企业
func (s *EnterpriseStore) Create(ctx context.Context, enterprise *model.Enterprise) error {
return s.db.WithContext(ctx).Create(enterprise).Error
}
// GetByID 根据 ID 获取企业
func (s *EnterpriseStore) GetByID(ctx context.Context, id uint) (*model.Enterprise, error) {
var enterprise model.Enterprise
query := s.db.WithContext(ctx).Where("id = ?", id)
// 应用归属店铺数据权限过滤
query = middleware.ApplyOwnerShopFilter(ctx, query)
if err := query.First(&enterprise).Error; err != nil {
return nil, err
}
return &enterprise, nil
}
// GetByCode 根据企业编号获取企业
func (s *EnterpriseStore) GetByCode(ctx context.Context, code string) (*model.Enterprise, error) {
var enterprise model.Enterprise
query := s.db.WithContext(ctx).Where("enterprise_code = ?", code)
// 应用归属店铺数据权限过滤
query = middleware.ApplyOwnerShopFilter(ctx, query)
if err := query.First(&enterprise).Error; err != nil {
return nil, err
}
return &enterprise, nil
}
// Update 更新企业
func (s *EnterpriseStore) Update(ctx context.Context, enterprise *model.Enterprise) error {
return s.db.WithContext(ctx).Save(enterprise).Error
}
// Delete 软删除企业
func (s *EnterpriseStore) Delete(ctx context.Context, id uint) error {
return s.db.WithContext(ctx).Delete(&model.Enterprise{}, id).Error
}
// List 查询企业列表
func (s *EnterpriseStore) List(ctx context.Context, opts *store.QueryOptions, filters map[string]interface{}) ([]*model.Enterprise, int64, error) {
var enterprises []*model.Enterprise
var total int64
query := s.db.WithContext(ctx).Model(&model.Enterprise{})
// 应用归属店铺数据权限过滤
query = middleware.ApplyOwnerShopFilter(ctx, query)
// 应用过滤条件
if enterpriseName, ok := filters["enterprise_name"].(string); ok && enterpriseName != "" {
query = query.Where("enterprise_name LIKE ?", "%"+enterpriseName+"%")
}
if enterpriseCode, ok := filters["enterprise_code"].(string); ok && enterpriseCode != "" {
query = query.Where("enterprise_code = ?", enterpriseCode)
}
if ownerShopID, ok := filters["owner_shop_id"].(uint); ok {
query = query.Where("owner_shop_id = ?", ownerShopID)
}
if status, ok := filters["status"].(int); ok {
query = query.Where("status = ?", status)
}
// 计算总数
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
// 分页
if opts == nil {
opts = &store.QueryOptions{
Page: 1,
PageSize: constants.DefaultPageSize,
}
}
offset := (opts.Page - 1) * opts.PageSize
query = query.Offset(offset).Limit(opts.PageSize)
// 排序
if opts.OrderBy != "" {
query = query.Order(opts.OrderBy)
} else {
query = query.Order("created_at DESC")
}
// 查询
if err := query.Find(&enterprises).Error; err != nil {
return nil, 0, err
}
return enterprises, total, nil
}
// GetByOwnerShopID 根据归属店铺 ID 查询企业列表
func (s *EnterpriseStore) GetByOwnerShopID(ctx context.Context, ownerShopID uint) ([]*model.Enterprise, error) {
var enterprises []*model.Enterprise
query := s.db.WithContext(ctx).Where("owner_shop_id = ?", ownerShopID)
// 应用归属店铺数据权限过滤
query = middleware.ApplyOwnerShopFilter(ctx, query)
if err := query.Find(&enterprises).Error; err != nil {
return nil, err
}
return enterprises, nil
}
// GetPlatformEnterprises 获取平台直属企业列表owner_shop_id 为 NULL
func (s *EnterpriseStore) GetPlatformEnterprises(ctx context.Context) ([]*model.Enterprise, error) {
var enterprises []*model.Enterprise
query := s.db.WithContext(ctx).Where("owner_shop_id IS NULL")
// 应用归属店铺数据权限过滤(代理用户无法看到平台直属企业)
query = middleware.ApplyOwnerShopFilter(ctx, query)
if err := query.Find(&enterprises).Error; err != nil {
return nil, err
}
return enterprises, nil
}
// GetByIDs 批量查询企业
func (s *EnterpriseStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.Enterprise, error) {
if len(ids) == 0 {
return []*model.Enterprise{}, nil
}
var enterprises []*model.Enterprise
query := s.db.WithContext(ctx).Where("id IN ?", ids)
// 应用归属店铺数据权限过滤
query = middleware.ApplyOwnerShopFilter(ctx, query)
if err := query.Find(&enterprises).Error; err != nil {
return nil, err
}
return enterprises, nil
}
// GetNameMapByIDs 批量查询企业名称映射(不受数据权限过滤)
// 专用于列表响应中回填企业名称,企业 ID 来自已过滤的授权记录,无需二次权限限制
func (s *EnterpriseStore) GetNameMapByIDs(ctx context.Context, ids []uint) (map[uint]string, error) {
if len(ids) == 0 {
return make(map[uint]string), nil
}
var rows []struct {
ID uint
EnterpriseName string
}
err := s.db.WithContext(ctx).Model(&model.Enterprise{}).
Select("id, enterprise_name").
Where("id IN ? AND deleted_at IS NULL", ids).
Scan(&rows).Error
if err != nil {
return nil, err
}
result := make(map[uint]string, len(rows))
for _, r := range rows {
result[r.ID] = r.EnterpriseName
}
return result, nil
}