package dataswitch import ( "context" "errors" "fmt" "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/library/batchinput/excel" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/batchinput/text" "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" ) type Row struct { DetailID int64 RowNo int Iccid string Msisdn string Imsi string Reason string Authorized bool CardID int64 CutoffThreshold float64 UsedFlowMb float64 PackageTotalFlowMb float64 RemainFlowMb float64 DataServiceStatusBefore int TrafficCutoffCrossMonthHold int TriggeredAt string TriggerReason string } func (r *Row) GetRowNo() int { if r == nil { return 0 } return r.RowNo } func (r *Row) GetItemID() string { if r == nil { return "" } return r.Iccid } func (r *Row) GetErrorReasons() []string { if r == nil || r.Reason == "" { return nil } return []string{r.Reason} } func (r *Row) AddErrorReason(reason string) { if r == nil || r.Reason != "" || reason == "" { return } r.Reason = reason } func (r *Row) GetIccid() string { if r == nil { return "" } return r.Iccid } func (r *Row) SetAuthorized(v bool) { if r == nil { return } r.Authorized = v } func (r *Row) Snapshot() *gjson.Json { if r == nil { return gjson.New(g.Map{}) } snapshot := g.Map{ "ICCID": r.Iccid, "MSISDN": r.Msisdn, "IMSI": r.Imsi, "authorized": r.Authorized, } if r.CardID > 0 { snapshot["cardId"] = r.CardID } if r.CutoffThreshold > 0 { snapshot["cutoffThreshold"] = r.CutoffThreshold } if r.UsedFlowMb > 0 { snapshot["usedFlowMb"] = r.UsedFlowMb } if r.PackageTotalFlowMb > 0 { snapshot["packageTotalFlowMb"] = r.PackageTotalFlowMb } if r.RemainFlowMb >= 0 && r.CutoffThreshold > 0 { snapshot["remainFlowMb"] = r.RemainFlowMb } if r.DataServiceStatusBefore != 0 { snapshot["dataServiceStatusBefore"] = r.DataServiceStatusBefore } if r.TrafficCutoffCrossMonthHold != 0 { snapshot["trafficCutoffCrossMonthHold"] = r.TrafficCutoffCrossMonthHold } if r.TriggeredAt != "" { snapshot["triggeredAt"] = r.TriggeredAt } if r.TriggerReason != "" { snapshot["triggerReason"] = r.TriggerReason } return gjson.New(snapshot) } func parseExcelFileRows(ctx context.Context, filePath string) ([]batchimport.Row, error) { parsed, err := excel.ParseFile(ctx, filePath, excel.ParseOptions{RequiredHeaders: []string{"ICCID"}, MaxDataRows: consts.SimCardBatchMaxRows}) if err != nil { return nil, err } rows := make([]batchimport.Row, 0, len(parsed)) for _, item := range parsed { rows = append(rows, &Row{ RowNo: item.RowNo, Iccid: excel.Field(item, "ICCID"), Msisdn: excel.Field(item, "MSISDN"), Imsi: excel.Field(item, "IMSI"), }) } return rows, nil } func parseInputRows(ctx context.Context, input string) ([]batchimport.Row, error) { lines, err := text.ParseWhitespaceFields(ctx, input) if err != nil { if errors.Is(err, text.ErrEmptyInput) { return nil, gerror.New("批量输入内容不能为空") } return nil, err } rows := make([]batchimport.Row, 0, len(lines)) for _, line := range lines { row := &Row{RowNo: line.RowNo} switch len(line.Fields) { case 1: row.Iccid = line.Fields[0] case 3: row.Iccid = line.Fields[0] row.Msisdn = line.Fields[1] row.Imsi = line.Fields[2] default: row.AddErrorReason("格式错误,应为 ICCID 或 ICCID MSISDN IMSI") } rows = append(rows, row) } return rows, nil } func validateBasicRows(rows []batchimport.Row) error { firstByIccid := make(map[string]*Row, len(rows)) issues := make([]string, 0) for _, item := range rows { row, ok := item.(*Row) if !ok || row == nil { return gerror.New("数据服务批次行类型错误") } row.Iccid = strings.TrimSpace(row.Iccid) row.Msisdn = strings.TrimSpace(row.Msisdn) row.Imsi = strings.TrimSpace(row.Imsi) if row.Reason != "" { issues = append(issues, fmt.Sprintf("第%d行:%s", row.RowNo, row.Reason)) continue } if row.Iccid == "" { row.AddErrorReason("ICCID不能为空") issues = append(issues, fmt.Sprintf("第%d行:ICCID不能为空", row.RowNo)) continue } if first, exists := firstByIccid[row.Iccid]; exists { row.AddErrorReason(fmt.Sprintf("ICCID与第%d行重复", first.RowNo)) first.AddErrorReason("ICCID重复") issues = append(issues, fmt.Sprintf("第%d行:ICCID与第%d行重复", row.RowNo, first.RowNo)) continue } firstByIccid[row.Iccid] = row } if len(issues) > 0 { return gerror.New("数据服务批次基础格式校验失败:" + strings.Join(issues, ";")) } return nil }