package dbrepo import ( "context" "errors" "go-udemy-web-1/internal/models" "go-udemy-web-1/internal/repository/sqlc" "time" "github.com/jackc/pgx/v5/pgtype" "golang.org/x/crypto/bcrypt" ) func (m *pgcDBRepo) AllUsers() bool { return true } // InsertReservation inserts a reservation into the database func (m *pgcDBRepo) InsertReservation(res models.Reservation) (int, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var newId int32 newId, err := m.Q.InsertReservation(ctx, sqlc.InsertReservationParams{ FirstName: res.FirstName, LastName: res.LastName, Email: res.Email, Phone: res.Phone, StartDate: pgtype.Date{Time: res.StartDate, Valid: true}, EndDate: pgtype.Date{Time: res.EndDate, Valid: true}, RoomID: int32(res.RoomID), CreatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, UpdatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, }) if err != nil { m.App.ErrorLog.Println(err) return 0, err } return int(newId), nil } // InsertRoomRestriction inserts a room restriction into the database func (m *pgcDBRepo) InsertRoomRestriction(r models.RoomRestriction) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.Q.InsertRoomRestriction(ctx, sqlc.InsertRoomRestrictionParams{ StartDate: pgtype.Date{Time: r.StartDate, Valid: true}, EndDate: pgtype.Date{Time: r.EndDate, Valid: true}, RoomID: int32(r.RoomID), ReservationID: pgtype.Int4{Int32: int32(r.ReservationID), Valid: true}, RestrictionID: int32(r.RestrictionID), CreatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, UpdatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, }) if err != nil { m.App.ErrorLog.Println(err) return err } return nil } // SearchAvailabilityByDatesByRoomID returns true if availability exists for roomID, and false if no availability func (m *pgcDBRepo) SearchAvailabilityByDatesByRoomID(start, end time.Time, roomID int) (bool, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() numRows, err := m.Q.SearchAvailabilityByDatesByRoomID(ctx, sqlc.SearchAvailabilityByDatesByRoomIDParams{ RoomID: int32(roomID), EndDate: pgtype.Date{Time: start, Valid: true}, StartDate: pgtype.Date{Time: end, Valid: false}, }) if err != nil { return false, err } if numRows == 0 { return false, nil } return true, nil } // SearchAvailabilityForAllRooms returns a slice of rooms, if any, for given date range func (m *pgcDBRepo) SearchAvailabilityForAllRooms(start, end time.Time) ([]models.Room, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var rooms []models.Room rows, err := m.Q.SearchAvailabilityForAllRooms(ctx, sqlc.SearchAvailabilityForAllRoomsParams{ EndDate: pgtype.Date{Time: start, Valid: true}, StartDate: pgtype.Date{Time: start, Valid: true}, }) if err != nil { return nil, err } for _, row := range rows { room := models.Room{ RoomName: row.RoomName, ID: int(row.ID), } rooms = append(rooms, room) } return rooms, nil } // GetRoomById gets a room by id func (m *pgcDBRepo) GetRoomById(id int) (models.Room, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var room models.Room row, err := m.Q.GetRoomById(ctx, int32(id)) if err != nil { return room, err } room = models.Room{ ID: int(row.ID), RoomName: row.RoomName, } return room, nil } // GetUserByID gets a user by id func (m *pgcDBRepo) GetUserByID(id int) (models.User, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var u models.User row, err := m.Q.GetUserByID(ctx, int32(id)) if err != nil { return u, err } u = models.User{ ID: int(row.ID), FirstName: row.FirstName, LastName: row.LastName, Email: row.Email, Password: row.Password, AccessLevel: int(row.AccessLevel), } return u, nil } // UpdateUser updates a user in the database func (m *pgcDBRepo) UpdateUser(u models.User) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.Q.UpdateUser(ctx, sqlc.UpdateUserParams{ FirstName: u.FirstName, LastName: u.LastName, Email: u.Email, AccessLevel: int32(u.AccessLevel), UpdatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, }) if err != nil { return err } return nil } // Authenticate authenticates a user func (m *pgcDBRepo) Authenticate(email, testPassword string) (int, string, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var id int var hashedPassword string row, err := m.Q.GetUserCred(ctx, email) if err != nil { return id, "", err } id = int(row.ID) hashedPassword = row.Password err = bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(testPassword)) if err == bcrypt.ErrMismatchedHashAndPassword { return 0, "", errors.New("incorrect password") } else if err != nil { return 0, "", err } return id, hashedPassword, nil } // AllReservations returns a slice of all reservations func (m *pgcDBRepo) AllReservations() ([]models.Reservation, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var reservations []models.Reservation rows, err := m.Q.AllReservations(ctx) if err != nil { return nil, err } for _, row := range rows { r := models.Reservation{ StartDate: row.StartDate.Time, EndDate: row.EndDate.Time, FirstName: row.FirstName, LastName: row.LastName, Email: row.Email, Phone: row.Phone, Room: models.Room{ID: int(row.RoomID), RoomName: row.RoomName.String}, ID: int(row.ID), RoomID: int(row.RoomID), Processed: int(row.Processed), } reservations = append(reservations, r) } return reservations, nil } // AllNewReservations returns a slice of all new reservations func (m *pgcDBRepo) AllNewReservations() ([]models.Reservation, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var reservations []models.Reservation rows, err := m.Q.AllNewReservations(ctx) if err != nil { return nil, err } for _, row := range rows { r := models.Reservation{ StartDate: row.StartDate.Time, EndDate: row.EndDate.Time, FirstName: row.FirstName, LastName: row.LastName, Email: row.Email, Phone: row.Phone, Room: models.Room{ID: int(row.RoomID), RoomName: row.RoomName.String}, ID: int(row.ID), RoomID: int(row.RoomID), Processed: int(row.Processed), } reservations = append(reservations, r) } return reservations, nil } // GetReservationByID returns one reservation by ID func (m *pgcDBRepo) GetReservationByID(id int) (models.Reservation, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var res models.Reservation row, err := m.Q.GetReservationByID(ctx, int32(id)) if err != nil { return res, err } res = models.Reservation{ StartDate: row.StartDate.Time, EndDate: row.EndDate.Time, FirstName: row.FirstName, LastName: row.LastName, Email: row.Email, Phone: row.Phone, Room: models.Room{ID: int(row.RoomID), RoomName: row.RoomName.String}, ID: int(row.ID), RoomID: int(row.RoomID), Processed: int(row.Processed), } return res, nil } // UpdateReservation updates a user in the database func (m *pgcDBRepo) UpdateReservation(r models.Reservation) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.Q.UpdateReservation(ctx, sqlc.UpdateReservationParams{ ID: int32(r.ID), FirstName: r.FirstName, LastName: r.LastName, Email: r.Email, Phone: r.Phone, UpdatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, }) if err != nil { return err } return nil } func (m *pgcDBRepo) DeleteReservation(id int) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.Q.DeleteReservation(ctx, int32(id)) if err != nil { return err } return nil } // UpdateProcessedForReservation set processed for a reservation func (m *pgcDBRepo) UpdateProcessedForReservation(id, processed int) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.Q.UpdateProcessedForReservation(ctx, sqlc.UpdateProcessedForReservationParams{ Processed: int32(processed), ID: int32(id), }) if err != nil { return err } return nil } func (m *pgcDBRepo) AllRooms() ([]models.Room, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var rooms []models.Room rows, err := m.Q.AllRooms(ctx) if err != nil { return nil, err } for _, row := range rows { room := models.Room{ RoomName: row.RoomName, ID: int(row.ID), } rooms = append(rooms, room) } return rooms, nil } // GetRestrictionsForRoomByDate returns restrictions for a room by date range func (m *pgcDBRepo) GetRestrictionsForRoomByDate(roomId int, start, end time.Time) ([]models.RoomRestriction, error) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var restrictions []models.RoomRestriction rows, err := m.Q.GetRestrictionsForRoomByDate(ctx, sqlc.GetRestrictionsForRoomByDateParams{ EndDate: pgtype.Date{Time: end, Valid: true}, StartDate: pgtype.Date{Time: start, Valid: true}, RoomID: int32(roomId), }) if err != nil { return restrictions, err } for _, row := range rows { r := models.RoomRestriction{ StartDate: row.StartDate.Time, EndDate: row.EndDate.Time, ID: int(row.ID), RoomID: int(row.RoomID), ReservationID: int(row.ReservationID), RestrictionID: int(row.RestrictionID), } restrictions = append(restrictions, r) } return restrictions, nil } // InsertBlockForRoom inserts a room restriction func (m *pgcDBRepo) InsertBlockForRoom(id int, startDate time.Time) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.Q.InsertBlockForRoom(ctx, sqlc.InsertBlockForRoomParams{ StartDate: pgtype.Date{Time: startDate, Valid: true}, EndDate: pgtype.Date{Time: startDate.AddDate(0, 0, 1)}, RoomID: int32(id), RestrictionID: 2, CreatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, UpdatedAt: pgtype.Timestamp{Time: time.Now(), Valid: true}, }) if err != nil { return err } return nil } // DeleteBlockByID deletes a block by ID func (m *pgcDBRepo) DeleteBlockByID(id int) error { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.Q.DeleteBlockByID(ctx, int32(id)) if err != nil { return err } return nil }