package app import ( "bytes" "reflect" "testing" "git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity" "github.com/gogf/gf/v2/os/gtime" "github.com/xuri/excelize/v2" ) func TestAppBuildRenewBatchImportExcelMatchesRenewTemplate(t *testing.T) { data, err := appBuildRenewBatchImportExcel(appRenewResultTestBatch(), "REN20260709164715A8F22BD5", 3, "测试备注", gtime.NewFromStr("2026-07-09 16:47:15")) if err != nil { t.Fatalf("build import excel: %v", err) } f, err := excelize.OpenReader(bytes.NewReader(data)) if err != nil { t.Fatalf("open import excel: %v", err) } defer f.Close() headers, err := f.GetRows("Sheet1") if err != nil { t.Fatalf("read import rows: %v", err) } wantHeaders := []string{"ICCID", "MSISDN", "IMSI", "续费年限", "是否走线下"} if len(headers) < 2 || !reflect.DeepEqual(headers[0], wantHeaders) { t.Fatalf("headers mismatch: %#v", headers) } wantRow := []string{"898604F4152391181413", "1441234567890", "460041234567890", "3", "TRUE"} if !reflect.DeepEqual(headers[1], wantRow) { t.Fatalf("row mismatch: %#v", headers[1]) } for _, cell := range []string{"A1", "B1", "C1", "D1", "E1", "A2", "B2", "C2", "D2", "E2"} { styleID, err := f.GetCellStyle("Sheet1", cell) if err != nil { t.Fatalf("get style %s: %v", cell, err) } style, err := f.GetStyle(styleID) if err != nil { t.Fatalf("get style detail %s: %v", cell, err) } if style.NumFmt != 49 { t.Fatalf("%s numFmt = %d, want 49", cell, style.NumFmt) } } for col, want := range map[string]float64{ "A": 24, "B": 14, "C": 18, "D": 18, "E": 18, } { got, err := f.GetColWidth("Sheet1", col) if err != nil { t.Fatalf("get width %s: %v", col, err) } if got != want { t.Fatalf("width %s = %v, want %v", col, got, want) } } } func TestAppBuildRenewBatchResultExcelMatchesBatchResultFormat(t *testing.T) { data, err := appBuildRenewBatchResultExcel(appRenewResultTestBatch(), &appRenewBatchLogFiles{ ImportOssId: 309, ImportFileName: "REN20260709164715A8F22BD5-import.xlsx", }, "REN20260709164715A8F22BD5", "SO202607091647150000875NYX", 3, 30, 30, nil, nil, nil, gtime.NewFromStr("2026-07-09 16:47:15"), 87, 310) if err != nil { t.Fatalf("build result excel: %v", err) } f, err := excelize.OpenReader(bytes.NewReader(data)) if err != nil { t.Fatalf("open result excel: %v", err) } defer f.Close() if sheets := f.GetSheetList(); !reflect.DeepEqual(sheets, []string{"导入结果", "批次信息"}) { t.Fatalf("sheets mismatch: %#v", sheets) } resultRows, err := f.GetRows("导入结果") if err != nil { t.Fatalf("read result rows: %v", err) } if !reflect.DeepEqual(resultRows[0], []string{"源文件行号", "item_id", "处理状态", "异常原因"}) { t.Fatalf("result headers mismatch: %#v", resultRows[0]) } if !reflect.DeepEqual(resultRows[1][:3], []string{"2", "898604F4152391181413", "成功"}) { t.Fatalf("result row mismatch: %#v", resultRows[1]) } infoRows, err := f.GetRows("批次信息") if err != nil { t.Fatalf("read info rows: %v", err) } if !reflect.DeepEqual(infoRows[0], []string{"字段", "值"}) { t.Fatalf("info headers mismatch: %#v", infoRows[0]) } if !reflect.DeepEqual(infoRows[1], []string{"批次号", "REN20260709164715A8F22BD5"}) { t.Fatalf("info row mismatch: %#v", infoRows[1]) } } func TestAppRenewBatchResultInfoRowsUsesBatchImportFileName(t *testing.T) { rows := appRenewBatchResultInfoRows( appRenewResultTestBatch(), &appRenewBatchLogFiles{}, "REN202607091748552P7KDBXN", 3, 10, 10, nil, nil, gtime.NewFromStr("2026-07-09 17:48:56"), 87, 340, ) info := map[string]string{} for _, row := range rows { info[row[0]] = row[1] } if info["原始文件名"] != "REN202607091748552P7KDBXN-import.xlsx" { t.Fatalf("source file name = %q, want batch import file name", info["原始文件名"]) } if info["原始文件OSS ID"] != "" { t.Fatalf("source file oss id = %q, want empty", info["原始文件OSS ID"]) } if info["结果文件OSS ID"] != "340" { t.Fatalf("result file oss id = %q, want 340", info["结果文件OSS ID"]) } } func appRenewResultTestBatch() *appRenewBatchContext { return &appRenewBatchContext{ CurrentPackage: &entity.TSimFlowPackageInfo{ PackageCode: "OLDPKG", PackageName: "原套餐", }, Package: &entity.TSimFlowPackageInfo{ Id: 2001, PackageCode: "NEWPKG", PackageName: "续费套餐", }, Price: &appRenewPriceSnapshot{ UnitPrice: 10, PriceSource: "system", }, Party: &appRenewOrderParty{ CustomerAgentId: 175, CreatedDept: 175, }, Durations: []int{1, 2, 3}, OwnerType: appCardOwnerAgent, RenewablePackageCodes: []string{"NEWPKG"}, Items: []*appRenewPackageContext{ { ExpectedCurrentPackageCode: "OLDPKG", Card: &appCardQueryRow{ TSimCardInfo: entity.TSimCardInfo{ Id: 1001, Iccid: "898604F4152391181413", Msisdn: "1441234567890", Imsi: "460041234567890", }, }, }, }, } }