Files
junhong_cmp_fiber/internal/domain/cardobservation/network.go
2026-07-24 16:07:18 +08:00

91 lines
3.3 KiB
Go

package cardobservation
import (
"strings"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
)
// NetworkObservation 是领域层接收的标准 Gateway 网络观测。
type NetworkObservation struct {
CardID uint
GatewayStatus string
GatewayExtend string
GatewayIMEI string
Metadata ObservationMetadata
}
// CardNetworkSnapshot 是网络规则需要的最小卡快照。
type CardNetworkSnapshot struct {
CardID uint
NetworkStatus int
StopReason string
IsStandalone bool
EnablePolling bool
}
// NetworkDecision 描述一次网络观测可安全持久化的最终值。
type NetworkDecision struct {
StatusKnown bool
StatusChanged bool
BeforeStatus int
AfterStatus int
GatewayExtend string
GatewayIMEI string
UpdateIMEI bool
StopReason string
StopReasonChanged bool
StopPolling bool
}
// ApplyNetwork 应用 Gateway 状态映射、运营商停机原因和独立风险卡规则。
func ApplyNetwork(snapshot CardNetworkSnapshot, observation NetworkObservation) (NetworkDecision, error) {
if err := validateObservationMetadata(observation.CardID, observation.Metadata); err != nil {
return NetworkDecision{}, err
}
if snapshot.NetworkStatus != constants.NetworkStatusOffline && snapshot.NetworkStatus != constants.NetworkStatusOnline {
return NetworkDecision{}, errors.New(errors.CodeInvalidStatus, "卡网络状态无效")
}
status, known := MapGatewayNetworkStatus(observation.GatewayStatus, observation.GatewayExtend)
extend := strings.TrimSpace(observation.GatewayExtend)
imei := strings.TrimSpace(observation.GatewayIMEI)
decision := NetworkDecision{
StatusKnown: known, BeforeStatus: snapshot.NetworkStatus, AfterStatus: snapshot.NetworkStatus,
GatewayExtend: extend, GatewayIMEI: imei, UpdateIMEI: imei != "", StopReason: snapshot.StopReason,
StopPolling: snapshot.EnablePolling && ShouldStopPollingForRisk(snapshot.IsStandalone, extend),
}
if !known {
return decision, nil
}
decision.AfterStatus = status
decision.StatusChanged = status != snapshot.NetworkStatus
if decision.StatusChanged && status == constants.NetworkStatusOffline && snapshot.StopReason == "" &&
strings.TrimSpace(observation.GatewayStatus) == constants.GatewayCardStatusStopped {
decision.StopReason = constants.StopReasonCarrierStopped
decision.StopReasonChanged = true
}
return decision, nil
}
// MapGatewayNetworkStatus 将 Gateway 状态稳定映射为本地网络状态。
func MapGatewayNetworkStatus(cardStatus, extend string) (int, bool) {
status := strings.TrimSpace(cardStatus)
ext := strings.TrimSpace(extend)
switch status {
case constants.GatewayCardStatusNormal:
return constants.NetworkStatusOnline, true
case constants.GatewayCardStatusStopped, constants.GatewayCardStatusReady:
return constants.NetworkStatusOffline, true
}
if ext == constants.GatewayCardExtendPendingActivation {
return constants.NetworkStatusOffline, true
}
return constants.NetworkStatusOffline, false
}
// ShouldStopPollingForRisk 判断独立卡是否命中运营商风险终止状态。
func ShouldStopPollingForRisk(isStandalone bool, extend string) bool {
return isStandalone && (extend == constants.GatewayCardExtendRiskStop || extend == constants.GatewayCardExtendCancelled)
}