package trafficcutoff import ( "context" "strings" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/service/batchresult" ) const ( cascadeFailureReason = "同一批次存在无效流量断网明细,已跳过更新" validationSkipReason = "批次校验未通过,已跳过流量断网更新" emptyICCIDReason = "ICCID不能为空" duplicateICCIDReason = "ICCID在批次内重复" unauthorizedReason = "ICCID不在当前操作员授权范围内" cardMissingReason = "ICCID不存在或不属于当前租户" statusCanceledReason = "ICCID已销户" statusInconsistentReason = "同一批次内卡状态不一致" ) type executor struct { repository Repository } func NewExecutor(repository Repository) Executor { return &executor{repository: repository} } func (e *executor) Execute(ctx context.Context, batchNo string) error { task, err := e.repository.Load(ctx, strings.TrimSpace(batchNo)) if err != nil { return gerror.Wrap(err, "load traffic cutoff batch") } if !validateTask(task) { if err = e.repository.SaveValidationFailure(ctx, task); err != nil { return gerror.Wrap(err, "save traffic cutoff validation failure") } e.saveResultFile(ctx, task) return nil } if err = e.repository.CommitBusiness(ctx, task); err != nil { return gerror.Wrap(err, "commit traffic cutoff business") } e.saveResultFile(ctx, task) return nil } func (e *executor) saveResultFile(ctx context.Context, task *Task) { request := batchresult.Request{ BatchNo: task.Batch.BatchNo, BatchType: task.Batch.BatchType, TenantID: task.Batch.TenantID, Rows: task.ResultRows(), } if err := e.repository.SaveResultFile(ctx, task, request); err != nil { g.Log().Errorf(ctx, "save traffic cutoff result file status failed, batchNo:%s, err:%+v", task.Batch.BatchNo, err) } } func validateTask(task *Task) bool { if task == nil || len(task.Details) == 0 { if task != nil { task.FailureReason = "流量断网批次无有效明细" } return false } if task.TrafficCutoffStatus != 1 { task.FailureReason = "流量断网批次必须开启断网" markAllFailed(task, task.FailureReason) return false } if task.TrafficCutoffThreshold <= 0 { task.FailureReason = "流量断网阈值必须大于0" markAllFailed(task, task.FailureReason) return false } hasFailure := false iccids := make(map[string]int, len(task.Details)) statusSet := make(map[int]struct{}) for _, detail := range task.Details { if detail == nil { hasFailure = true continue } validateDetail(detail) if detail.Reason != "" { hasFailure = true continue } iccids[detail.ICCID]++ statusSet[detail.BossCardStatusBefore] = struct{}{} } for _, detail := range task.Details { if detail == nil || detail.Reason != "" { continue } if iccids[detail.ICCID] > 1 { detail.Reason = duplicateICCIDReason hasFailure = true } } if len(statusSet) > 1 { for _, detail := range task.Details { if detail != nil && detail.Reason == "" { detail.Reason = statusInconsistentReason } } hasFailure = true } if !hasFailure { task.ValidationOK = true return true } for _, detail := range task.Details { if detail != nil && detail.Reason == "" { detail.Reason = cascadeFailureReason } } task.FailureReason = validationSkipReason return false } func validateDetail(detail *Detail) { if detail.Reason != "" { return } detail.ICCID = strings.TrimSpace(detail.ICCID) detail.InputMSISDN = strings.TrimSpace(detail.InputMSISDN) detail.InputIMSI = strings.TrimSpace(detail.InputIMSI) if detail.ICCID == "" { detail.Reason = emptyICCIDReason return } if !detail.Authorized { detail.Reason = unauthorizedReason return } if detail.Card == nil { detail.Reason = cardMissingReason return } detail.MSISDN = strings.TrimSpace(detail.Card.MSISDN) detail.IMSI = strings.TrimSpace(detail.Card.IMSI) detail.BossCardStatusBefore = detail.Card.BossCardStatus detail.TrafficCutoffStatusBefore = detail.Card.TrafficCutoffStatus detail.TrafficCutoffThresholdBefore = detail.Card.TrafficCutoffThreshold if detail.InputMSISDN != "" && detail.InputMSISDN != detail.MSISDN { detail.Reason = "MSISDN与卡档案不一致" return } if detail.InputIMSI != "" && detail.InputIMSI != detail.IMSI { detail.Reason = "IMSI与卡档案不一致" return } if detail.BossCardStatusBefore == BossCardStatusCanceled { detail.Reason = statusCanceledReason return } } func markAllFailed(task *Task, reason string) { for _, detail := range task.Details { if detail != nil { detail.Reason = reason } } }