package trafficcutoffconfig import ( "context" "fmt" "math" "strings" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/batchimport" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model" "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" ) type Processor struct{} func NewProcessor() *Processor { return &Processor{} } func (p *Processor) Config() batchimport.ProcessorConfig { return batchimport.ProcessorConfig{ Code: "sim_card_traffic_cutoff_config", BatchType: consts.BatchTypeTrafficCutoffConfig, BatchNoPrefix: consts.BatchNoPrefixTrafficCutoffConfig, TaskName: consts.ResourceBatchDownloadTaskTrafficCutoffConfig, ExportScene: consts.ResourceExportSceneTrafficCutoffConfig, ImportDir: consts.SimCardTrafficCutoffConfigSubDirImportExcel, ResultDir: consts.SimCardTrafficCutoffConfigSubDirResultExcel, MaxFileSize: consts.SimCardTrafficCutoffConfigMaxFileSize, TemplateHeaders: []string{"ICCID", "MSISDN", "IMSI"}, RequiredHeaders: []string{"ICCID"}, } } func (p *Processor) ParseRows(ctx context.Context, filePath string) ([]batchimport.Row, error) { return ParseExcelFileRows(ctx, filePath) } func (p *Processor) ValidateRows(_ context.Context, rows []batchimport.Row) error { firstByIccid := make(map[string]*Row, len(rows)) for _, item := range rows { row, ok := item.(*Row) if !ok || row == nil { item.AddErrorReason("达量断网配置行类型错误") continue } row.Iccid = strings.TrimSpace(row.Iccid) row.Msisdn = strings.TrimSpace(row.Msisdn) row.Imsi = strings.TrimSpace(row.Imsi) if row.Iccid == "" { row.AddErrorReason("ICCID不能为空") continue } if first, exists := firstByIccid[row.Iccid]; exists { row.AddErrorReason(fmt.Sprintf("ICCID与第%d行重复", first.RowNo)) first.AddErrorReason("ICCID重复") continue } firstByIccid[row.Iccid] = row } return nil } func (p *Processor) BuildBatchInfo(ctx context.Context, req batchimport.SubmitRequest, result *batchimport.Result, importOss *model.SysOssSaveContentModel, resultOss *model.SysOssSaveContentModel, downloadId int64) *gjson.Json { options, _ := OptionsFromParams(req.BizParams) info := g.Map{ "operation": "traffic_cutoff_config", "configName": "达量断网配置", "submitScene": submitScene(req.BizParams), "trafficCutoffStatus": options.TrafficCutoffStatus, "trafficCutoffThreshold": options.TrafficCutoffThreshold, "trafficCutoffCrossMonthHold": options.TrafficCutoffCrossMonthHold, "trafficCutoffThresholdUnit": "MB", "resultFile": g.Map{"status": "pending"}, } if result != nil && result.ImportFileOssId > 0 { info["importFileOssId"] = result.ImportFileOssId } else if importOss != nil && importOss.OssId > 0 { info["importFileOssId"] = importOss.OssId } if resultOss != nil && resultOss.OssId > 0 { info["resultFileOssId"] = resultOss.OssId } if downloadId > 0 { info["resultDownloadId"] = downloadId } return gjson.New(info) } func OptionsFromParams(params any) (Options, error) { switch in := params.(type) { case *model.TSimCardTrafficCutoffExcelSubmitParam: if in == nil { return Options{}, gerror.New("达量断网配置参数不能为空") } return NormalizeOptions(&in.TSimCardTrafficCutoffOptions) case *model.TSimCardTrafficCutoffInputSubmitParam: if in == nil { return Options{}, gerror.New("达量断网配置参数不能为空") } return NormalizeOptions(&in.TSimCardTrafficCutoffOptions) case *model.TSimCardTrafficCutoffRangeSubmitParam: if in == nil { return Options{}, gerror.New("达量断网配置参数不能为空") } return NormalizeOptions(&in.TSimCardTrafficCutoffOptions) default: return Options{}, gerror.New("达量断网配置参数不能为空") } } func NormalizeOptions(in *model.TSimCardTrafficCutoffOptions) (Options, error) { if in == nil || in.TrafficCutoffStatus == nil { return Options{}, gerror.New("达量断网配置状态不能为空") } crossMonthHold := 0 if in.TrafficCutoffCrossMonthHold != nil { crossMonthHold = *in.TrafficCutoffCrossMonthHold } options := Options{ TrafficCutoffCrossMonthHold: crossMonthHold, TrafficCutoffStatus: *in.TrafficCutoffStatus, TrafficCutoffThreshold: in.TrafficCutoffThreshold, } if err := ValidateConfig(options.TrafficCutoffStatus, options.TrafficCutoffThreshold, options.TrafficCutoffCrossMonthHold); err != nil { return Options{}, err } return options, nil } func ValidateConfig(status int, threshold float64, crossMonthHoldValues ...int) error { crossMonthHold := 0 if len(crossMonthHoldValues) > 0 { crossMonthHold = crossMonthHoldValues[0] } if status != 0 && status != 1 && status != 2 { return gerror.New("达量断网启停状态无效") } if threshold < 0 { return gerror.New("达量断网阈值不能小于0") } if status == 0 && threshold != 0 { return gerror.New("未配置达量断网时阈值必须为0") } if status == 1 && threshold <= 0 { return gerror.New("开启达量断网时阈值必须大于0") } if crossMonthHold != 0 && crossMonthHold != 1 { return gerror.New("invalid cross-month traffic cutoff hold value") } if status != 1 && crossMonthHold != 0 { return gerror.New("cross-month hold requires traffic cutoff to be enabled") } rounded := math.Round(threshold*1000) / 1000 if math.Abs(threshold-rounded) > 0.0000001 { return gerror.New("达量断网阈值最多保留3位小数") } return nil } func submitScene(params any) string { switch params.(type) { case *model.TSimCardTrafficCutoffExcelSubmitParam: return "excel" case *model.TSimCardTrafficCutoffInputSubmitParam: return "input" case *model.TSimCardTrafficCutoffRangeSubmitParam: return "range" default: return "" } }