backend-service/internal/repositories/booking_repository.go
ats-tech25 98f4b4392d feat(booking): Implement comprehensive booking management functionality
- Add full implementation for booking handlers with complete CRUD operations
- Implement GetAvailableSlots endpoint to retrieve available booking time slots
- Add CreateBooking handler with robust error handling and validation
- Implement GetUserBookings endpoint to fetch user's booking history
- Add CancelBooking handler with specific error scenarios and authorization checks
- Integrate booking service and middleware for authentication and request processing
- Add support for date parsing and slot availability checking
- Enhance error responses with detailed error messages and appropriate HTTP status codes
- Integrate with existing authentication and middleware components
2025-11-05 16:35:36 +00:00

151 lines
4.1 KiB
Go

package repositories
import (
"errors"
"fmt"
"time"
"attune-heart-therapy/internal/models"
"gorm.io/gorm"
)
// bookingRepository implements the BookingRepository interface
type bookingRepository struct {
db *gorm.DB
}
// NewBookingRepository creates a new instance of BookingRepository
func NewBookingRepository(db *gorm.DB) BookingRepository {
return &bookingRepository{
db: db,
}
}
// Create creates a new booking in the database
func (r *bookingRepository) Create(booking *models.Booking) error {
if booking == nil {
return errors.New("booking cannot be nil")
}
if err := r.db.Create(booking).Error; err != nil {
return fmt.Errorf("failed to create booking: %w", err)
}
return nil
}
// GetByID retrieves a booking by its ID with user preloaded
func (r *bookingRepository) GetByID(id uint) (*models.Booking, error) {
if id == 0 {
return nil, errors.New("invalid booking ID")
}
var booking models.Booking
if err := r.db.Preload("User").First(&booking, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("booking with ID %d not found", id)
}
return nil, fmt.Errorf("failed to get booking by ID: %w", err)
}
return &booking, nil
}
// GetByUserID retrieves all bookings for a specific user with user preloaded
func (r *bookingRepository) GetByUserID(userID uint) ([]models.Booking, error) {
if userID == 0 {
return nil, errors.New("invalid user ID")
}
var bookings []models.Booking
if err := r.db.Preload("User").Where("user_id = ?", userID).
Order("scheduled_at DESC").Find(&bookings).Error; err != nil {
return nil, fmt.Errorf("failed to get bookings for user %d: %w", userID, err)
}
return bookings, nil
}
// Update updates an existing booking in the database
func (r *bookingRepository) Update(booking *models.Booking) error {
if booking == nil {
return errors.New("booking cannot be nil")
}
if booking.ID == 0 {
return errors.New("booking ID is required for update")
}
// Check if booking exists
var existingBooking models.Booking
if err := r.db.First(&existingBooking, booking.ID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("booking with ID %d not found", booking.ID)
}
return fmt.Errorf("failed to check booking existence: %w", err)
}
// Update the booking
if err := r.db.Save(booking).Error; err != nil {
return fmt.Errorf("failed to update booking: %w", err)
}
return nil
}
// Delete soft deletes a booking by its ID
func (r *bookingRepository) Delete(id uint) error {
if id == 0 {
return errors.New("invalid booking ID")
}
// Check if booking exists
var booking models.Booking
if err := r.db.First(&booking, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("booking with ID %d not found", id)
}
return fmt.Errorf("failed to check booking existence: %w", err)
}
// Soft delete the booking
if err := r.db.Delete(&booking).Error; err != nil {
return fmt.Errorf("failed to delete booking: %w", err)
}
return nil
}
// GetUpcomingBookings retrieves all upcoming bookings for notification scheduling
func (r *bookingRepository) GetUpcomingBookings() ([]models.Booking, error) {
var bookings []models.Booking
// Get bookings that are scheduled and in the future
if err := r.db.Preload("User").
Where("status = ? AND scheduled_at > ?", models.BookingStatusScheduled, time.Now()).
Order("scheduled_at ASC").
Find(&bookings).Error; err != nil {
return nil, fmt.Errorf("failed to get upcoming bookings: %w", err)
}
return bookings, nil
}
// GetByPaymentID retrieves a booking by its payment ID with user preloaded
func (r *bookingRepository) GetByPaymentID(paymentID string) (*models.Booking, error) {
if paymentID == "" {
return nil, errors.New("payment ID cannot be empty")
}
var booking models.Booking
if err := r.db.Preload("User").Where("payment_id = ?", paymentID).First(&booking).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("booking with payment ID %s not found", paymentID)
}
return nil, fmt.Errorf("failed to get booking by payment ID: %w", err)
}
return &booking, nil
}