package adminuser import ( "errors" "strings" "testing" "hfb_sys/backend/internal/model" "gorm.io/driver/sqlite" "gorm.io/gorm" ) func TestDepositFreeQuotaAmountCent(t *testing.T) { tests := []struct { name string req DepositFreeQuotaRequest want int64 }{ { name: "使用分字段", req: DepositFreeQuotaRequest{AmountCent: 1234}, want: 1234, }, { name: "负分拒绝", req: DepositFreeQuotaRequest{AmountCent: -1}, want: -1, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := depositFreeQuotaAmountCent(tt.req); got != tt.want { t.Fatalf("depositFreeQuotaAmountCent() = %d, want %d", got, tt.want) } }) } } func TestParseBoolQuery(t *testing.T) { tests := []struct { name string value string want bool }{ {name: "true 开启", value: "true", want: true}, {name: "数字 1 开启", value: "1", want: true}, {name: "on 开启", value: "on", want: true}, {name: "空值关闭", value: "", want: false}, {name: "false 关闭", value: "false", want: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := parseBoolQuery(tt.value); got != tt.want { t.Fatalf("parseBoolQuery(%q) = %v, want %v", tt.value, got, tt.want) } }) } } func TestApplyUserFilterHasDepositFreeQuota(t *testing.T) { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{DryRun: true}) if err != nil { t.Fatalf("打开测试数据库失败:%v", err) } stmt := applyUserFilter(db.Table("users AS u"), ListQuery{ Status: "active", HasDepositFreeQuota: true, }).Find(&[]struct{}{}).Statement sql := stmt.SQL.String() if !strings.Contains(sql, "u.deposit_free_quota_cent > 0") { t.Fatalf("SQL 未包含免押额度过滤:%s", sql) } if len(stmt.Vars) != 1 || stmt.Vars[0] != "active" { t.Fatalf("筛选变量不正确:%v", stmt.Vars) } } func TestManualRealnameUpdatesUserRecordAndAudit(t *testing.T) { db := setupAdminUserTestDB(t) user := model.User{ Phone: "13900000001", Nickname: "待实名用户", RealnameStatus: "rejected", Status: "active", } if err := db.Create(&user).Error; err != nil { t.Fatalf("创建用户失败:%v", err) } repo := NewRepository(db) got, err := repo.ManualRealname(t.Context(), 99, user.ID, ManualRealnameRequest{ Name: "周奕男", IDNo: "130682200604080615", Reason: "第三方服务异常,客服人工核验通过", }, AuditMeta{IP: "127.0.0.1", UserAgent: "test", RequestID: "req-1"}) if err != nil { t.Fatalf("ManualRealname() error = %v", err) } if got.RealnameStatus != "verified" { t.Fatalf("用户实名状态 = %s, want verified", got.RealnameStatus) } var savedUser model.User if err := db.First(&savedUser, user.ID).Error; err != nil { t.Fatalf("查询用户失败:%v", err) } if savedUser.RealnameStatus != "verified" { t.Fatalf("数据库用户实名状态 = %s, want verified", savedUser.RealnameStatus) } var record model.UserRealname if err := db.Where("user_id = ?", user.ID).First(&record).Error; err != nil { t.Fatalf("查询实名记录失败:%v", err) } if record.Provider != "admin_manual" || record.Status != "verified" { t.Fatalf("实名记录不正确:provider=%s status=%s", record.Provider, record.Status) } if record.MaskedName != "周**" || record.MaskedIDNo != "1306**********0615" { t.Fatalf("脱敏信息不正确:name=%s id=%s", record.MaskedName, record.MaskedIDNo) } if record.EncryptedName != "周奕男" || record.EncryptedIDNo != "130682200604080615" { t.Fatalf("加密字段未写入:name=%s id=%s", record.EncryptedName, record.EncryptedIDNo) } if record.VerifiedAt == nil { t.Fatal("VerifiedAt 不能为空") } var audit model.AuditLog if err := db.Where("action = ?", "admin_user.manual_realname").First(&audit).Error; err != nil { t.Fatalf("查询审计日志失败:%v", err) } if audit.ActorID != 99 || audit.BizID == nil || *audit.BizID != user.ID { t.Fatalf("审计日志主体不正确:actor=%d biz=%v", audit.ActorID, audit.BizID) } if strings.Contains(string(audit.Detail), "130682200604080615") { t.Fatalf("审计日志不应包含完整身份证号:%s", string(audit.Detail)) } } func TestManualRealnameRejectsVerifiedUser(t *testing.T) { db := setupAdminUserTestDB(t) user := model.User{ Phone: "13900000002", Nickname: "已实名用户", RealnameStatus: "verified", Status: "active", } if err := db.Create(&user).Error; err != nil { t.Fatalf("创建用户失败:%v", err) } repo := NewRepository(db) _, err := repo.ManualRealname(t.Context(), 99, user.ID, ManualRealnameRequest{ Name: "周奕男", IDNo: "130682200604080615", }, AuditMeta{}) if !errors.Is(err, ErrRealnameAlreadyVerified) { t.Fatalf("ManualRealname() error = %v, want ErrRealnameAlreadyVerified", err) } } func setupAdminUserTestDB(t *testing.T) *gorm.DB { t.Helper() db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) if err != nil { t.Fatalf("打开测试数据库失败:%v", err) } if err := db.AutoMigrate( &model.User{}, &model.UserRealname{}, &model.AuditLog{}, &model.RentalOrder{}, &model.RentalListing{}, &model.Dispute{}, ); err != nil { t.Fatalf("数据库迁移失败:%v", err) } return db }