Skip to content

Mohammed2372/Booking-Engine-API

Repository files navigation

🏨 Hotel Booking Engine API

Python Django PostgreSQL Redis Celery Stripe JWT Docker image

A robust, production-ready REST API for a hotel booking system. Features dynamic pricing, real-time inventory management, automated expiration of unpaid bookings ("Zombie Killer"), and secure payments via Stripe. Built with Django REST Framework, Celery, Redis, and Stripe.

πŸ“‹ Table of Contents


✨ Features

πŸ“… Booking & Inventory

  • Real-time Availability: Prevents double-booking using atomic database transactions.
  • Dynamic Pricing Engine: Calculates prices based on:
    • Date ranges (e.g., High Season)
    • Days of the week (e.g., Weekend rates)
    • Room types
  • The "Zombie Killer" Task: A background job (Celery) that automatically expires "Pending" bookings if they remain unpaid for more than 15 minutes, releasing inventory back to the pool.

πŸ’³ Payments (Stripe)

  • Payment Intents: Secure handling of payments using Stripe's modern API.
  • Webhooks: Listens for Stripe events to automatically confirm bookings upon successful payment.
  • "God Mode" Testing: A developer-only feature to instantly confirm payments via API without a frontend (for testing purposes).
  • Refund Handling: Logic for calculating refunds and penalties based on cancellation policies (48-hour rule).

πŸ›  Technical

  • Authentication: JWT (JSON Web Token) authentication.
  • Documentation: Auto-generated Swagger/OpenAPI docs via drf-spectacular.
  • Dockerized: Ready for containerized deployment.

🌊 API Flow Diagrams

Complete Booking Workflow

graph TD
    A[Client/Frontend] -->|1. Search Rooms| B[GET /api/search]
    B -->|Returns available rooms| A
    A -->|2. Create Booking| C[POST /api/book]
    C -->|Creates PENDING booking| D[(Database)]
    D -->|Status: PENDING| A

    A -->|3. Initiate Payment| E[POST /api/bookings/ID/checkout]
    E -->|Creates Stripe Intent| F[Stripe API]
    F -->|Returns client_secret| E
    E -->|Returns credentials| A

    A -->|4. Confirm Payment| F
    F -->|5. Payment Succeeded| G[Stripe Webhook]
    G -->|6. POST /api/webhook| H[Django Webhook Handler]
    H -->|Updates booking| D
    D -->|Status: CONFIRMED| H

    H -->|7. Response 200| G
    D -->|Booking confirmed| A
Loading

πŸš€ Quick Start (Docker) - Easiest Method

Use this method to run the entire system (Django, Postgres, Redis, Celery) instantly without installing any dependencies on your machine.

Prerequisites: Only Docker Desktop and Git.

πŸ’‘ Quick Download: Want to skip cloning the repository? You can pull the pre-built Docker image directly from Docker Hub:

docker pull mohammed237/booking-engine:v1

View image on Docker Hub for updates, documentation, and version history.

1. Clone & Setup Environment

# Clone the repository
git https://github.com/Mohammed2372/Booking-Engine-API.git
cd Booking-Engine-API

# Copy the example env file to create your local config
cp .env.example .env
# (On Windows use: copy .env.example .env)

# Open the .env file and fill in your specific keys:
# - SECRET_KEY
# - STRIPE Keys (Public, Secret, Webhook)

2. Run the Application

Run this single command to download the image, set up the database, and start the servers.

docker compose -f docker-compose.prod.yml up

3. Create Admin User (Optional)

To access the admin panel, create a superuser inside the running container:

docker compose -f docker-compose.prod.yml exec web python manage.py createsuperuser

πŸ’» Manual Development Setup

Use this method only if you are a developer contributing to the code and want to run services individually for debugging.

Prerequisites

  • Python 3.10+
  • PostgreSQL
  • Redis (for Celery)
  • Stripe CLI

1. Environment Setup

# Create virtual environment
python -m venv .venv
source .venv/bin/activate
# On Windows: .venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Create .env from example
cp .env.example .env

2. Install & Configure Services

You must install these manually if running outside Docker:

A. PostgreSQL

  • Install PostgreSQL for your OS.
  • Create a database named booking_db.
  • Update .env to set SQL_HOST=localhost.

B. Redis

  • Install Redis (brew install redis or download for Windows).
  • Ensure it is running on port 6379.
  • Update .env to set CELERY_BROKER=redis://localhost:6379/0.

C. Stripe CLI

  • Install Stripe CLI to forward webhooks to localhost.
  • Run stripe login.

3. Database Migrations

python manage.py migrate
python manage.py createsuperuser

4. Running Services (4 Terminal Windows Needed)

  1. Django Server: python manage.py runserver
  2. Celery Worker: celery -A core worker -l info
  3. Celery Beat: celery -A core beat -l info
  4. Stripe Listener: stripe listen --forward-to localhost:8000/api/webhook/

πŸ”§ Configuration Reference

Celery Configuration

Located in core/celery.py:

# Task routing
CELERY_TASK_ROUTES = {
    'bookings.tasks.expire_pending_bookings': {'queue': 'default'},
}

# Task time limits (prevent hanging tasks)
CELERY_TASK_TIME_LIMIT = 30 * 60  # 30 minutes hard limit
CELERY_TASK_SOFT_TIME_LIMIT = 25 * 60  # 25 minutes soft limit

# Celery Beat schedule (in core/settings.py)
CELERY_BEAT_SCHEDULE = {
    'expire-pending-bookings': {
        'task': 'bookings.tasks.expire_pending_bookings',
        'schedule': crontab(minute='*/1'),  # Every minute
    },
}

Stripe Configuration

Keys location: core/settings.py

STRIPE_SECRET_KEY = os.getenv("STRIPE_SECRET_KEY")
STRIPE_PUBLIC_KEY = os.getenv("STRIPE_PUBLIC_KEY")
STRIPE_WEBHOOK_KEY = os.getenv("STRIPE_WEBHOOK_KEY")

Webhook endpoint: POST /api/webhook/

πŸ§ͺ Testing Guide

1. The "Zombie Killer" Flow (Expired Bookings)

To test that bookings expire after 15 minutes:

  1. Create a Booking: POST to /api/book/. Status will be PENDING.
  2. Wait: Wait 16 minutes OR manually modify the created_at timestamp in DB.
  3. Check Status: The Celery Beat task runs every minute. It should update status to EXPIRED.
  4. Verify Inventory: You should be able to book the same room again immediately.

2. Stripe Payments (Backend Only / "God Mode")

We implemented a special testing flag to bypass the frontend card entry.

Endpoint: POST /api/bookings/{id}/checkout/

Request Body:

{
  "auto_confirm": true
}

Result: The server contacts Stripe, forces a test charge using a Visa mock, and instantly updates the booking to CONFIRMED.

3. Stripe Webhooks (Real Simulation)

To test the real integration where Stripe notifies Django:

  1. Start Stripe Listener:

    stripe listen --forward-to localhost:8000/api/webhook/
  2. Create a Booking normally (get the client_secret).

  3. Confirm via CLI (Simulates user paying on frontend):

    stripe payment_intents confirm pi_3Sk... --payment-method=pm_card_visa
  4. Verify: Check your terminal. The webhook should hit /api/webhook/ and you should see "βœ… Booking confirmed via Webhook."

4. Running Unit Tests

# Run specific bookings app tests
python manage.py test bookings

πŸ“š API Documentation

Once the server is running, visit:

Key Endpoints

Method Endpoint Description
GET /api/search/ Search available rooms
POST /api/book/ Create a new booking
GET /api/bookings/{id}/ Get booking details
POST /api/bookings/{id}/checkout/ Initiate payment
POST /api/bookings/{id}/cancel/ Cancel a booking
POST /api/webhook/ Stripe webhook handler
POST /api/auth/login/ JWT authentication

πŸ“ Project Structure

Booking Engine/                         # repository root
β”œβ”€β”€ .env.example                        # example env variables
β”œβ”€β”€ manage.py                           # Django management entrypoint
β”œβ”€β”€ README.md                           # this file
β”œβ”€β”€ requirements.txt                    # Python dependencies
β”‚
β”œβ”€β”€ authentication/                     # auth: registration & JWT
β”‚   β”œβ”€β”€ admin.py                        # Django admin registrations
β”‚   β”œβ”€β”€ models.py                       # auth-related models (users/profiles)
β”‚   β”œβ”€β”€ serializers.py                  # DRF serializers for auth
β”‚   β”œβ”€β”€ urls.py                         # endpoints: register/login/refresh
β”‚   └── views.py                        # registration & auth views
β”‚
β”œβ”€β”€ bookings/                           # booking domain logic
β”‚   β”œβ”€β”€ admin.py                        # admin for bookings/models
β”‚   β”œβ”€β”€ models.py                       # Booking, Reservation, etc.
β”‚   β”œβ”€β”€ serializers.py                  # DRF serializers for bookings
β”‚   β”œβ”€β”€ services.py                     # business logic & helpers
β”‚   β”œβ”€β”€ tasks.py                        # Celery tasks (e.g., expire bookings)
β”‚   β”œβ”€β”€ tests.py                        # unit tests for bookings
β”‚   β”œβ”€β”€ urls.py                         # booking-related endpoints
β”‚   └── views.py                        # booking API views
β”‚
β”œβ”€β”€ core/                               # project core settings & entrypoints
β”‚   β”œβ”€β”€ celery.py                       # Celery app configuration
β”‚   β”œβ”€β”€ settings.py                     # Django settings
β”‚   └── urls.py                         # root URL config (includes app urls)
β”‚
β”œβ”€β”€ inventory/                          # rooms, room types, availability
β”‚   β”œβ”€β”€ admin.py                        # admin for RoomType model
β”‚   β”œβ”€β”€ filters.py                      # DRF filters for search/listing
β”‚   β”œβ”€β”€ models.py                       # Room, RoomType, PricingRule models
β”‚   β”œβ”€β”€ serializers.py                  # DRF serializers for inventory
β”‚   β”œβ”€β”€ services.py                     # inventory helpers & pricing engine
β”‚   β”œβ”€β”€ urls.py                         # endpoints: room search
β”‚   └── views.py                        # search & listing rooms API views
β”‚
β”œβ”€β”€ payments/                           # Stripe payment integration
β”‚   β”œβ”€β”€ services.py                     # create payment intents, webhooks
β”‚   β”œβ”€β”€ urls.py                         # endpoints: webhook
β”‚   └── views.py                        # Stripe webhook handler
β”‚
└── user/                               # user profile & wishlist & reviews
    β”œβ”€β”€ admin.py                        # user profile, wishlist and reviews dashboards
    β”œβ”€β”€ models.py                       # Profile, Wishlist models
    β”œβ”€β”€ serializers.py                  # DRF serializers for user
    β”œβ”€β”€ urls.py                         # endpoints: profile, wishlist, review
    └── views.py                        # user API views