diff --git a/internal/infrastructure/cardobservation/series_runner.go b/internal/infrastructure/cardobservation/series_runner.go index 0ee473aa..d3fffb64 100644 --- a/internal/infrastructure/cardobservation/series_runner.go +++ b/internal/infrastructure/cardobservation/series_runner.go @@ -475,10 +475,11 @@ func (r *SeriesRunner) loadCurrentICCIDs(ctx context.Context, payload cardapp.Se if err != nil { return nil, err } + // 显式列名:GORM 默认把 ICCID 映射成 icc_id,不写 tag 时三个值都读不到,本地预期判定永远不成立。 var current struct { - ICCID string - ICCID19 string - ICCID20 *string + ICCID string `gorm:"column:iccid"` + ICCID19 string `gorm:"column:iccid_19"` + ICCID20 *string `gorm:"column:iccid_20"` } err = r.db.WithContext(ctx).Table("tb_device_sim_binding AS binding"). Select("card.iccid, card.iccid_19, card.iccid_20"). diff --git a/internal/query/pollingalert/stop_refused.go b/internal/query/pollingalert/stop_refused.go index 80ec4963..b7309cd4 100644 --- a/internal/query/pollingalert/stop_refused.go +++ b/internal/query/pollingalert/stop_refused.go @@ -24,7 +24,7 @@ type StopRefusedFilter struct { type StopRefusedRow struct { ID uint CardID uint - ICCID string + ICCID string `gorm:"column:iccid"` // 显式列名:GORM 默认映射成 icc_id CarrierID uint CarrierName string DeviceID uint diff --git a/internal/query/pollingalert/stop_refused_columns_test.go b/internal/query/pollingalert/stop_refused_columns_test.go new file mode 100644 index 00000000..d2775199 --- /dev/null +++ b/internal/query/pollingalert/stop_refused_columns_test.go @@ -0,0 +1,20 @@ +package pollingalert + +import ( + "sync" + "testing" + + "gorm.io/gorm/schema" +) + +// GORM 默认把字段 ICCID 映射成 icc_id;查询选的是 a.iccid,必须显式指定列名,否则列表 ICCID 一直为空。 +func TestStopRefusedRowICCIDColumn(t *testing.T) { + s, err := schema.Parse(&StopRefusedRow{}, &sync.Map{}, schema.NamingStrategy{}) + if err != nil { + t.Fatalf("parse StopRefusedRow: %v", err) + } + field := s.LookUpField("ICCID") + if field == nil || field.DBName != "iccid" { + t.Fatalf("StopRefusedRow.ICCID column = %v, want iccid", field) + } +} diff --git a/internal/query/recorddisplay/columns_test.go b/internal/query/recorddisplay/columns_test.go new file mode 100644 index 00000000..7fc7df36 --- /dev/null +++ b/internal/query/recorddisplay/columns_test.go @@ -0,0 +1,29 @@ +package recorddisplay + +import ( + "sync" + "testing" + + "gorm.io/gorm/schema" +) + +// 防回归:不带 column tag 时 GORM 会把 ICCID 读成 icc_id 列。 +func TestDefaultNamingSplitsICCID(t *testing.T) { + type untagged struct{ ICCID string } + type tagged struct { + ICCID string `gorm:"column:iccid"` + } + for _, tc := range []struct { + name string + v any + want string + }{{"untagged", &untagged{}, "icc_id"}, {"tagged", &tagged{}, "iccid"}} { + s, err := schema.Parse(tc.v, &sync.Map{}, schema.NamingStrategy{}) + if err != nil { + t.Fatal(err) + } + if got := s.LookUpField("ICCID").DBName; got != tc.want { + t.Fatalf("%s: DBName = %q, want %q", tc.name, got, tc.want) + } + } +}