收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/gateway"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
@@ -51,73 +52,31 @@ func (s *Service) GatewayGetSlotInfo(ctx context.Context, identifier string) (*g
|
||||
func (s *Service) GatewaySetWiFi(ctx context.Context, identifier string, req *dto.SetWiFiRequest) error {
|
||||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||||
if err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSetWiFi,
|
||||
"设备设置WiFi失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
nil,
|
||||
nil,
|
||||
map[string]any{
|
||||
"identifier": identifier,
|
||||
"ssid": req.SSID,
|
||||
"enabled": req.Enabled,
|
||||
"password": req.Password,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
return err
|
||||
}
|
||||
observation := s.captureDeviceControlObservation(ctx, device.ID, 0, "")
|
||||
if err = s.gatewayClient.SetWiFi(ctx, &gateway.WiFiReq{
|
||||
CardNo: imei,
|
||||
Params: gateway.WiFiParams{
|
||||
SSIDName: req.SSID,
|
||||
SSIDPassword: req.Password,
|
||||
err = s.executeDeviceGatewayCommand(ctx, device, deviceGatewayCommand{
|
||||
ActionCode: constants.AuditActionDeviceWiFiSet,
|
||||
Summary: "设置设备 Wi-Fi",
|
||||
Operation: constants.IntegrationOperationGatewaySetWiFi,
|
||||
Scene: constants.CardObservationSceneDeviceSetWiFi,
|
||||
RequestSummary: map[string]any{
|
||||
"device_id": device.ID, "imei": imei, "ssid": req.SSID,
|
||||
"enabled_requested": req.Enabled, "credentials_configured": req.Password != "",
|
||||
},
|
||||
}); err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSetWiFi,
|
||||
"设备设置WiFi失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{
|
||||
"imei": imei,
|
||||
"ssid": req.SSID,
|
||||
"enabled": req.Enabled,
|
||||
"password": req.Password,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
Metadata: map[string]any{
|
||||
"ssid": req.SSID, "enabled_requested": req.Enabled, "credentials_configured": req.Password != "",
|
||||
},
|
||||
Call: func(callCtx context.Context) error {
|
||||
return s.gatewayClient.SetWiFi(callCtx, &gateway.WiFiReq{
|
||||
CardNo: imei,
|
||||
Params: gateway.WiFiParams{SSIDName: req.SSID, SSIDPassword: req.Password},
|
||||
})
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSetWiFi,
|
||||
"设备设置WiFi",
|
||||
constants.AssetAuditResultSuccess,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{
|
||||
"imei": imei,
|
||||
"ssid": req.SSID,
|
||||
"enabled": req.Enabled,
|
||||
"password": req.Password,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
)
|
||||
s.dispatchDeviceControlObservation(ctx, device.ID, constants.CardObservationSceneDeviceSetWiFi, observation, false)
|
||||
return nil
|
||||
}
|
||||
@@ -126,58 +85,92 @@ func (s *Service) GatewaySetWiFi(ctx context.Context, identifier string, req *dt
|
||||
func (s *Service) GatewaySwitchCard(ctx context.Context, identifier string, req *dto.SwitchCardRequest) error {
|
||||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||||
if err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchCard,
|
||||
"设备切卡失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
nil,
|
||||
nil,
|
||||
map[string]any{
|
||||
"identifier": identifier,
|
||||
"target_iccid": req.TargetICCID,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
return err
|
||||
}
|
||||
state, err := loadDeviceBindingState(ctx, s.db, device.ID, req.TargetICCID, false)
|
||||
metadata := map[string]any{"target_iccid": req.TargetICCID}
|
||||
if err != nil {
|
||||
s.recordDeviceBindingAuditFailure(ctx, constants.AuditActionDeviceCurrentCardSwitched, "设备切卡失败", constants.AuditResultFailed,
|
||||
device, nil, nil, metadata, err)
|
||||
return err
|
||||
}
|
||||
if state.target == nil {
|
||||
appErr := errors.New(errors.CodeForbidden, "目标卡未绑定到当前设备")
|
||||
s.recordDeviceBindingAuditFailure(ctx, constants.AuditActionDeviceCurrentCardSwitched, "设备切卡被拒绝", constants.AuditResultDenied,
|
||||
device, map[string]any{"current_iot_card_id": currentCardID(state)}, switchCardAuditItems(state), metadata, appErr)
|
||||
return appErr
|
||||
}
|
||||
targetCard := state.cards[state.target.IotCardID]
|
||||
if targetCard == nil {
|
||||
appErr := errors.New(errors.CodeNotFound, "目标卡资产不存在或无权限访问")
|
||||
s.recordDeviceBindingAuditFailure(ctx, constants.AuditActionDeviceCurrentCardSwitched, "设备切卡失败", constants.AuditResultFailed,
|
||||
device, map[string]any{"current_iot_card_id": currentCardID(state)}, switchCardAuditItems(state), metadata, appErr)
|
||||
return appErr
|
||||
}
|
||||
metadata["target_iot_card_id"] = targetCard.ID
|
||||
metadata["target_slot_position"] = state.target.SlotPosition
|
||||
observation := s.captureDeviceControlObservation(ctx, device.ID, 0, req.TargetICCID)
|
||||
if err = s.gatewayClient.SwitchCard(ctx, &gateway.SwitchCardReq{
|
||||
deviceID := strconv.FormatUint(uint64(device.ID), 10)
|
||||
observer := &deviceGatewayAttemptObserver{
|
||||
service: s, operation: constants.IntegrationOperationGatewaySwitchCard,
|
||||
scene: constants.CardObservationSceneDeviceSwitchCard, seriesKey: deviceCommandSeriesKey(ctx),
|
||||
resource: deviceGatewayResource{
|
||||
Type: constants.AuditResourceDevice, ID: deviceID, Key: audit.DeviceResourceKey(device), ExternalID: imei,
|
||||
RequestSummary: map[string]any{
|
||||
"device_id": device.ID, "imei": imei, "target_iot_card_id": targetCard.ID,
|
||||
"target_iccid": targetCard.ICCID, "target_slot_position": state.target.SlotPosition,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err = s.gatewayClient.SwitchCard(gateway.WithAttemptObserver(ctx, observer), &gateway.SwitchCardReq{
|
||||
CardNo: imei,
|
||||
ICCID: req.TargetICCID,
|
||||
}); err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchCard,
|
||||
"设备切卡失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"target_iccid": req.TargetICCID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
result, summary := constants.AuditResultFailed, "设备切卡失败"
|
||||
if observer.unknown {
|
||||
result, summary = constants.AuditResultUnknown, "设备切卡结果未知"
|
||||
}
|
||||
metadata["integration_id"] = observer.integration
|
||||
s.recordDeviceBindingAuditFailure(ctx, constants.AuditActionDeviceCurrentCardSwitched, summary, result,
|
||||
device, map[string]any{"current_iot_card_id": currentCardID(state)}, switchCardAuditItems(state), metadata, err)
|
||||
return err
|
||||
}
|
||||
metadata["integration_id"] = observer.integration
|
||||
if err := observer.completeSuccess(ctx, false); err != nil {
|
||||
appErr := errors.Wrap(errors.CodeDatabaseError, err, "终结设备切卡 Integration Log 失败")
|
||||
s.recordDeviceBindingAuditFailure(ctx, constants.AuditActionDeviceCurrentCardSwitched, "设备切卡结果未知", constants.AuditResultUnknown,
|
||||
device, map[string]any{"current_iot_card_id": currentCardID(state)}, switchCardAuditItems(state), metadata, appErr)
|
||||
return appErr
|
||||
}
|
||||
err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
lockedState, err := loadDeviceBindingState(ctx, tx, device.ID, targetCard.ICCID, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if lockedState.target == nil {
|
||||
return errors.New(errors.CodeConflict, "切卡期间目标卡绑定关系已变化")
|
||||
}
|
||||
if err := tx.WithContext(ctx).Model(&model.DeviceSimBinding{}).
|
||||
Where("device_id = ? AND bind_status = ?", device.ID, constants.BindStatusBound).
|
||||
Update("is_current", false).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.WithContext(ctx).Model(&model.DeviceSimBinding{}).
|
||||
Where("id = ? AND bind_status = ?", lockedState.target.ID, constants.BindStatusBound).
|
||||
Update("is_current", true).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return s.appendDeviceBindingAudit(ctx, tx, constants.AuditActionDeviceCurrentCardSwitched, "切换设备当前卡", constants.AuditResultSuccess,
|
||||
device,
|
||||
map[string]any{"current_iot_card_id": currentCardID(lockedState)},
|
||||
map[string]any{"current_iot_card_id": lockedState.target.IotCardID},
|
||||
switchCardAuditItems(lockedState), metadata, nil)
|
||||
})
|
||||
if err != nil {
|
||||
s.recordDeviceBindingAuditFailure(ctx, constants.AuditActionDeviceCurrentCardSwitched, "设备切卡结果未知", constants.AuditResultUnknown,
|
||||
device, map[string]any{"current_iot_card_id": currentCardID(state)}, switchCardAuditItems(state), metadata, err)
|
||||
return err
|
||||
}
|
||||
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchCard,
|
||||
"设备切卡",
|
||||
constants.AssetAuditResultSuccess,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"target_iccid": req.TargetICCID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
)
|
||||
s.dispatchDeviceControlObservation(ctx, device.ID, constants.CardObservationSceneDeviceSwitchCard, observation, true)
|
||||
return nil
|
||||
}
|
||||
@@ -186,54 +179,21 @@ func (s *Service) GatewaySwitchCard(ctx context.Context, identifier string, req
|
||||
func (s *Service) GatewayRebootDevice(ctx context.Context, identifier string) error {
|
||||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||||
if err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceReboot,
|
||||
"设备重启失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
nil,
|
||||
nil,
|
||||
map[string]any{"identifier": identifier},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
return err
|
||||
}
|
||||
observation := s.captureDeviceControlObservation(ctx, device.ID, 0, "")
|
||||
if err = s.gatewayClient.RebootDevice(ctx, &gateway.DeviceOperationReq{
|
||||
DeviceID: imei,
|
||||
}); err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceReboot,
|
||||
"设备重启失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
nil,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
err = s.executeDeviceGatewayCommand(ctx, device, deviceGatewayCommand{
|
||||
ActionCode: constants.AuditActionDeviceRebooted, Summary: "重启设备",
|
||||
Operation: constants.IntegrationOperationGatewayReboot, Scene: constants.CardObservationSceneDeviceReboot,
|
||||
RequestSummary: map[string]any{"device_id": device.ID, "imei": imei},
|
||||
Metadata: map[string]any{"requested_action": "reboot"},
|
||||
Call: func(callCtx context.Context) error {
|
||||
return s.gatewayClient.RebootDevice(callCtx, &gateway.DeviceOperationReq{DeviceID: imei})
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceReboot,
|
||||
"设备重启",
|
||||
constants.AssetAuditResultSuccess,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
nil,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
)
|
||||
s.dispatchDeviceControlObservation(ctx, device.ID, constants.CardObservationSceneDeviceReboot, observation, false)
|
||||
return nil
|
||||
}
|
||||
@@ -242,54 +202,21 @@ func (s *Service) GatewayRebootDevice(ctx context.Context, identifier string) er
|
||||
func (s *Service) GatewayResetDevice(ctx context.Context, identifier string) error {
|
||||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||||
if err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceReset,
|
||||
"设备恢复出厂失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
nil,
|
||||
nil,
|
||||
map[string]any{"identifier": identifier},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
return err
|
||||
}
|
||||
observation := s.captureDeviceControlObservation(ctx, device.ID, 0, "")
|
||||
if err = s.gatewayClient.ResetDevice(ctx, &gateway.DeviceOperationReq{
|
||||
DeviceID: imei,
|
||||
}); err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceReset,
|
||||
"设备恢复出厂失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
nil,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
err = s.executeDeviceGatewayCommand(ctx, device, deviceGatewayCommand{
|
||||
ActionCode: constants.AuditActionDeviceReset, Summary: "恢复设备出厂设置",
|
||||
Operation: constants.IntegrationOperationGatewayReset, Scene: constants.CardObservationSceneDeviceReset,
|
||||
RequestSummary: map[string]any{"device_id": device.ID, "imei": imei},
|
||||
Metadata: map[string]any{"requested_action": "factory_reset"},
|
||||
Call: func(callCtx context.Context) error {
|
||||
return s.gatewayClient.ResetDevice(callCtx, &gateway.DeviceOperationReq{DeviceID: imei})
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceReset,
|
||||
"设备恢复出厂",
|
||||
constants.AssetAuditResultSuccess,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
nil,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
)
|
||||
s.dispatchDeviceControlObservation(ctx, device.ID, constants.CardObservationSceneDeviceReset, observation, false)
|
||||
return nil
|
||||
}
|
||||
@@ -303,244 +230,77 @@ func (s *Service) GatewaySwitchMode(ctx context.Context, identifier string, req
|
||||
|
||||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||||
if err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
nil,
|
||||
nil,
|
||||
map[string]any{
|
||||
"identifier": identifier,
|
||||
"switch_mode": switchMode,
|
||||
"iot_card_id": req.IotCardID,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
return err
|
||||
}
|
||||
recordRejected := func(summary, result string, businessErr error, targetCard *model.IotCard) error {
|
||||
s.recordDeviceCommandAudit(ctx, constants.AuditActionDeviceSwitchModeSet, summary, result,
|
||||
device, targetCard, nil, nil,
|
||||
map[string]any{"requested_switch_mode": switchMode, "iot_card_id": req.IotCardID}, businessErr)
|
||||
return businessErr
|
||||
}
|
||||
if req.SwitchMode == nil {
|
||||
appErr := errors.New(errors.CodeInvalidParam, "切卡模式不能为空")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换被拒绝",
|
||||
constants.AssetAuditResultDenied,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"iot_card_id": req.IotCardID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式被拒绝", constants.AuditResultDenied, appErr, nil)
|
||||
}
|
||||
if switchMode != 0 && switchMode != 1 {
|
||||
appErr := errors.New(errors.CodeInvalidParam, "切卡模式仅支持0或1")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换被拒绝",
|
||||
constants.AssetAuditResultDenied,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式被拒绝", constants.AuditResultDenied, appErr, nil)
|
||||
}
|
||||
if req.IotCardID == 0 {
|
||||
appErr := errors.New(errors.CodeInvalidParam, "目标卡资产ID不能为空")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换被拒绝",
|
||||
constants.AssetAuditResultDenied,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式被拒绝", constants.AuditResultDenied, appErr, nil)
|
||||
}
|
||||
|
||||
targetCard, err := s.iotCardStore.GetByID(ctx, req.IotCardID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
appErr := errors.New(errors.CodeNotFound, "目标卡资产不存在或无权限访问")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换被拒绝",
|
||||
constants.AssetAuditResultDenied,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式被拒绝", constants.AuditResultDenied, appErr, nil)
|
||||
}
|
||||
appErr := errors.Wrap(errors.CodeDatabaseError, err, "查询目标卡资产失败")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式失败", constants.AuditResultFailed, appErr, nil)
|
||||
}
|
||||
if _, err = s.deviceSimBindingStore.GetByDeviceAndCard(ctx, device.ID, targetCard.ID); err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
appErr := errors.New(errors.CodeForbidden, "目标卡未绑定到当前设备,禁止设置切卡模式")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换被拒绝",
|
||||
constants.AssetAuditResultDenied,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID, "iccid": targetCard.ICCID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式被拒绝", constants.AuditResultDenied, appErr, targetCard)
|
||||
}
|
||||
appErr := errors.Wrap(errors.CodeDatabaseError, err, "查询设备卡绑定关系失败")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID, "iccid": targetCard.ICCID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式失败", constants.AuditResultFailed, appErr, targetCard)
|
||||
}
|
||||
if targetCard.ICCID == "" {
|
||||
appErr := errors.New(errors.CodeConflict, "目标卡资产缺少ICCID,无法设置切卡模式")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换被拒绝",
|
||||
constants.AssetAuditResultDenied,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式被拒绝", constants.AuditResultDenied, appErr, targetCard)
|
||||
}
|
||||
if targetCard.NetworkStatus != constants.NetworkStatusOnline {
|
||||
appErr := errors.New(errors.CodeForbidden, "目标卡状态异常,仅正常状态的卡允许设置切卡模式")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换被拒绝",
|
||||
constants.AssetAuditResultDenied,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{
|
||||
"switch_mode": switchMode,
|
||||
"iot_card_id": req.IotCardID,
|
||||
"iccid": targetCard.ICCID,
|
||||
"network_status": targetCard.NetworkStatus,
|
||||
"real_name_status": targetCard.RealNameStatus,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式被拒绝", constants.AuditResultDenied, appErr, targetCard)
|
||||
}
|
||||
if targetCard.RealNameStatus != constants.RealNameStatusVerified {
|
||||
appErr := errors.New(errors.CodeForbidden, "目标卡未实名,禁止设置切卡模式")
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换被拒绝",
|
||||
constants.AssetAuditResultDenied,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{
|
||||
"switch_mode": switchMode,
|
||||
"iot_card_id": req.IotCardID,
|
||||
"iccid": targetCard.ICCID,
|
||||
"network_status": targetCard.NetworkStatus,
|
||||
"real_name_status": targetCard.RealNameStatus,
|
||||
},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
appErr,
|
||||
)
|
||||
return appErr
|
||||
return recordRejected("设置设备切卡模式被拒绝", constants.AuditResultDenied, appErr, targetCard)
|
||||
}
|
||||
observation := s.captureDeviceControlObservation(ctx, device.ID, targetCard.ID, targetCard.ICCID)
|
||||
if err = s.gatewayClient.SwitchMode(ctx, &gateway.SwitchModeReq{
|
||||
CardNo: imei,
|
||||
SwitchMode: strconv.Itoa(switchMode),
|
||||
ICCID: targetCard.ICCID,
|
||||
}); err != nil {
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换失败",
|
||||
constants.AssetAuditResultFailed,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID, "iccid": targetCard.ICCID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
err,
|
||||
)
|
||||
err = s.executeDeviceGatewayCommand(ctx, device, deviceGatewayCommand{
|
||||
ActionCode: constants.AuditActionDeviceSwitchModeSet, Summary: "设置设备切卡模式",
|
||||
Operation: constants.IntegrationOperationGatewaySwitchMode, Scene: constants.CardObservationSceneDeviceSwitchMode,
|
||||
RequestSummary: map[string]any{
|
||||
"device_id": device.ID, "imei": imei, "switch_mode": switchMode,
|
||||
"iot_card_id": targetCard.ID, "iccid": targetCard.ICCID,
|
||||
},
|
||||
Metadata: map[string]any{
|
||||
"requested_switch_mode": switchMode, "iot_card_id": targetCard.ID, "iccid": targetCard.ICCID,
|
||||
},
|
||||
TargetCard: targetCard,
|
||||
Call: func(callCtx context.Context) error {
|
||||
return s.gatewayClient.SwitchMode(callCtx, &gateway.SwitchModeReq{
|
||||
CardNo: imei, SwitchMode: strconv.Itoa(switchMode), ICCID: targetCard.ICCID,
|
||||
})
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.logDeviceOperation(
|
||||
ctx,
|
||||
constants.AssetAuditOpDeviceSwitchMode,
|
||||
"设备切卡模式切换",
|
||||
constants.AssetAuditResultSuccess,
|
||||
device,
|
||||
map[string]any{"device": deviceSnapshot(device)},
|
||||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID, "iccid": targetCard.ICCID},
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
)
|
||||
s.dispatchDeviceControlObservation(ctx, device.ID, constants.CardObservationSceneDeviceSwitchMode, observation, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user