package service import ( "testing" "time" "github.com/freefire/jiang13-bbs/model" "github.com/glebarez/sqlite" "gorm.io/gorm" ) // 贡献值口径:earnedPoints 只累计窗口内正入账积分(排除 bounty_refund), // 支出、悬赏退回、封禁用户、窗口外入账均不计 func TestEarnedPointsWindowAndExclusions(t *testing.T) { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) if err != nil { t.Fatalf("open sqlite: %v", err) } if err := db.AutoMigrate(&model.User{}, &model.PointLedger{}); err != nil { t.Fatalf("migrate: %v", err) } now := time.Now() weekAgo := now.AddDate(0, 0, -7) users := []*model.User{ {Username: "earner", Password: "x"}, {Username: "refund_only", Password: "x"}, {Username: "banned", Password: "x", Banned: true}, {Username: "old_earner", Password: "x"}, } for _, u := range users { if err := db.Create(u).Error; err != nil { t.Fatalf("seed user %s: %v", u.Username, err) } } a, d := users[0].ID, users[3].ID ledgers := []model.PointLedger{ {UserID: a, Delta: 5, Reason: model.PointReasonCheckin, Balance: 5, CreatedAt: now}, {UserID: a, Delta: 3, Reason: model.PointReasonReplyReward, Balance: 8, CreatedAt: now}, {UserID: a, Delta: 2, Reason: model.PointReasonStreakBonus, Balance: 10, CreatedAt: now.Add(-time.Hour)}, {UserID: a, Delta: -3, Reason: model.PointReasonUnlockPost, Balance: 7, CreatedAt: now}, // 支出不计 {UserID: users[1].ID, Delta: 8, Reason: model.PointReasonBountyRefund, Balance: 8, CreatedAt: now}, // 退回不计 {UserID: users[2].ID, Delta: 5, Reason: model.PointReasonCheckin, Balance: 5, CreatedAt: now}, // 封禁不计 {UserID: d, Delta: 5, Reason: model.PointReasonCheckin, Balance: 5, CreatedAt: weekAgo.Add(-time.Hour)}, // 窗口外 } if err := db.Create(&ledgers).Error; err != nil { t.Fatalf("seed ledgers: %v", err) } s := NewLeaderboardService(db) from := weekAgo pts, err := s.earnedPoints(&from, nil) if err != nil { t.Fatalf("earnedPoints: %v", err) } if len(pts) != 1 || pts[a] != 10 { t.Fatalf("周窗内应仅 earner 计 10 分,got %v", pts) } all, err := s.earnedPoints(nil, nil) if err != nil { t.Fatalf("earnedPoints(all): %v", err) } if len(all) != 2 || all[a] != 10 || all[d] != 5 { t.Fatalf("全窗口:earner=10、old_earner=5,退回/封禁不计,got %v", all) } }