A comprehensive online movie ticket booking system built with NestJS
The Movie Theater Booking System is a backend web application developed with NestJS and TypeScript, providing RESTful APIs for cinema management, online ticket booking, and diverse payment processing. The system supports advanced features such as real-time seat booking, automated scheduling, and multiple payment gateway integrations.
- Movie Management: CRUD operations for movies with detailed information (actors, genres, versions)
- Cinema Management: Create and manage cinema rooms with seat layouts
- Smart Scheduling: Automatically generate schedules based on revenue and popularity
- Movie Versions: Support multiple versions (2D, 3D, IMAX, Dolby Atmos)
- Real-time Booking: WebSocket for real-time seat status updates
- Seat Management: Hold seats for 10 minutes during booking process
- Diverse Ticket Types: Regular, VIP, Couple seats with different pricing
- QR Code: Automatically generate QR codes for paid tickets
- MoMo: Popular e-wallet in Vietnam
- VNPay: Vietnamese banking payment gateway
- ZaloPay: Zalo e-wallet
- PayPal: International payment
- Stripe (Visa/Mastercard): Credit card payment
- Cash: Counter payment
- Registration/Login: Authentication system with JWT
- Google OAuth: Quick login with Google account
- Role Management: Admin, Employee, Customer with different permissions
- Points System: Accumulate and use reward points
- Overview Dashboard: Revenue statistics, ticket sales
- Order Management: View order details, refunds
- Email Notifications: Send confirmation and refund emails
- Promotion System: Create and manage discount codes
- Caching: Redis for performance optimization
- File Upload: AWS S3 for image storage
- Scheduled Tasks: Cron jobs for cleanup and automation
- WebSocket: Real-time communication
- API Documentation: Swagger/OpenAPI
- Backend Framework: NestJS 11.x
- Language: TypeScript 5.x
- Database: MySQL 2.x with TypeORM
- Cache: Redis (ioredis)
- Authentication: JWT + Passport
- File Storage: AWS S3
- Email: NodeMailer with Handlebars templates
- WebSocket: Socket.IO
- Payment: Multiple gateways integration
- Documentation: Swagger/OpenAPI
- Testing: Jest
src/
βββ common/ # Shared utilities & configurations
β βββ config/ # Application configuration
β βββ cron/ # Scheduled tasks & automation
β βββ decorator/ # Custom decorators
β βββ enums/ # Application enums
β βββ exceptions/ # Custom exceptions
β βββ gateways/ # WebSocket gateways
β βββ guards/ # Authentication & authorization guards
β βββ interceptors/ # Request/response interceptors
β βββ pagination/ # Pagination utilities
β βββ qrcode/ # QR code generation
β βββ redis/ # Redis configuration
β βββ s3/ # AWS S3 integration
β βββ utils/ # Helper functions
βββ database/ # Database entities & models
β βββ entities/
β βββ cinema/ # Cinema, Movie, Schedule entities
β βββ order/ # Order, Ticket, Transaction entities
β βββ user/ # User & authentication entities
β βββ item/ # Product & promotion entities
βββ modules/ # Feature modules
β βββ auth/ # Authentication & authorization
β βββ actor/ # Actor management
β βββ cinema-room/ # Cinema room management
β βββ gerne/ # Movie genres
β βββ movie/ # Movie management
β βββ order/ # Order processing & payment
β β βββ payment-method/ # Payment gateway integrations
β βββ schedule/ # Movie scheduling
β βββ seat/ # Seat management
β βββ ticket/ # Ticket management
β βββ member/ # User management
β βββ promotion/ # Promotion & discount system
β βββ overview/ # Dashboard & statistics
βββ template/ # Email templates
POST /auth/register # Register account
POST /auth/login # Login
POST /auth/google # Google OAuth login
POST /auth/refresh-token # Refresh JWT token
POST /auth/logout # Logout
GET /movies # List movies
GET /movies/:id # Movie details
POST /movies # Create new movie (Admin)
PUT /movies/:id # Update movie (Admin)
DELETE /movies/:id # Delete movie (Admin)
GET /cinema-rooms # List cinema rooms
POST /cinema-rooms # Create cinema room (Admin)
PUT /cinema-rooms/:id # Update cinema room (Admin)
GET /schedules # List schedules
GET /schedules/:id # Schedule details
POST /schedules # Create schedule (Admin)
PUT /schedules/:id # Update schedule (Admin)
GET /seats/room/:roomId # List seats by room
GET /schedule-seats/:scheduleId # Seat status by schedule
POST /order # Create order
GET /order # User's order list
GET /order/:id # Order details
PATCH /order/:id/cancel # Cancel order
POST /order/momo # MoMo payment
POST /order/vnpay # VNPay payment
POST /order/zalopay # ZaloPay payment
POST /order/paypal # PayPal payment
POST /order/visa # Stripe (Visa) payment
# Payment callbacks
GET /order/momo/return # MoMo callback
GET /order/vnpay/return # VNPay callback
GET /order/zalopay/return # ZaloPay callback
GET /order/paypal/return # PayPal callback
GET /order/visa/return # Stripe callback
GET /users/profile # Profile information
PUT /users/profile # Update profile
GET /users/booking-history # Booking history
GET /users/points # Accumulated points
GET /overview/dashboard # Overview dashboard
GET /overview/revenue # Revenue report
GET /overview/popular-movies # Popular movies
GET /overview/user-stats # User statistics
- Node.js >= 18.x
- MySQL >= 8.0
- Redis >= 6.0
- npm or yarn
git clone <repository-url>
cd Be_Nestjsnpm installCreate .env file with required environment variables:
# Database
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=your_username
DB_PASSWORD=your_password
DB_DATABASE=movie_theater
# JWT
JWT_SECRET=your_jwt_secret
JWT_REFRESH_SECRET=your_refresh_secret
# Redis
REDIS_PUBLIC_URL=redis://localhost:6379
# AWS S3
S3_ACCESS_KEY=your_s3_access_key
S3_SECRET_KEY=your_s3_secret_key
S3_REGION=your_s3_region
S3_BUCKET_NAME=your_bucket_name
# Email
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USER=your_email@gmail.com
MAIL_PASSWORD=your_app_password
# Payment Gateways
# MoMo
MOMO_ACCESS_KEY=your_momo_access_key
MOMO_SECRET_KEY=your_momo_secret_key
MOMO_PARTNER_CODE=your_partner_code
# VNPay
VNP_TMN_CODE=your_vnpay_tmn_code
VNP_HASH_SECRET=your_vnpay_hash_secret
VNP_URL=https://sandbox.vnpayment.vn/paymentv2/vpcpay.html
# ZaloPay
ZALO_APP_ID=your_zalopay_app_id
ZALO_KEY=your_zalopay_key
# PayPal
PAYPAL_CLIENT_ID=your_paypal_client_id
PAYPAL_CLIENT_SECRET=your_paypal_client_secret
# Stripe
VISA_PUBLIC_KEY=your_stripe_public_key
VISA_SECRET_KEY=your_stripe_secret_key
# Google OAuth
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret# Create database
npm run db:create
# Run migrations
npm run migration:runnpm run devnpm run build
npm run start:prod- API Server: http://localhost:3001
- API Documentation: http://localhost:3001/api
- WebSocket: ws://localhost:3001
npm run testnpm run test:covnpm run test:e2enpm run test:watch- Seat Booking: Real-time seat status updates
- Live Notifications: Order and payment notifications
- Admin Dashboard: Real-time statistics updates
The system automatically creates schedules based on:
- Revenue from the last 3 days for each movie
- Golden hours (6 PM - 9 PM) prioritize popular movies
- Optimize cinema room usage
- Runs daily at 2 AM
- Multi-gateway support: 6 different payment gateways
- Currency conversion: Automatic VND β USD conversion
- Payment verification: Signature and callback verification
- Refund system: Automatic refunds via API
- JWT Authentication: Access token + Refresh token
- Role-based Access Control: Admin, Employee, Customer
- API Rate Limiting: Request limit per IP
- Input Validation: Sanitize and validate all inputs
- CORS Protection: Secure CORS configuration
- Redis Caching: Cache hot data and sessions
- Database Indexing: Optimize query performance
- Pagination: Pagination for large lists
- Lazy Loading: Load relations when needed
- Connection Pooling: Optimize database connections
users # User information
βββ id (PK)
βββ email (unique)
βββ password_hash
βββ full_name
βββ phone_number
βββ role (admin/employee/customer)
βββ points
βββ is_verified
user_profiles # Extended profile
βββ user_id (FK)
βββ avatar_url
βββ date_of_birth
βββ gender
βββ addressmovies # Movie information
βββ id (PK)
βββ name
βββ description
βββ duration_minutes
βββ release_date
βββ poster_url
βββ trailer_url
βββ age_rating
βββ is_deleted
cinema_rooms # Cinema rooms
βββ id (PK)
βββ cinema_room_name
βββ is_deleted
seats # Seats
βββ id (PK)
βββ seat_row
βββ seat_column
βββ cinema_room_id (FK)
βββ seat_type_id (FK)
βββ is_deleted
schedules # Schedules
βββ id (PK)
βββ movie_id (FK)
βββ cinema_room_id (FK)
βββ version_id (FK)
βββ start_movie_time
βββ end_movie_time
βββ is_deletedorders # Orders
βββ id (PK)
βββ user_id (FK)
βββ total_prices
βββ status
βββ payment_method_id (FK)
βββ promotion_id (FK)
βββ created_at
βββ updated_at
order_details # Order details
βββ id (PK)
βββ order_id (FK)
βββ schedule_id (FK)
βββ ticket_id (FK)
βββ total_each_ticket
βββ created_at
tickets # Tickets
βββ id (PK)
βββ schedule_id (FK)
βββ seat_id (FK)
βββ ticket_type_id (FK)
βββ price
βββ qr_code
βββ status
βββ created_at
transactions # Payment transactions
βββ id (PK)
βββ order_id (FK)
βββ payment_gateway
βββ transaction_code
βββ amount
βββ status
βββ payment_url
βββ created_at{
"access_token": {
"user_id": "uuid",
"email": "user@example.com",
"role": "customer",
"exp": "timestamp"
},
"refresh_token": {
"user_id": "uuid",
"token_id": "uuid",
"exp": "timestamp"
}
}| Endpoint | Customer | Employee | Admin |
|---|---|---|---|
| Movies (Read) | β | β | β |
| Movies (Write) | β | β | β |
| Cinema Rooms (Read) | β | β | β |
| Cinema Rooms (Write) | β | β | β |
| Schedules (Read) | β | β | β |
| Schedules (Write) | β | β | β |
| Orders (Own) | β | β | β |
| Orders (All) | β | β | β |
| Dashboard | β | β | β |
| User Management | β | β | β |
- User selects seats β Check availability
- Hold seats for 10 minutes β Update status to 'HELD'
- User proceeds to payment β Create order with PENDING status
- Payment processing β Redirect to payment gateway
- Payment callback β Verify signature and update order
- Success: Mark seats as 'BOOKED', generate QR code, send email
- Failure: Release seats, mark order as 'FAILED'
// Cron job runs daily at 2 AM
@Cron('0 2 * * *')
async handleAutoScheduleMovies() {
// 1. Calculate revenue from last 3 days
const movieRevenue = await this.getMovieRevenue(3);
// 2. Allocate slots based on revenue percentage
const totalSlots = 20;
const movieSlotPlan = this.calculateSlotDistribution(movieRevenue, totalSlots);
// 3. Prioritize top movies during golden hours (6 PM - 9 PM)
// 4. Avoid schedule conflicts in the same room
// 5. Create schedules for tomorrow
}Each payment gateway implements AbstractPaymentService:
abstract class AbstractPaymentService {
abstract createOrder(orderData: OrderBillType): Promise<PaymentResponse>;
abstract handleReturn(query: any): Promise<string>;
abstract queryOrderStatus(orderId: string): Promise<PaymentStatus>;
// Shared business logic
protected async handleReturnSuccess(transaction: Transaction): Promise<string>;
protected async handleReturnFailed(transaction: Transaction): Promise<string>;
}- Application logs: NestJS Logger vα»i different levels
- Performance monitoring: Request duration tracking
- Error tracking: Custom exception filters
- Database queries: TypeORM query logging
- Cache hit rate: Redis performance metrics
GET /health/database # Check database connection
GET /health/redis # Check Redis connection
GET /health/s3 # Check AWS S3 connection
GET /health/payment # Check payment gateways
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3001
CMD ["npm", "run", "start:prod"]- Development: Local MySQL + Redis
- Staging: Docker Compose with separate services
- Production: Kubernetes cluster with LoadBalancer
- Fork repository
- Create feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Create Pull Request
- TypeScript: Strict mode enabled
- ESLint: Airbnb configuration with custom rules
- Prettier: Code formatting
- Commit messages: Conventional Commits format
- Testing: Minimum 80% coverage required
npm run lint # ESLint checking
npm run format # Prettier formatting
npm run test # Run unit tests
npm run build # Build verificationAfter running the application, access Swagger documentation at: http://localhost:3001/api
curl -X POST http://localhost:3001/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "password123",
"full_name": "Nguyen Van A",
"phone_number": "0123456789"
}'curl -X POST http://localhost:3001/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "password123"
}'curl -X GET "http://localhost:3001/movies?page=1&take=10" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"curl -X POST http://localhost:3001/order \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"schedule_id": 1,
"seats": ["R1_A1", "R1_A2"],
"payment_method_id": 2,
"promotion_id": null
}'Error: ER_ACCESS_DENIED_ERROR: Access denied for userSolution: Check username, password and MySQL access permissions
Error: connect ECONNREFUSED 127.0.0.1:6379Solution: Ensure Redis server is running
redis-server
# or
docker run -d -p 6379:6379 redis:alpineError: JsonWebTokenError: invalid tokenSolution: Check JWT_SECRET in .env file
Error: Invalid signatureSolution: Re-verify API keys and secret keys for payment gateways
# Run with debug logs
DEBUG=* npm run dev
# Or only NestJS logs
DEBUG=nest:* npm run dev- MoMo API Documentation
- VNPay API Documentation
- ZaloPay API Documentation
- PayPal API Documentation
- Stripe API Documentation
π¬ Made with β€οΈ for movie lovers