417 lines
11 KiB
Go
417 lines
11 KiB
Go
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
|
|
}
|