| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- package repository
- import (
- "context"
- "errors"
- "testing"
- "time"
- "github.com/jackc/pgx/v5/pgconn"
- "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models"
- )
- func TestBookingRepo_Create_CalculatesTotalPrice(t *testing.T) {
- if testPool == nil {
- t.Skip("DATABASE_URL_TEST not set")
- }
- cleanTables(t, "bookings", "places", "users")
- user := insertTestUser(t)
- rate := 1000
- place := insertTestPlace(t, user.ID, &rate)
- repo := NewBookingRepo(testPool)
- start := time.Now().Truncate(time.Hour).Add(2 * time.Hour)
- end := start.Add(3 * time.Hour)
- booking := &models.Booking{
- PlaceID: place.ID,
- UserID: user.ID,
- StartTime: start,
- EndTime: end,
- }
- if err := repo.Create(context.Background(), booking); err != nil {
- t.Fatalf("Create: %v", err)
- }
- if booking.ID == "" {
- t.Fatal("expected non-empty booking ID")
- }
- if booking.TotalPrice == nil {
- t.Fatal("expected TotalPrice to be calculated")
- }
- expected := 1000 * 3 // 1000 RUB/h * 3h
- if *booking.TotalPrice != expected {
- t.Errorf("TotalPrice = %d, want %d", *booking.TotalPrice, expected)
- }
- if booking.Currency != "RUB" {
- t.Errorf("Currency = %s, want RUB", booking.Currency)
- }
- if booking.Status != "pending" {
- t.Errorf("Status = %s, want pending", booking.Status)
- }
- }
- func TestBookingRepo_Create_NoPriceForNonStudio(t *testing.T) {
- if testPool == nil {
- t.Skip("DATABASE_URL_TEST not set")
- }
- cleanTables(t, "bookings", "places", "users")
- user := insertTestUser(t)
- place := insertTestPlace(t, user.ID, nil)
- place.Type = "place"
- repo := NewBookingRepo(testPool)
- start := time.Now().Truncate(time.Hour).Add(2 * time.Hour)
- end := start.Add(3 * time.Hour)
- booking := &models.Booking{
- PlaceID: place.ID,
- UserID: user.ID,
- StartTime: start,
- EndTime: end,
- }
- if err := repo.Create(context.Background(), booking); err != nil {
- t.Fatalf("Create: %v", err)
- }
- if booking.TotalPrice != nil {
- t.Errorf("TotalPrice = %d, want nil (place without hourly_rate)", *booking.TotalPrice)
- }
- }
- func TestBookingRepo_Create_PlaceNotFound(t *testing.T) {
- if testPool == nil {
- t.Skip("DATABASE_URL_TEST not set")
- }
- cleanTables(t, "bookings")
- repo := NewBookingRepo(testPool)
- booking := &models.Booking{
- PlaceID: "00000000-0000-0000-0000-000000000000",
- UserID: "00000000-0000-0000-0000-000000000000",
- StartTime: time.Now(),
- EndTime: time.Now().Add(1 * time.Hour),
- }
- err := repo.Create(context.Background(), booking)
- if !errors.Is(err, ErrPlaceNotFound) {
- t.Errorf("expected ErrPlaceNotFound, got %v", err)
- }
- }
- func TestBookingRepo_Create_OverlapRejected(t *testing.T) {
- if testPool == nil {
- t.Skip("DATABASE_URL_TEST not set")
- }
- cleanTables(t, "bookings", "places", "users")
- user := insertTestUser(t)
- rate := 500
- place := insertTestPlace(t, user.ID, &rate)
- repo := NewBookingRepo(testPool)
- start := time.Now().Truncate(time.Hour).Add(5 * time.Hour)
- end := start.Add(2 * time.Hour)
- // First booking succeeds
- b1 := &models.Booking{
- PlaceID: place.ID,
- UserID: user.ID,
- StartTime: start,
- EndTime: end,
- }
- if err := repo.Create(context.Background(), b1); err != nil {
- t.Fatalf("first booking: %v", err)
- }
- // Overlapping booking fails with 23P01 (exclusion constraint)
- b2 := &models.Booking{
- PlaceID: place.ID,
- UserID: user.ID,
- StartTime: start.Add(30 * time.Minute),
- EndTime: end.Add(30 * time.Minute),
- }
- err := repo.Create(context.Background(), b2)
- if err == nil {
- t.Fatal("expected error for overlapping booking, got nil")
- }
- var pgErr *pgconn.PgError
- if !errors.As(err, &pgErr) || pgErr.Code != "23P01" {
- t.Errorf("expected 23P01 exclusion violation, got: %v", err)
- }
- }
- func TestBookingRepo_Create_SameSlotDifferentPlace(t *testing.T) {
- if testPool == nil {
- t.Skip("DATABASE_URL_TEST not set")
- }
- cleanTables(t, "bookings", "places", "users")
- user := insertTestUser(t)
- rate := 500
- p1 := insertTestPlace(t, user.ID, &rate)
- p2 := insertTestPlace(t, user.ID, &rate)
- repo := NewBookingRepo(testPool)
- start := time.Now().Truncate(time.Hour).Add(10 * time.Hour)
- end := start.Add(2 * time.Hour)
- b1 := &models.Booking{PlaceID: p1.ID, UserID: user.ID, StartTime: start, EndTime: end}
- if err := repo.Create(context.Background(), b1); err != nil {
- t.Fatalf("first booking: %v", err)
- }
- b2 := &models.Booking{PlaceID: p2.ID, UserID: user.ID, StartTime: start, EndTime: end}
- if err := repo.Create(context.Background(), b2); err != nil {
- t.Fatalf("same slot different place: %v", err)
- }
- }
|