package renew import ( "context" "testing" "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" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model/entity" "github.com/gogf/gf/v2/os/gtime" ) func TestBuildBatchInfoOmitsRemovedEmptyFields(t *testing.T) { t.Parallel() info := NewProcessor().BuildBatchInfo(context.Background(), batchimport.SubmitRequest{ BizParams: &model.TSimCardRenewBatchSubmitParam{ DurationMonths: 12, GiftDurationMonths: 2, Amount: "100.00", OfflineContractCompleted: true, }, ExecutionResult: &CompleteOutput{ Quantity: 1, PackageCode: "PKG001", OrderSn: "ORDER001", }, }, &batchimport.Result{}, nil, nil, 0) data := info.Map() for _, key := range []string{"sourceBatchNo", "buyerNote", "adminNote", "remark"} { if _, ok := data[key]; ok { t.Fatalf("batch info should omit %s when empty: %#v", key, data) } } if data["durationMonths"] != 12 { t.Fatalf("unexpected durationMonths: %#v", data["durationMonths"]) } if data["giftDurationMonths"] != 2 { t.Fatalf("unexpected giftDurationMonths: %#v", data["giftDurationMonths"]) } if data["offlineContractCompleted"] != true { t.Fatalf("unexpected offlineContractCompleted: %#v", data["offlineContractCompleted"]) } } func TestCurrentPackagePeriodKey(t *testing.T) { t.Parallel() bind := &entity.TSimCardBindPkg{ EffectiveTime: gtime.NewFromStr("2026-01-01"), ExpectedExpireTime: gtime.NewFromStr("2026-12-31"), } if got, want := currentPackagePeriodKey(bind), "2026-01-01|2026-12-31"; got != want { t.Fatalf("currentPackagePeriodKey() = %q, want %q", got, want) } if got := currentPackagePeriodKey(&entity.TSimCardBindPkg{}); got != "" { t.Fatalf("currentPackagePeriodKey() for empty bind = %q, want empty", got) } } func TestRenewBaseExpireTimePrefersLaterCardExpire(t *testing.T) { t.Parallel() card := &entity.TSimCardInfo{ FlowPkgEndAt: gtime.NewFromStr("2026-10-31 00:00:00"), } bind := &entity.TSimCardBindPkg{ ExpectedExpireTime: gtime.NewFromStr("2026-08-31 00:00:00"), } if got, want := renewBaseExpireTime(card, bind).Format("Y-m-d"), "2026-10-31"; got != want { t.Fatalf("renewBaseExpireTime() = %q, want %q", got, want) } } func TestRenewBeginDateFromExpireUsesExpireDate(t *testing.T) { t.Parallel() beginAt := renewBeginDateFromExpire(gtime.NewFromStr("2026-08-31 23:59:59")) if beginAt == nil { t.Fatal("renew begin date is nil") } if got, want := beginAt.Format("Y-m-d H:i:s"), "2026-08-31 23:59:59"; got != want { t.Fatalf("renewBeginDateFromExpire() = %q, want %q", got, want) } } func TestValidateRenewRowRejectsExpireAfterSixMonths(t *testing.T) { t.Parallel() card := &entity.TSimCardInfo{ CurrentPackageCode: "PKG001", PackageStatus: consts.PackageStatusEffective, } bind := &entity.TSimCardBindPkg{ PackageCode: "PKG001", ExpectedExpireTime: gtime.Now().AddDate(0, 6, 1), EffectiveTime: gtime.Now().AddDate(-1, 0, 0), EffectiveStatus: consts.EffectiveStatusEffective, } if got, want := validateRenewRow("", batchimport.OperatorContext{}, card, bind), "距离到期超过6个月,不能续费"; got != want { t.Fatalf("validateRenewRow() = %q, want %q", got, want) } } func TestValidateRenewRowAllowsExpireWithinSixMonths(t *testing.T) { t.Parallel() card := &entity.TSimCardInfo{ CurrentPackageCode: "PKG001", PackageStatus: consts.PackageStatusEffective, } bind := &entity.TSimCardBindPkg{ PackageCode: "PKG001", ExpectedExpireTime: gtime.Now().AddDate(0, 6, 0), EffectiveTime: gtime.Now().AddDate(-1, 0, 0), EffectiveStatus: consts.EffectiveStatusEffective, } if got := validateRenewRow("", batchimport.OperatorContext{}, card, bind); got != "" { t.Fatalf("validateRenewRow() = %q, want empty", got) } } func TestValidateRenewRowRejectsStoppedCard(t *testing.T) { t.Parallel() card := &entity.TSimCardInfo{ BossCardStatus: consts.V3ApiSimBossCardStatusStopped, CurrentPackageCode: "PKG001", PackageStatus: consts.PackageStatusEffective, } bind := &entity.TSimCardBindPkg{ PackageCode: "PKG001", } if got, want := validateRenewRow("", batchimport.OperatorContext{}, card, bind), "ICCID当前为停机状态,不能续费"; got != want { t.Fatalf("validateRenewRow() = %q, want %q", got, want) } } func TestRenewPrepareSubmitParamUsesPrepareSourceBatchNo(t *testing.T) { t.Parallel() req := &batchimport.SubmitRequest{ BizParams: &model.TSimCardRenewBatchPrepareParam{SourceBatchNo: " OUT20260807001 "}, } got := renewPrepareSubmitParam(req) if got.SourceBatchNo != "OUT20260807001" { t.Fatalf("SourceBatchNo = %q, want OUT20260807001", got.SourceBatchNo) } } func TestRenewPrepareSubmitParamFallsBackToRequestSourceBatchNo(t *testing.T) { t.Parallel() req := &batchimport.SubmitRequest{ BizParams: &model.TSimCardRenewBatchSubmitParam{}, SourceBatchNo: " OUT20260807002 ", } got := renewPrepareSubmitParam(req) if got.SourceBatchNo != "OUT20260807002" { t.Fatalf("SourceBatchNo = %q, want OUT20260807002", got.SourceBatchNo) } } func TestPrepareProcessorValidateRowsDoesNotBlockSubmit(t *testing.T) { t.Parallel() rows := []batchimport.Row{ &Row{RowNo: 1, Iccid: "8986001"}, &Row{RowNo: 2, Iccid: "8986001"}, } if err := NewPrepareProcessor().ValidateRows(context.Background(), rows); err != nil { t.Fatalf("ValidateRows() error = %v", err) } for _, item := range rows { row := item.(*Row) if row.Reason != "" { t.Fatalf("row %d reason = %q, want empty before worker prepare", row.RowNo, row.Reason) } } }