package activity import ( "context" "testing" "bindbox-game/internal/repository/mysql/dao" "gorm.io/driver/sqlite" "gorm.io/gorm" ) func newRewardSnapshotTestService(t *testing.T) (*service, *dao.Query, *gorm.DB) { t.Helper() db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) if err != nil { t.Fatalf("open sqlite failed: %v", err) } if err := db.Exec(`CREATE TABLE products ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, price INTEGER NOT NULL, stock INTEGER NOT NULL, images_json TEXT, updated_at DATETIME, deleted_at DATETIME );`).Error; err != nil { t.Fatalf("create products failed: %v", err) } if err := db.Exec(`CREATE TABLE activity_reward_settings ( id INTEGER PRIMARY KEY AUTOINCREMENT, created_at DATETIME, updated_at DATETIME, issue_id INTEGER NOT NULL, product_id INTEGER, price_snapshot_cents INTEGER NOT NULL DEFAULT 0, price_snapshot_at DATETIME, weight INTEGER NOT NULL, quantity INTEGER NOT NULL, original_qty INTEGER NOT NULL, level INTEGER NOT NULL, sort INTEGER, is_boss INTEGER, min_score INTEGER NOT NULL DEFAULT 0, deleted_at DATETIME );`).Error; err != nil { t.Fatalf("create activity_reward_settings failed: %v", err) } q := dao.Use(db) svc := &service{readDB: q, writeDB: q} return svc, q, db } func TestCreateIssueRewards_SnapshotFromProductPrice(t *testing.T) { svc, q, db := newRewardSnapshotTestService(t) ctx := context.Background() if err := db.Exec("INSERT INTO products (id, name, price, stock, images_json) VALUES (101, 'A', 1000, 10, '[]')").Error; err != nil { t.Fatalf("insert product failed: %v", err) } err := svc.CreateIssueRewards(ctx, 88, []CreateRewardInput{ { ProductID: 101, Weight: 1, Quantity: 2, OriginalQty: 2, Level: 1, Sort: 1, IsBoss: 0, MinScore: 0, }, }) if err != nil { t.Fatalf("CreateIssueRewards failed: %v", err) } row, err := q.ActivityRewardSettings.WithContext(ctx).Where(q.ActivityRewardSettings.IssueID.Eq(88)).First() if err != nil { t.Fatalf("query reward failed: %v", err) } if row.PriceSnapshotCents != 1000 { t.Fatalf("expected snapshot=1000, got=%d", row.PriceSnapshotCents) } } func TestModifyIssueReward_ProductChanged_RecomputeSnapshot(t *testing.T) { svc, q, db := newRewardSnapshotTestService(t) ctx := context.Background() _ = db.Exec("INSERT INTO products (id, name, price, stock, images_json) VALUES (101, 'A', 1000, 10, '[]')").Error _ = db.Exec("INSERT INTO products (id, name, price, stock, images_json) VALUES (102, 'B', 2300, 10, '[]')").Error _ = db.Exec("INSERT INTO activity_reward_settings (id, issue_id, product_id, price_snapshot_cents, weight, quantity, original_qty, level, sort, is_boss, min_score) VALUES (1, 9, 101, 1000, 1, 1, 1, 1, 1, 0, 0)").Error newProductID := int64(102) if err := svc.ModifyIssueReward(ctx, 1, ModifyRewardInput{ProductID: &newProductID}); err != nil { t.Fatalf("ModifyIssueReward failed: %v", err) } row, err := q.ActivityRewardSettings.WithContext(ctx).Where(q.ActivityRewardSettings.ID.Eq(1)).First() if err != nil { t.Fatalf("query reward failed: %v", err) } if row.ProductID != 102 { t.Fatalf("expected product_id=102, got=%d", row.ProductID) } if row.PriceSnapshotCents != 2300 { t.Fatalf("expected snapshot=2300, got=%d", row.PriceSnapshotCents) } }