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) }