package query import ( "context" "strings" "github.com/gogf/gf/v2/errors/gerror" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/dao" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/model" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/model/entity" "git.5iot.com/iotlcm-public/iotlcm-openapi/internal/service" ) const queryTrafficCutoffConfigMaxCards = 1000 type trafficCutoffIdentifier struct { Msisdn string Iccid string Imsi string } func validateTrafficCutoffIdentifier(item trafficCutoffIdentifier) error { count := 0 if item.Msisdn != "" { count++ } if item.Iccid != "" { count++ } if item.Imsi != "" { count++ } if count == 0 { return gerror.New("msisdn、iccid、imsi至少传一个") } return nil } func trafficCutoffIdentifierKey(item trafficCutoffIdentifier) string { if item.Iccid != "" { return "iccid:" + item.Iccid } if item.Msisdn != "" { return "msisdn:" + item.Msisdn } return "imsi:" + item.Imsi } func trafficCutoffCardMatchesIdentifier(card *entity.TSimCardInfo, identifier trafficCutoffIdentifier) bool { if card == nil { return false } if identifier.Iccid != "" && strings.TrimSpace(card.Iccid) != identifier.Iccid { return false } if identifier.Msisdn != "" && strings.TrimSpace(card.Msisdn) != identifier.Msisdn { return false } if identifier.Imsi != "" && strings.TrimSpace(card.Imsi) != identifier.Imsi { return false } return true } func (s *sQuerySim) QueryTrafficCutoffConfig(ctx context.Context, in *model.QueryTrafficCutoffConfigParam) (*model.QueryTrafficCutoffConfigOutput, error) { if in == nil { return nil, gerror.New("查询参数不能为空") } if strings.TrimSpace(in.AppId) == "" { return nil, gerror.New("appId不能为空") } if len(in.Cards) == 0 { return nil, gerror.New("查询卡不能为空") } if len(in.Cards) > queryTrafficCutoffConfigMaxCards { return nil, gerror.Newf("单次最多查询%d张卡", queryTrafficCutoffConfigMaxCards) } identifiers := make([]trafficCutoffIdentifier, 0, len(in.Cards)) seen := make(map[string]struct{}, len(in.Cards)) for _, item := range in.Cards { identifier := trafficCutoffIdentifier{Msisdn: strings.TrimSpace(item.Msisdn), Iccid: strings.TrimSpace(item.Iccid), Imsi: strings.TrimSpace(item.Imsi)} if err := validateTrafficCutoffIdentifier(identifier); err != nil { return nil, err } key := trafficCutoffIdentifierKey(identifier) if _, ok := seen[key]; ok { return nil, gerror.Newf("卡片标识重复:%s", key) } seen[key] = struct{}{} identifiers = append(identifiers, identifier) } cardMap, err := loadTrafficCutoffCards(ctx, identifiers) if err != nil { return nil, err } output := &model.QueryTrafficCutoffConfigOutput{Total: len(identifiers), Items: make([]model.QueryTrafficCutoffConfigItem, 0, len(identifiers))} for _, identifier := range identifiers { result := model.QueryTrafficCutoffConfigItem{} card := cardMap[trafficCutoffIdentifierKey(identifier)] if !trafficCutoffCardMatchesIdentifier(card, identifier) { result.ErrorCode = "CARD_NOT_FOUND" result.ErrorMessage = "卡片不存在或无权限" output.NotFoundCount++ output.Items = append(output.Items, result) continue } result.Matched = true result.Iccid = strings.TrimSpace(card.Iccid) result.TrafficCutoffStatus = card.TrafficCutoffStatus result.TrafficCutoffStatusName = trafficCutoffStatusName(card.TrafficCutoffStatus) result.TrafficCutoffThreshold = card.TrafficCutoffThreshold if result.TrafficCutoffStatus == 0 { result.TrafficCutoffThreshold = 0 } result.TrafficCutoffThresholdUnit = "MB" if in.IncludeUsage { packageTotalFlowMb := card.PackageTotalFlowMb usedFlowMb := card.UsedFlowMb remainingFlowMb := maxFloat(packageTotalFlowMb-usedFlowMb, 0) result.PackageTotalFlowMb = &packageTotalFlowMb result.UsedFlowMb = &usedFlowMb result.RemainingFlowMb = &remainingFlowMb } output.MatchedCount++ output.Items = append(output.Items, result) } return output, nil } func loadTrafficCutoffCards(ctx context.Context, identifiers []trafficCutoffIdentifier) (map[string]*entity.TSimCardInfo, error) { columns := dao.TSimCardInfo.Columns() result := make(map[string]*entity.TSimCardInfo, len(identifiers)) lookup := func(field string, values []string) error { if len(values) == 0 { return nil } var cards []*entity.TSimCardInfo err := service.IotTSimCardInfo().Model(ctx). Fields(columns.Iccid, columns.Msisdn, columns.Imsi, columns.PackageTotalFlowMb, columns.UsedFlowMb, columns.TrafficCutoffStatus, columns.TrafficCutoffThreshold). WhereIn(field, values).Scan(&cards) if err != nil { return gerror.Wrap(err, "查询达量断网配置失败") } for _, card := range cards { if card == nil { continue } if card.Iccid != "" { result["iccid:"+strings.TrimSpace(card.Iccid)] = card } if card.Msisdn != "" { result["msisdn:"+strings.TrimSpace(card.Msisdn)] = card } if card.Imsi != "" { result["imsi:"+strings.TrimSpace(card.Imsi)] = card } } return nil } iccidValues, msisdnValues, imsiValues := make([]string, 0), make([]string, 0), make([]string, 0) for _, item := range identifiers { switch { case item.Iccid != "": iccidValues = append(iccidValues, item.Iccid) case item.Msisdn != "": msisdnValues = append(msisdnValues, item.Msisdn) default: imsiValues = append(imsiValues, item.Imsi) } } if err := lookup(columns.Iccid, iccidValues); err != nil { return nil, err } if err := lookup(columns.Msisdn, msisdnValues); err != nil { return nil, err } if err := lookup(columns.Imsi, imsiValues); err != nil { return nil, err } return result, nil } func trafficCutoffStatusName(status int) string { switch status { case 1: return "已开启" case 2: return "已关闭" default: return "删除" } } func maxFloat(value, floor float64) float64 { if value < floor { return floor } return value }