udemy-go-web-1/internal/repository/dbrepo/pgc.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
}