修复企业授权报错的问题
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m57s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m57s
This commit is contained in:
@@ -2,6 +2,7 @@ package enterprise_device
|
||||
|
||||
import (
|
||||
"context"
|
||||
stderrors "errors"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -74,8 +76,8 @@ func (s *Service) AllocateDevices(ctx context.Context, enterpriseID uint, req *d
|
||||
currentShopID := middleware.GetShopIDFromContext(ctx)
|
||||
userType := middleware.GetUserTypeFromContext(ctx)
|
||||
|
||||
// 检查已授权的设备
|
||||
existingAuths, err := s.enterpriseDeviceAuthStore.GetActiveAuthsByDeviceIDs(ctx, enterpriseID, deviceIDs)
|
||||
// 检查设备是否已存在有效授权(不区分企业)
|
||||
activeAuthEnterpriseMap, err := s.enterpriseDeviceAuthStore.GetActiveAuthEnterpriseByDeviceIDs(ctx, deviceIDs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "查询已有授权失败")
|
||||
}
|
||||
@@ -86,7 +88,17 @@ func (s *Service) AllocateDevices(ctx context.Context, enterpriseID uint, req *d
|
||||
}
|
||||
|
||||
devicesToAllocate := make([]*model.Device, 0)
|
||||
seenDeviceNos := make(map[string]struct{}, len(req.DeviceNos))
|
||||
for _, deviceNo := range req.DeviceNos {
|
||||
if _, exists := seenDeviceNos[deviceNo]; exists {
|
||||
resp.FailedItems = append(resp.FailedItems, dto.FailedDeviceItem{
|
||||
VirtualNo: deviceNo,
|
||||
Reason: "请求中设备号重复",
|
||||
})
|
||||
continue
|
||||
}
|
||||
seenDeviceNos[deviceNo] = struct{}{}
|
||||
|
||||
device, exists := deviceMap[deviceNo]
|
||||
if !exists {
|
||||
resp.FailedItems = append(resp.FailedItems, dto.FailedDeviceItem{
|
||||
@@ -116,11 +128,15 @@ func (s *Service) AllocateDevices(ctx context.Context, enterpriseID uint, req *d
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否已授权
|
||||
if existingAuths[device.ID] {
|
||||
// 检查是否已授权(同企业 / 其他企业)
|
||||
if authEnterpriseID, exists := activeAuthEnterpriseMap[device.ID]; exists {
|
||||
reason := "设备已授权给其他企业"
|
||||
if authEnterpriseID == enterpriseID {
|
||||
reason = "设备已授权给此企业"
|
||||
}
|
||||
resp.FailedItems = append(resp.FailedItems, dto.FailedDeviceItem{
|
||||
VirtualNo: deviceNo,
|
||||
Reason: "设备已授权给此企业",
|
||||
Reason: reason,
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -134,38 +150,58 @@ func (s *Service) AllocateDevices(ctx context.Context, enterpriseID uint, req *d
|
||||
now := time.Now()
|
||||
authorizerType := userType
|
||||
|
||||
// 1. 创建设备授权记录
|
||||
deviceAuths := make([]*model.EnterpriseDeviceAuthorization, 0, len(devicesToAllocate))
|
||||
// 1. 创建设备授权记录(逐条处理,避免并发冲突导致整批失败)
|
||||
deviceAuthIDMap := make(map[uint]uint, len(devicesToAllocate))
|
||||
successDevices := make([]*model.Device, 0, len(devicesToAllocate))
|
||||
for _, device := range devicesToAllocate {
|
||||
deviceAuths = append(deviceAuths, &model.EnterpriseDeviceAuthorization{
|
||||
deviceAuth := &model.EnterpriseDeviceAuthorization{
|
||||
EnterpriseID: enterpriseID,
|
||||
DeviceID: device.ID,
|
||||
AuthorizedBy: currentUserID,
|
||||
AuthorizedAt: now,
|
||||
AuthorizerType: authorizerType,
|
||||
Remark: req.Remark,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Create(deviceAuths).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "创建设备授权记录失败")
|
||||
}
|
||||
if err := tx.Create(deviceAuth).Error; err != nil {
|
||||
if isUniqueConstraintViolation(err, "uq_active_device_auth") {
|
||||
reason := "设备已授权给其他企业"
|
||||
|
||||
// 构建设备ID到授权ID的映射
|
||||
deviceAuthIDMap := make(map[uint]uint)
|
||||
for _, auth := range deviceAuths {
|
||||
deviceAuthIDMap[auth.DeviceID] = auth.ID
|
||||
var existingAuth model.EnterpriseDeviceAuthorization
|
||||
queryErr := tx.Select("enterprise_id").
|
||||
Where("device_id = ? AND revoked_at IS NULL", device.ID).
|
||||
First(&existingAuth).Error
|
||||
if queryErr == nil && existingAuth.EnterpriseID == enterpriseID {
|
||||
reason = "设备已授权给此企业"
|
||||
}
|
||||
if queryErr != nil && !stderrors.Is(queryErr, gorm.ErrRecordNotFound) {
|
||||
return errors.Wrap(errors.CodeInternalError, queryErr, "查询冲突授权记录失败")
|
||||
}
|
||||
|
||||
resp.FailedItems = append(resp.FailedItems, dto.FailedDeviceItem{
|
||||
VirtualNo: device.VirtualNo,
|
||||
Reason: reason,
|
||||
})
|
||||
continue
|
||||
}
|
||||
return errors.Wrap(errors.CodeInternalError, err, "创建设备授权记录失败")
|
||||
}
|
||||
|
||||
deviceAuthIDMap[device.ID] = deviceAuth.ID
|
||||
successDevices = append(successDevices, device)
|
||||
}
|
||||
|
||||
// 2. 查询所有设备绑定的卡
|
||||
deviceIDsToQuery := make([]uint, 0, len(devicesToAllocate))
|
||||
for _, device := range devicesToAllocate {
|
||||
deviceIDsToQuery := make([]uint, 0, len(successDevices))
|
||||
for _, device := range successDevices {
|
||||
deviceIDsToQuery = append(deviceIDsToQuery, device.ID)
|
||||
}
|
||||
|
||||
var bindings []model.DeviceSimBinding
|
||||
if err := tx.Where("device_id IN ? AND bind_status = 1", deviceIDsToQuery).Find(&bindings).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "查询设备绑定卡失败")
|
||||
if len(deviceIDsToQuery) > 0 {
|
||||
if err := tx.Where("device_id IN ? AND bind_status = 1", deviceIDsToQuery).Find(&bindings).Error; err != nil {
|
||||
return errors.Wrap(errors.CodeInternalError, err, "查询设备绑定卡失败")
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 为每张绑定的卡创建授权记录
|
||||
@@ -196,7 +232,7 @@ func (s *Service) AllocateDevices(ctx context.Context, enterpriseID uint, req *d
|
||||
}
|
||||
|
||||
// 5. 构建响应
|
||||
for _, device := range devicesToAllocate {
|
||||
for _, device := range successDevices {
|
||||
resp.AuthorizedDevices = append(resp.AuthorizedDevices, dto.AuthorizedDeviceItem{
|
||||
DeviceID: device.ID,
|
||||
VirtualNo: device.VirtualNo,
|
||||
@@ -212,11 +248,25 @@ func (s *Service) AllocateDevices(ctx context.Context, enterpriseID uint, req *d
|
||||
}
|
||||
}
|
||||
|
||||
resp.SuccessCount = len(devicesToAllocate)
|
||||
resp.SuccessCount = len(resp.AuthorizedDevices)
|
||||
resp.FailCount = len(resp.FailedItems)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func isUniqueConstraintViolation(err error, constraintName string) bool {
|
||||
var pgErr *pgconn.PgError
|
||||
if stderrors.As(err, &pgErr) {
|
||||
if pgErr.Code != "23505" {
|
||||
return false
|
||||
}
|
||||
if constraintName == "" {
|
||||
return true
|
||||
}
|
||||
return pgErr.ConstraintName == constraintName
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RecallDevices 撤销设备授权
|
||||
func (s *Service) RecallDevices(ctx context.Context, enterpriseID uint, req *dto.RecallDevicesReq) (*dto.RecallDevicesResp, error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
|
||||
@@ -162,6 +162,29 @@ func (s *EnterpriseDeviceAuthorizationStore) GetActiveAuthsByDeviceIDs(ctx conte
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetActiveAuthEnterpriseByDeviceIDs 获取设备ID列表的有效授权企业映射(deviceID -> enterpriseID)
|
||||
func (s *EnterpriseDeviceAuthorizationStore) GetActiveAuthEnterpriseByDeviceIDs(ctx context.Context, deviceIDs []uint) (map[uint]uint, error) {
|
||||
if len(deviceIDs) == 0 {
|
||||
return make(map[uint]uint), nil
|
||||
}
|
||||
|
||||
var auths []model.EnterpriseDeviceAuthorization
|
||||
query := s.db.WithContext(ctx).
|
||||
Select("device_id, enterprise_id").
|
||||
Where("device_id IN ? AND revoked_at IS NULL", deviceIDs)
|
||||
// 应用企业数据权限过滤
|
||||
query = middleware.ApplyEnterpriseFilter(ctx, query)
|
||||
if err := query.Find(&auths).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uint]uint, len(auths))
|
||||
for _, auth := range auths {
|
||||
result[auth.DeviceID] = auth.EnterpriseID
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *EnterpriseDeviceAuthorizationStore) ListDeviceIDsByEnterprise(ctx context.Context, enterpriseID uint) ([]uint, error) {
|
||||
var deviceIDs []uint
|
||||
query := s.db.WithContext(ctx).
|
||||
|
||||
Reference in New Issue
Block a user