feat: 实现企业卡授权和授权记录管理功能
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m9s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m9s
主要功能: - 添加企业卡授权/回收接口 (POST /enterprises/:id/allocate-cards, recall-cards) - 添加授权记录管理接口 (GET/PUT /authorizations) - 实现代理用户数据权限过滤(只能查看自己店铺下企业的授权记录) - 添加 GORM callback 支持授权记录表的数据权限过滤 技术改进: - 原生 SQL 查询手动添加数据权限过滤(ListWithJoin, GetByIDWithJoin) - 移除卡授权预检接口(allocate-cards/preview),保留内部方法 - 完善单元测试和集成测试覆盖
This commit is contained in:
@@ -2,8 +2,12 @@ package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
pkgGorm "github.com/break/junhong_cmp_fiber/pkg/gorm"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -31,25 +35,23 @@ func (s *EnterpriseCardAuthorizationStore) BatchCreate(ctx context.Context, auth
|
||||
return s.db.WithContext(ctx).CreateInBatches(auths, 100).Error
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) UpdateStatus(ctx context.Context, enterpriseID, cardID uint, status int) error {
|
||||
return s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND iot_card_id = ?", enterpriseID, cardID).
|
||||
Update("status", status).Error
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) BatchUpdateStatus(ctx context.Context, enterpriseID uint, cardIDs []uint, status int) error {
|
||||
func (s *EnterpriseCardAuthorizationStore) RevokeAuthorizations(ctx context.Context, enterpriseID uint, cardIDs []uint, revokedBy uint) error {
|
||||
if len(cardIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
now := time.Now()
|
||||
return s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND iot_card_id IN ?", enterpriseID, cardIDs).
|
||||
Update("status", status).Error
|
||||
Where("enterprise_id = ? AND card_id IN ? AND revoked_at IS NULL", enterpriseID, cardIDs).
|
||||
Updates(map[string]interface{}{
|
||||
"revoked_by": revokedBy,
|
||||
"revoked_at": now,
|
||||
}).Error
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) GetByEnterpriseAndCard(ctx context.Context, enterpriseID, cardID uint) (*model.EnterpriseCardAuthorization, error) {
|
||||
var auth model.EnterpriseCardAuthorization
|
||||
err := s.db.WithContext(ctx).
|
||||
Where("enterprise_id = ? AND iot_card_id = ?", enterpriseID, cardID).
|
||||
Where("enterprise_id = ? AND card_id = ?", enterpriseID, cardID).
|
||||
First(&auth).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -57,11 +59,11 @@ func (s *EnterpriseCardAuthorizationStore) GetByEnterpriseAndCard(ctx context.Co
|
||||
return &auth, nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) ListByEnterprise(ctx context.Context, enterpriseID uint, status *int) ([]*model.EnterpriseCardAuthorization, error) {
|
||||
func (s *EnterpriseCardAuthorizationStore) ListByEnterprise(ctx context.Context, enterpriseID uint, includeRevoked bool) ([]*model.EnterpriseCardAuthorization, error) {
|
||||
var auths []*model.EnterpriseCardAuthorization
|
||||
query := s.db.WithContext(ctx).Where("enterprise_id = ?", enterpriseID)
|
||||
if status != nil {
|
||||
query = query.Where("status = ?", *status)
|
||||
if !includeRevoked {
|
||||
query = query.Where("revoked_at IS NULL")
|
||||
}
|
||||
if err := query.Find(&auths).Error; err != nil {
|
||||
return nil, err
|
||||
@@ -69,28 +71,326 @@ func (s *EnterpriseCardAuthorizationStore) ListByEnterprise(ctx context.Context,
|
||||
return auths, nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) ListCardIDsByEnterprise(ctx context.Context, enterpriseID uint) ([]uint, error) {
|
||||
func (s *EnterpriseCardAuthorizationStore) ListByCards(ctx context.Context, cardIDs []uint, includeRevoked bool) ([]*model.EnterpriseCardAuthorization, error) {
|
||||
if len(cardIDs) == 0 {
|
||||
return []*model.EnterpriseCardAuthorization{}, nil
|
||||
}
|
||||
var auths []*model.EnterpriseCardAuthorization
|
||||
query := s.db.WithContext(ctx).Where("card_id IN ?", cardIDs)
|
||||
if !includeRevoked {
|
||||
query = query.Where("revoked_at IS NULL")
|
||||
}
|
||||
if err := query.Find(&auths).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return auths, nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) GetActiveAuthorizedCardIDs(ctx context.Context, enterpriseID uint) ([]uint, error) {
|
||||
var cardIDs []uint
|
||||
err := s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND status = 1", enterpriseID).
|
||||
Pluck("iot_card_id", &cardIDs).Error
|
||||
Where("enterprise_id = ? AND revoked_at IS NULL", enterpriseID).
|
||||
Pluck("card_id", &cardIDs).Error
|
||||
return cardIDs, err
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) CheckAuthorizationExists(ctx context.Context, enterpriseID, cardID uint) (bool, error) {
|
||||
var count int64
|
||||
err := s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND card_id = ? AND revoked_at IS NULL", enterpriseID, cardID).
|
||||
Count(&count).Error
|
||||
return count > 0, err
|
||||
}
|
||||
|
||||
type AuthorizationListOptions struct {
|
||||
EnterpriseID *uint
|
||||
AuthorizerType *int
|
||||
AuthorizedBy *uint
|
||||
IncludeRevoked bool
|
||||
CardIDs []uint
|
||||
Offset int
|
||||
Limit int
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) ListWithOptions(ctx context.Context, opts AuthorizationListOptions) ([]*model.EnterpriseCardAuthorization, int64, error) {
|
||||
var auths []*model.EnterpriseCardAuthorization
|
||||
query := s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{})
|
||||
|
||||
if opts.EnterpriseID != nil {
|
||||
query = query.Where("enterprise_id = ?", *opts.EnterpriseID)
|
||||
}
|
||||
if opts.AuthorizerType != nil {
|
||||
query = query.Where("authorizer_type = ?", *opts.AuthorizerType)
|
||||
}
|
||||
if opts.AuthorizedBy != nil {
|
||||
query = query.Where("authorized_by = ?", *opts.AuthorizedBy)
|
||||
}
|
||||
if !opts.IncludeRevoked {
|
||||
query = query.Where("revoked_at IS NULL")
|
||||
}
|
||||
if len(opts.CardIDs) > 0 {
|
||||
query = query.Where("card_id IN ?", opts.CardIDs)
|
||||
}
|
||||
|
||||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if opts.Limit > 0 {
|
||||
query = query.Limit(opts.Limit).Offset(opts.Offset)
|
||||
}
|
||||
|
||||
if err := query.Order("id DESC").Find(&auths).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return auths, total, nil
|
||||
}
|
||||
|
||||
// GetActiveAuthsByCardIDs 获取指定企业和卡ID列表的有效授权记录(返回 map[cardID]bool)
|
||||
func (s *EnterpriseCardAuthorizationStore) GetActiveAuthsByCardIDs(ctx context.Context, enterpriseID uint, cardIDs []uint) (map[uint]bool, error) {
|
||||
if len(cardIDs) == 0 {
|
||||
return make(map[uint]bool), nil
|
||||
}
|
||||
var auths []model.EnterpriseCardAuthorization
|
||||
err := s.db.WithContext(ctx).
|
||||
Where("enterprise_id = ? AND iot_card_id IN ? AND status = 1", enterpriseID, cardIDs).
|
||||
Find(&auths).Error
|
||||
var authCardIDs []uint
|
||||
err := s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND card_id IN ? AND revoked_at IS NULL", enterpriseID, cardIDs).
|
||||
Pluck("card_id", &authCardIDs).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make(map[uint]bool)
|
||||
for _, auth := range auths {
|
||||
result[auth.IotCardID] = true
|
||||
for _, cardID := range authCardIDs {
|
||||
result[cardID] = true
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// BatchUpdateStatus 批量更新授权状态(回收授权:设置 revoked_at)
|
||||
func (s *EnterpriseCardAuthorizationStore) BatchUpdateStatus(ctx context.Context, enterpriseID uint, cardIDs []uint, status int) error {
|
||||
if len(cardIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
// status 0 表示回收(设置 revoked_at)
|
||||
if status == 0 {
|
||||
now := time.Now()
|
||||
return s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND card_id IN ? AND revoked_at IS NULL", enterpriseID, cardIDs).
|
||||
Update("revoked_at", now).Error
|
||||
}
|
||||
// 其他状态暂不处理
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListCardIDsByEnterprise 获取企业的有效授权卡ID列表
|
||||
func (s *EnterpriseCardAuthorizationStore) ListCardIDsByEnterprise(ctx context.Context, enterpriseID uint) ([]uint, error) {
|
||||
var cardIDs []uint
|
||||
err := s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("enterprise_id = ? AND revoked_at IS NULL", enterpriseID).
|
||||
Pluck("card_id", &cardIDs).Error
|
||||
return cardIDs, err
|
||||
}
|
||||
|
||||
type AuthorizationWithJoinListOptions struct {
|
||||
EnterpriseID *uint
|
||||
ICCID string
|
||||
AuthorizerType *int
|
||||
Status *int
|
||||
StartTime *time.Time
|
||||
EndTime *time.Time
|
||||
Offset int
|
||||
Limit int
|
||||
}
|
||||
|
||||
type AuthorizationWithJoin struct {
|
||||
ID uint `gorm:"column:id"`
|
||||
EnterpriseID uint `gorm:"column:enterprise_id"`
|
||||
EnterpriseName string `gorm:"column:enterprise_name"`
|
||||
CardID uint `gorm:"column:card_id"`
|
||||
ICCID string `gorm:"column:iccid"`
|
||||
MSISDN string `gorm:"column:msisdn"`
|
||||
AuthorizedBy uint `gorm:"column:authorized_by"`
|
||||
AuthorizerName string `gorm:"column:authorizer_name"`
|
||||
AuthorizerType int `gorm:"column:authorizer_type"`
|
||||
AuthorizedAt time.Time `gorm:"column:authorized_at"`
|
||||
RevokedBy *uint `gorm:"column:revoked_by"`
|
||||
RevokerName *string `gorm:"column:revoker_name"`
|
||||
RevokedAt *time.Time `gorm:"column:revoked_at"`
|
||||
Remark string `gorm:"column:remark"`
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) ListWithJoin(ctx context.Context, opts AuthorizationWithJoinListOptions) ([]AuthorizationWithJoin, int64, error) {
|
||||
baseQuery := `
|
||||
FROM tb_enterprise_card_authorization a
|
||||
LEFT JOIN tb_enterprise e ON a.enterprise_id = e.id AND e.deleted_at IS NULL
|
||||
LEFT JOIN tb_iot_card c ON a.card_id = c.id AND c.deleted_at IS NULL
|
||||
LEFT JOIN tb_account acc1 ON a.authorized_by = acc1.id AND acc1.deleted_at IS NULL
|
||||
LEFT JOIN tb_account acc2 ON a.revoked_by = acc2.id AND acc2.deleted_at IS NULL
|
||||
WHERE a.deleted_at IS NULL
|
||||
`
|
||||
|
||||
args := []interface{}{}
|
||||
|
||||
// 数据权限过滤(原生 SQL 需要手动处理)
|
||||
// 检查是否跳过数据权限过滤
|
||||
if skip, ok := ctx.Value(pkgGorm.SkipDataPermissionKey).(bool); !ok || !skip {
|
||||
userType := middleware.GetUserTypeFromContext(ctx)
|
||||
// 超级管理员和平台用户跳过过滤
|
||||
if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform {
|
||||
if userType == constants.UserTypeAgent {
|
||||
shopID := middleware.GetShopIDFromContext(ctx)
|
||||
if shopID == 0 {
|
||||
// 代理用户没有 shop_id,返回空结果
|
||||
return []AuthorizationWithJoin{}, 0, nil
|
||||
}
|
||||
// 只能看到自己店铺下企业的授权记录(不包含下级店铺)
|
||||
baseQuery += " AND a.enterprise_id IN (SELECT id FROM tb_enterprise WHERE owner_shop_id = ? AND deleted_at IS NULL)"
|
||||
args = append(args, shopID)
|
||||
} else if userType == constants.UserTypeEnterprise {
|
||||
enterpriseID := middleware.GetEnterpriseIDFromContext(ctx)
|
||||
if enterpriseID == 0 {
|
||||
return []AuthorizationWithJoin{}, 0, nil
|
||||
}
|
||||
baseQuery += " AND a.enterprise_id = ?"
|
||||
args = append(args, enterpriseID)
|
||||
} else {
|
||||
// 其他用户类型(个人客户等)不应访问授权记录
|
||||
return []AuthorizationWithJoin{}, 0, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if opts.EnterpriseID != nil {
|
||||
baseQuery += " AND a.enterprise_id = ?"
|
||||
args = append(args, *opts.EnterpriseID)
|
||||
}
|
||||
if opts.ICCID != "" {
|
||||
baseQuery += " AND c.iccid LIKE ?"
|
||||
args = append(args, "%"+opts.ICCID+"%")
|
||||
}
|
||||
if opts.AuthorizerType != nil {
|
||||
baseQuery += " AND a.authorizer_type = ?"
|
||||
args = append(args, *opts.AuthorizerType)
|
||||
}
|
||||
if opts.Status != nil {
|
||||
if *opts.Status == 1 {
|
||||
baseQuery += " AND a.revoked_at IS NULL"
|
||||
} else {
|
||||
baseQuery += " AND a.revoked_at IS NOT NULL"
|
||||
}
|
||||
}
|
||||
if opts.StartTime != nil {
|
||||
baseQuery += " AND a.authorized_at >= ?"
|
||||
args = append(args, *opts.StartTime)
|
||||
}
|
||||
if opts.EndTime != nil {
|
||||
baseQuery += " AND a.authorized_at < ?"
|
||||
args = append(args, *opts.EndTime)
|
||||
}
|
||||
|
||||
var total int64
|
||||
countSQL := "SELECT COUNT(*) " + baseQuery
|
||||
if err := s.db.WithContext(ctx).Raw(countSQL, args...).Scan(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
selectSQL := `
|
||||
SELECT
|
||||
a.id, a.enterprise_id, COALESCE(e.enterprise_name, '') as enterprise_name,
|
||||
a.card_id, COALESCE(c.iccid, '') as iccid, COALESCE(c.msisdn, '') as msisdn,
|
||||
a.authorized_by, COALESCE(acc1.username, '') as authorizer_name,
|
||||
a.authorizer_type, a.authorized_at,
|
||||
a.revoked_by, acc2.username as revoker_name, a.revoked_at,
|
||||
COALESCE(a.remark, '') as remark
|
||||
` + baseQuery + " ORDER BY a.id DESC"
|
||||
|
||||
if opts.Limit > 0 {
|
||||
selectSQL += " LIMIT ? OFFSET ?"
|
||||
args = append(args, opts.Limit, opts.Offset)
|
||||
}
|
||||
|
||||
var results []AuthorizationWithJoin
|
||||
if err := s.db.WithContext(ctx).Raw(selectSQL, args...).Scan(&results).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return results, total, nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) GetByIDWithJoin(ctx context.Context, id uint) (*AuthorizationWithJoin, error) {
|
||||
baseSQL := `
|
||||
SELECT
|
||||
a.id, a.enterprise_id, COALESCE(e.enterprise_name, '') as enterprise_name,
|
||||
a.card_id, COALESCE(c.iccid, '') as iccid, COALESCE(c.msisdn, '') as msisdn,
|
||||
a.authorized_by, COALESCE(acc1.username, '') as authorizer_name,
|
||||
a.authorizer_type, a.authorized_at,
|
||||
a.revoked_by, acc2.username as revoker_name, a.revoked_at,
|
||||
COALESCE(a.remark, '') as remark
|
||||
FROM tb_enterprise_card_authorization a
|
||||
LEFT JOIN tb_enterprise e ON a.enterprise_id = e.id AND e.deleted_at IS NULL
|
||||
LEFT JOIN tb_iot_card c ON a.card_id = c.id AND c.deleted_at IS NULL
|
||||
LEFT JOIN tb_account acc1 ON a.authorized_by = acc1.id AND acc1.deleted_at IS NULL
|
||||
LEFT JOIN tb_account acc2 ON a.revoked_by = acc2.id AND acc2.deleted_at IS NULL
|
||||
WHERE a.id = ? AND a.deleted_at IS NULL
|
||||
`
|
||||
|
||||
args := []interface{}{id}
|
||||
|
||||
// 数据权限过滤(原生 SQL 需要手动处理)
|
||||
if skip, ok := ctx.Value(pkgGorm.SkipDataPermissionKey).(bool); !ok || !skip {
|
||||
userType := middleware.GetUserTypeFromContext(ctx)
|
||||
if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform {
|
||||
if userType == constants.UserTypeAgent {
|
||||
shopID := middleware.GetShopIDFromContext(ctx)
|
||||
if shopID == 0 {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
baseSQL += " AND a.enterprise_id IN (SELECT id FROM tb_enterprise WHERE owner_shop_id = ? AND deleted_at IS NULL)"
|
||||
args = append(args, shopID)
|
||||
} else if userType == constants.UserTypeEnterprise {
|
||||
enterpriseID := middleware.GetEnterpriseIDFromContext(ctx)
|
||||
if enterpriseID == 0 {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
baseSQL += " AND a.enterprise_id = ?"
|
||||
args = append(args, enterpriseID)
|
||||
} else {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result AuthorizationWithJoin
|
||||
if err := s.db.WithContext(ctx).Raw(baseSQL, args...).Scan(&result).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if result.ID == 0 {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) UpdateRemark(ctx context.Context, id uint, remark string) error {
|
||||
result := s.db.WithContext(ctx).Model(&model.EnterpriseCardAuthorization{}).
|
||||
Where("id = ?", id).
|
||||
Update("remark", remark)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseCardAuthorizationStore) GetByID(ctx context.Context, id uint) (*model.EnterpriseCardAuthorization, error) {
|
||||
var auth model.EnterpriseCardAuthorization
|
||||
err := s.db.WithContext(ctx).Where("id = ?", id).First(&auth).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &auth, nil
|
||||
}
|
||||
|
||||
@@ -49,6 +49,17 @@ func (s *IotCardStore) GetByICCID(ctx context.Context, iccid string) (*model.Iot
|
||||
return &card, nil
|
||||
}
|
||||
|
||||
func (s *IotCardStore) GetByIDs(ctx context.Context, ids []uint) ([]*model.IotCard, error) {
|
||||
if len(ids) == 0 {
|
||||
return []*model.IotCard{}, nil
|
||||
}
|
||||
var cards []*model.IotCard
|
||||
if err := s.db.WithContext(ctx).Where("id IN ?", ids).Find(&cards).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cards, nil
|
||||
}
|
||||
|
||||
func (s *IotCardStore) ExistsByICCID(ctx context.Context, iccid string) (bool, error) {
|
||||
var count int64
|
||||
if err := s.db.WithContext(ctx).Model(&model.IotCard{}).Where("iccid = ?", iccid).Count(&count).Error; err != nil {
|
||||
@@ -84,6 +95,89 @@ func (s *IotCardStore) Delete(ctx context.Context, id uint) error {
|
||||
return s.db.WithContext(ctx).Delete(&model.IotCard{}, id).Error
|
||||
}
|
||||
|
||||
func (s *IotCardStore) List(ctx context.Context, opts *store.QueryOptions, filters map[string]any) ([]*model.IotCard, int64, error) {
|
||||
var cards []*model.IotCard
|
||||
var total int64
|
||||
|
||||
query := s.db.WithContext(ctx).Model(&model.IotCard{})
|
||||
|
||||
// 企业用户特殊处理:只能看到授权给自己的卡
|
||||
if enterpriseID, ok := filters["authorized_enterprise_id"].(uint); ok && enterpriseID > 0 {
|
||||
query = query.Where("id IN (?)",
|
||||
s.db.Table("tb_enterprise_card_authorization").
|
||||
Select("card_id").
|
||||
Where("enterprise_id = ? AND revoked_at IS NULL AND deleted_at IS NULL", enterpriseID))
|
||||
}
|
||||
|
||||
// 基础过滤条件
|
||||
if status, ok := filters["status"].(int); ok && status > 0 {
|
||||
query = query.Where("status = ?", status)
|
||||
}
|
||||
if carrierID, ok := filters["carrier_id"].(uint); ok && carrierID > 0 {
|
||||
query = query.Where("carrier_id = ?", carrierID)
|
||||
}
|
||||
if shopID, ok := filters["shop_id"].(uint); ok && shopID > 0 {
|
||||
query = query.Where("shop_id = ?", shopID)
|
||||
}
|
||||
if iccid, ok := filters["iccid"].(string); ok && iccid != "" {
|
||||
query = query.Where("iccid LIKE ?", "%"+iccid+"%")
|
||||
}
|
||||
if msisdn, ok := filters["msisdn"].(string); ok && msisdn != "" {
|
||||
query = query.Where("msisdn LIKE ?", "%"+msisdn+"%")
|
||||
}
|
||||
if batchNo, ok := filters["batch_no"].(string); ok && batchNo != "" {
|
||||
query = query.Where("batch_no = ?", batchNo)
|
||||
}
|
||||
if packageID, ok := filters["package_id"].(uint); ok && packageID > 0 {
|
||||
query = query.Where("id IN (?)",
|
||||
s.db.Table("tb_package_usage").
|
||||
Select("iot_card_id").
|
||||
Where("package_id = ? AND deleted_at IS NULL", packageID))
|
||||
}
|
||||
if isDistributed, ok := filters["is_distributed"].(bool); ok {
|
||||
if isDistributed {
|
||||
query = query.Where("shop_id IS NOT NULL")
|
||||
} else {
|
||||
query = query.Where("shop_id IS NULL")
|
||||
}
|
||||
}
|
||||
if iccidStart, ok := filters["iccid_start"].(string); ok && iccidStart != "" {
|
||||
query = query.Where("iccid >= ?", iccidStart)
|
||||
}
|
||||
if iccidEnd, ok := filters["iccid_end"].(string); ok && iccidEnd != "" {
|
||||
query = query.Where("iccid <= ?", iccidEnd)
|
||||
}
|
||||
|
||||
// 统计总数
|
||||
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(&cards).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return cards, total, nil
|
||||
}
|
||||
|
||||
func (s *IotCardStore) ListStandalone(ctx context.Context, opts *store.QueryOptions, filters map[string]any) ([]*model.IotCard, int64, error) {
|
||||
var cards []*model.IotCard
|
||||
var total int64
|
||||
@@ -251,10 +345,32 @@ func (s *IotCardStore) GetBoundCardIDs(ctx context.Context, cardIDs []uint) ([]u
|
||||
if len(cardIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var boundCardIDs []uint
|
||||
var boundIDs []uint
|
||||
err := s.db.WithContext(ctx).Model(&model.DeviceSimBinding{}).
|
||||
Select("iot_card_id").
|
||||
Where("iot_card_id IN ? AND bind_status = ?", cardIDs, 1).
|
||||
Pluck("iot_card_id", &boundCardIDs).Error
|
||||
return boundCardIDs, err
|
||||
Pluck("iot_card_id", &boundIDs).Error
|
||||
return boundIDs, err
|
||||
}
|
||||
|
||||
func (s *IotCardStore) GetByIDsWithEnterpriseFilter(ctx context.Context, cardIDs []uint, enterpriseID *uint) ([]*model.IotCard, error) {
|
||||
if len(cardIDs) == 0 {
|
||||
return []*model.IotCard{}, nil
|
||||
}
|
||||
query := s.db.WithContext(ctx).Model(&model.IotCard{})
|
||||
|
||||
if enterpriseID != nil && *enterpriseID > 0 {
|
||||
query = query.Where("id IN (?) AND id IN (?)",
|
||||
cardIDs,
|
||||
s.db.Table("tb_enterprise_card_authorization").
|
||||
Select("card_id").
|
||||
Where("enterprise_id = ? AND revoked_at IS NULL AND deleted_at IS NULL", *enterpriseID))
|
||||
} else {
|
||||
query = query.Where("id IN ?", cardIDs)
|
||||
}
|
||||
|
||||
var cards []*model.IotCard
|
||||
if err := query.Find(&cards).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cards, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user