Skip to content

ModusTeam/cinema-platform-back

Repository files navigation

🎬 Cinema Platform API

Backend API for a Cinema Management System developed as part of the SoftServe Practice. This solution provides a comprehensive RESTful API for managing movies, sessions, halls, and ticket bookings using Clean Architecture principles.

.NET PostgreSQL Redis RabbitMQ Supabase SignalR Docker License

Frontend: Check out cinema-platform-front for the React + TypeScript client.


πŸ—οΈ Architecture & Tech Stack

The project follows Clean Architecture combined with the CQRS (Command Query Responsibility Segregation) pattern with Event-Driven Architecture.

Layer Technologies
API ASP.NET Core 8 Web API, Swagger/OpenAPI, SignalR
Application MediatR (CQRS), FluentValidation, Mapster, Domain Events
Domain Entities, Value Objects, Enums, Domain Exceptions, Result pattern
Infrastructure EF Core, PostgreSQL (Supabase), Redis, Refit (TMDB, Gemini), gRPC, Hangfire, Serilog
Messaging RabbitMQ, MassTransit (Event Bus)
Email SMTP (Gmail/custom), HTML templates, PDF attachments
Auth ASP.NET Core Identity, JWT (Access + Refresh Tokens)
Patterns Idempotency, Outbox, Repository, Unit of Work, Event-Driven
DevOps Docker & Docker Compose

πŸ“‚ Project Structure

Cinema.Api/                # Controllers, Middleware, SignalR Hubs, Entry Point
β”œβ”€β”€ Controllers/           # Account, Auth, Genres, Halls, Movies, Orders, Pricings, etc.
β”œβ”€β”€ Hubs/                 # TicketHub (SignalR real-time notifications)
β”œβ”€β”€ ExceptionHandlers/    # GlobalExceptionHandler
β”œβ”€β”€ Middleware/           # RequestLogContextMiddleware
└── Services/             # CurrentUserService, SignalRTicketNotifier, TicketNotificationWorker

Cinema.Application/        # Business Logic, CQRS Handlers, DTOs, Validators
β”œβ”€β”€ Account/              # Profile & password commands/queries
β”œβ”€β”€ Achievements/         # Achievements logic & queries
β”œβ”€β”€ Auth/                 # Login, Register, RefreshToken
β”œβ”€β”€ Genres/               # Genre CRUD
β”œβ”€β”€ Halls/                # Hall CRUD + technologies management
β”œβ”€β”€ Loyalty/              # Loyalty system integration and rules
β”œβ”€β”€ Movies/               # Movie CRUD + TMDB import + AI embeddings
β”œβ”€β”€ Orders/               # CreateOrder, CancelOrder, GetMyOrders, ValidateTicket
β”‚   β”œβ”€β”€ EventHandlers/    # OrderPaidIntegrationEventHandler (publishes to RabbitMQ)
β”‚   └── Services/         # OrderCheckoutOrchestrator for complex checkout sagas
β”œβ”€β”€ Pricings/             # Pricing CRUD + price calculation
β”œβ”€β”€ Seats/                # Seat types, locking logic
β”œβ”€β”€ Sessions/             # Session scheduling, reschedule, cancel
β”œβ”€β”€ Stats/                # Dashboard KPIs and analytics
β”œβ”€β”€ Technologies/         # Hall technologies (IMAX, 3D, Dolby Atmos)
β”œβ”€β”€ Users/                # Role management
β”œβ”€β”€ Jobs/                 # CancelExpiredOrdersJob (Hangfire recurring job)
└── Common/
    β”œβ”€β”€ Behaviours/       # ValidationBehavior, IdempotencyBehavior
    β”œβ”€β”€ Contracts/        # TicketPurchasedMessage (message contract)
    β”œβ”€β”€ Interfaces/       # IPaymentService, IPriceCalculator, ITicketNotifier, IEmailService, etc.
    └── Mappings/         # Mapster configuration

Cinema.Domain/             # Core: Entities, Value Objects, Enums, Events
β”œβ”€β”€ Entities/             # Movie, Hall, Session, Seat, Order, Ticket, Genre, Pricing, etc.
β”œβ”€β”€ Enums/                # MovieStatus, SeatStatus, SessionStatus, OrderStatus, TicketStatus
β”œβ”€β”€ Events/               # OrderPaidEvent (domain events)
└── Shared/               # Result<T>, Error, EntityId<T>

Cinema.Infrastructure/     # Data, Caching, External APIs, Identity, Messaging
β”œβ”€β”€ Persistence/
β”‚   β”œβ”€β”€ Configurations/   # EF Core entity configurations
β”‚   β”œβ”€β”€ Migrations/       # Database migrations
β”‚   └── ApplicationDbContext.cs
β”œβ”€β”€ Messaging/
β”‚   └── Consumers/        # TicketPurchased, TierUpgraded, PointsExpiring consumers
└── Services/             # Identity, Token, Redis SeatLocking, TMDB, Gemini, gRPC (Loyalty/Achievements), Payment, Email, etc.

πŸš€ Getting Started

Prerequisites

  • .NET 8.0 SDK
  • Docker Desktop
  • Supabase account (for PostgreSQL) or local PostgreSQL
  • Redis instance
  • RabbitMQ instance (for email notifications)
  • SMTP Server (Gmail or other) for email delivery

Option 1 β€” Docker Compose (Recommended)

Spins up the API, Redis, Redis Commander, and RabbitMQ:

  1. Create a .env file in the root directory:
SUPABASE_CONNECTION_STRING=Host=<your-supabase-host>;Database=postgres;Username=postgres;Password=<your-password>
REDIS_PASSWORD=your-redis-password
JWT_SECRET=your-super-secret-jwt-key-min-32-chars
RABBITMQ_HOST=rabbitmq
RABBITMQ_USER=admin
RABBITMQ_PASSWORD=admin123
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_SENDER_EMAIL=your-email@gmail.com
  1. Run:
docker-compose up -d --build

The API will be available at http://localhost:5000 and https://localhost:5001. RabbitMQ Management UI will be available at http://localhost:15672 (admin/admin123).

Option 2 β€” Run Locally

  1. Clone the repository:
git clone https://github.com/your-username/cinema-platform-backend.git
cd cinema-platform-backend
  1. Update appsettings.json:
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=localhost;Database=cinema;Username=postgres;Password=postgres",
    "RedisConnection": "localhost:6379"
  },
  "JwtSettings": {
    "Secret": "your-32-char-secret-key",
    "Issuer": "CinemaApi",
    "Audience": "CinemaClient"
  },
  "RabbitMQ": {
    "Host": "localhost",
    "Username": "guest",
    "Password": "guest"
  },
  "SmtpSettings": {
    "Host": "smtp.gmail.com",
    "Port": 587,
    "Username": "your-email@gmail.com",
    "Password": "your-app-password",
    "SenderEmail": "your-email@gmail.com"
  }
}
  1. Restore, migrate, and run:
dotnet restore
dotnet ef database update --project Cinema.Infrastructure --startup-project Cinema.Api
dotnet run --project Cinema.Api

πŸ—ΊοΈ Roadmap & Requirements

Progress tracking based on SoftServe Practice requirements.

πŸ‘€ Administrator

  • Movie Management β€” Create, update, delete movies (including TMDB import)
  • Session Management β€” Schedule sessions, detect overlaps, manage pricing policies
  • Hall Management β€” Configure halls, seat layouts, and technologies (IMAX, 3D, etc.)
  • Genre Management β€” CRUD operations for movie genres
  • Pricing Management β€” Create dynamic pricing policies with seat type multipliers
  • Sales Statistics β€” View sales stats and key metrics (KPIs dashboard)
  • AI Integration β€” Movie embeddings for semantic search
  • Loyalty Program β€” Manage users' points, VIP statuses, and view balances
  • Achievements β€” Create and manage platform achievements

πŸ‘€ Client

  • Browse Offers β€” View current movies and new releases
  • Schedule Filtering β€” View sessions with filters by date, time, and genre
  • Movie Details β€” Description, trailers, cast, ratings
  • Authentication β€” Registration and login via ASP.NET Core Identity
  • Ticket Booking β€” COMPLETE ORDER FLOW IMPLEMENTED
    • Seat locking via Redis distributed lock (10-min TTL)
    • Loyalty point discounts & VIP Gold Seat Upgrades
    • Order creation with payment processing
    • Automatic ticket generation
    • Order history (active & past orders)
    • Real-time ticket notifications via SignalR
    • Ticket validation system
    • Email notifications with PDF tickets πŸ“§
  • Order Management
    • View my orders
    • Cancel pending orders
    • Automatic expiration of unpaid orders (Hangfire job)
  • Personalized Recommendations β€” Based on AI embeddings and booking history
  • Loyalty & Achievements β€” Earn points, unlock VIP tiers, and gain achievements

πŸ”‘ Key Implementation Details

Complete Order & Payment Flow with Email Notifications

The system now implements a full end-to-end booking flow with asynchronous email delivery:

  1. Seat Selection β†’ User browses available sessions and seats
  2. Seat Locking β†’ Redis distributed lock (10-min TTL) prevents double-booking
  3. Price Calculation β†’ Dynamic pricing based on seat type and session pricing policy
  4. Order Creation β†’ CreateOrderCommand generates order with Pending status
  5. Loyalty Processing β†’ OrderCheckoutOrchestrator applies points discounts or Gold upgrades via gRPC
  6. Payment Processing β†’ IPaymentService handles payment (mock implementation included)
  7. Ticket Generation β†’ On payment success, tickets are auto-generated with Valid status
  8. Real-Time Notification β†’ SignalR pushes ticket data to client via TicketHub
  9. Event Publishing β†’ OrderPaidEvent triggers OrderPaidIntegrationEventHandler
  10. RabbitMQ Message β†’ TicketPurchasedMessage published to message queue
  11. Email Delivery β†’ TicketPurchasedConsumer generates PDF ticket and sends email via SMTP
  12. Order Expiration β†’ Hangfire job CancelExpiredOrdersJob auto-cancels unpaid orders

Event-Driven Architecture: The system uses domain events and RabbitMQ for decoupled communication:

  • OrderPaidEvent β†’ Domain event raised when payment succeeds
  • OrderPaidIntegrationEventHandler β†’ Publishes TicketPurchasedMessage to RabbitMQ
  • TicketPurchasedConsumer β†’ Consumes messages, generates PDF tickets, sends emails
  • TierUpgradedConsumer & PointsExpiringConsumer β†’ Listen to external loyalty service events

Orchestration (Saga Pattern): The OrderCheckoutOrchestrator manages complex checkout scenarios ensuring atomicity between database operations, payment processing, and gRPC calls (with compensation logic/refunds if failures occur).

Idempotency: Duplicate order requests are prevented via IdempotencyBehavior using request IDs.

Loyalty & Achievements (Microservices Integration)

  • gRPC Integration: Connects to an external Loyalty Service to handle user points, tiers, and achievements.
  • Resilience: OrderCheckoutOrchestrator gracefully degrades if the loyalty service is unavailable.
  • Features:
    • Earn points on purchases.
    • Pay with points or apply "Gold Upgrades" to standard seats for VIP users.
    • Track user achievements seamlessly through the unified API.

Email Notification System

  • Technology: SMTP (Gmail or custom server), MassTransit, RabbitMQ
  • Flow: Order payment β†’ RabbitMQ message β†’ Consumer generates PDF β†’ Email sent
  • Features:
    • HTML email templates
    • PDF ticket attachments with QR codes
    • Download links for tickets
    • Personalized greeting (user's name)
    • Movie, session, and seat information
  • Resilience: Retry logic via MassTransit for failed email deliveries

RabbitMQ Integration

  • Message Broker: RabbitMQ with MassTransit abstraction
  • Message Contract: TicketPurchasedMessage (OrderId, UserEmail, UserName, MovieTitle, SessionTime, SeatInfo, TotalPrice, DownloadUrl)
  • Consumer: TicketPurchasedConsumer handles ticket generation and email sending
  • Configuration: Automatic queue and exchange creation via MassTransit
  • Management UI: Available at http://localhost:15672 in Docker setup

Seat Locking System

  • Technology: Redis with distributed locks (StackExchange.Redis)
  • TTL: 10 minutes (configurable in RedisSeatLockingService)
  • Resilience: Polly retry policy with exponential backoff
  • Key Format: seat_lock:{sessionId}:{seatId}
  • Auto-Release: Locks expire automatically if payment isn't completed

TMDB Integration

Movies can be imported directly from The Movie Database by ID via the Refit HTTP client. Cast, posters, genres, and details are pulled automatically. Background import jobs are handled by Hangfire.

AI-Powered Features

  • Embeddings: Google Gemini API generates embeddings for movies
  • Semantic Search: Find similar movies based on plot, themes, and content
  • Recommendations: Personalized suggestions based on user preferences
  • Analytics: AI-enhanced analytics for movie performance

Pricing System

  • Dynamic Pricing: Admin creates pricing policies with base prices
  • Seat Type Multipliers: Different seat types (Standard, VIP, Premium) apply multipliers
  • Price Calculator: IPriceCalculator interface calculates final ticket prices
  • Session-Level Pricing: Each session can use a different pricing policy

Session Conflict Detection

The scheduling service checks for time-slot overlaps within the same hall before allowing a new session to be created or an existing one to be rescheduled.

Authentication & Authorization

  • Registration: Users register with email/password via ASP.NET Core Identity
  • Login: Returns short-lived Access Token (JWT, 60-min) + long-lived Refresh Token (stored in DB)
  • Token Refresh: Secure token rotation via /api/auth/refresh
  • Roles: Admin and User roles with role-based endpoint protection

Real-Time Features (SignalR)

  • Hub: TicketHub at /hubs/ticket
  • Events: TicketCreated, OrderStatusChanged
  • Client Integration: Frontend subscribes to receive instant ticket updates after payment

Background Jobs (Hangfire)

  • CancelExpiredOrdersJob: Runs every 5 minutes to cancel orders that remain Pending past expiration time
  • Dashboard: Hangfire dashboard available at /hangfire (dev environment)

Object Mapping

  • Mapster: High-performance object-to-object mapper
  • Configuration: Mapping profiles in Cinema.Application/Common/Mappings/
  • Usage: entity.Adapt<Dto>() for clean, type-safe transformations

πŸ“‘ API Endpoints Overview

Movies

  • GET /api/movies β€” List movies with pagination & filters
  • GET /api/movies/{id} β€” Get movie details
  • POST /api/movies β€” Create movie (Admin)
  • PUT /api/movies/{id} β€” Update movie (Admin)
  • DELETE /api/movies/{id} β€” Delete movie (Admin)
  • POST /api/movies/import β€” Import from TMDB (Admin)
  • GET /api/movies/{id}/similar β€” Get similar movies (AI-powered)

Sessions

  • GET /api/sessions β€” List sessions with filters
  • GET /api/sessions/{id} β€” Get session details
  • POST /api/sessions β€” Create session (Admin)
  • PUT /api/sessions/{id}/reschedule β€” Reschedule (Admin)
  • PUT /api/sessions/{id}/cancel β€” Cancel session (Admin)

Seats & Locking

  • POST /api/seats/lock β€” Lock a seat for booking (authenticated)
  • PUT /api/seats/{id}/type β€” Change seat type (Admin)

Orders & Tickets

  • POST /api/orders β€” Create order (purchase tickets)
  • GET /api/orders β€” Get my orders
  • GET /api/orders/{id} β€” Get order details
  • PUT /api/orders/{id}/cancel β€” Cancel order
  • GET /api/tickets/{id} β€” Get ticket details
  • GET /api/tickets/{orderId}/download β€” Download PDF ticket
  • POST /api/tickets/{id}/validate β€” Validate ticket (Admin)

Halls & Technologies

  • GET /api/halls β€” List halls
  • POST /api/halls β€” Create hall (Admin)
  • GET /api/technologies β€” List technologies (IMAX, 3D, etc.)

Genres

  • GET /api/genres β€” List genres
  • POST /api/genres β€” Create genre (Admin)

Loyalty & Achievements

  • GET /api/admin/loyalty/users β€” List users with loyalty tiers (Admin)
  • POST /api/admin/loyalty/modify-points β€” Modify user points (Admin)
  • POST /api/admin/loyalty/users/{id}/vip β€” Grant VIP status (Admin)
  • GET /api/achievements/me β€” Get my achievements
  • GET /api/achievements β€” List achievements (Admin)

Pricings

  • GET /api/pricings β€” List pricing policies
  • POST /api/pricings β€” Create pricing (Admin)

Statistics (Admin)

  • GET /api/stats/kpi β€” Get dashboard KPIs
  • GET /api/stats/occupancy β€” Get occupancy rates
  • GET /api/stats/revenue β€” Get revenue statistics

Auth & Account

  • POST /api/auth/register β€” Register new user
  • POST /api/auth/login β€” Login (returns JWT + Refresh Token)
  • POST /api/auth/refresh β€” Refresh access token
  • GET /api/account/profile β€” Get my profile
  • PUT /api/account/profile β€” Update profile
  • PATCH /api/account/profile/date-of-birth β€” Set my date of birth (one-time)
  • POST /api/account/change-password β€” Change password

πŸ§ͺ Testing

Postman Collection

A complete automated test suite is included: Cinema Booking Flow (Auto).postman_collection.json

Test Flow:

  1. Login β†’ Get JWT token
  2. Get Sessions β†’ Find OpenForSales session
  3. Get Hall Seats β†’ Pick 2 Active seats
  4. Lock Seat 1 & 2 β†’ Redis locks with 10-min TTL
  5. Create Order β†’ Process payment, generate tickets, send email
  6. Check Email β†’ Receive PDF ticket attachment
  7. Get My Orders β†’ Verify order + save ticketId
  8. Get Ticket Details β†’ View ticket with QR code

Environment Variables Required:

  • baseUrl: http://localhost:5000
  • email: Your test user email
  • password: Your test user password

🐳 Docker Deployment

The docker-compose.yaml includes:

  • cinema-api: Main .NET 8 API container
  • redis: Redis cache with password protection
  • redis-commander: Web UI for Redis at http://localhost:8081
  • rabbitmq: Message broker with management UI at http://localhost:15672

Environment Variables (in .env file):

  • SUPABASE_CONNECTION_STRING β€” PostgreSQL connection string
  • REDIS_PASSWORD β€” Redis password
  • JWT_SECRET β€” JWT signing key (min 32 chars)
  • RABBITMQ_HOST β€” RabbitMQ host
  • RABBITMQ_USER β€” RabbitMQ username
  • RABBITMQ_PASSWORD β€” RabbitMQ password
  • SMTP_HOST β€” SMTP server host
  • SMTP_PORT β€” SMTP server port
  • SMTP_USERNAME β€” SMTP username
  • SMTP_PASSWORD β€” SMTP password
  • SMTP_SENDER_EMAIL β€” Sender email address
  • Grpc__LoyaltyServiceUrl β€” URL for the external Loyalty gRPC Service

πŸ”„ Database Migrations & Seeding in Production

In Production (ASPNETCORE_ENVIRONMENT=Production), database migrations and identity seeding are not executed automatically on API startup to ensure zero-downtime and safe deployment practices. Instead, they are run as separate steps:

1. Database Migrations (cinema-migrator)

Migrations are run using a separate container (e.g. cinema-migrator) that executes dotnet ef database update.

2. Database Seeding (cinema-seeder)

Seeding of default Identity roles (Admin, User) and the default admin user is executed via a separate one-off job container cinema-seeder.

Configuration / Environment Variables

The seeder is controlled by the following environment variables (which can be defined in your .env file):

  • SEED__RUN (bool) β€” Enables/disables execution of the seeder. Defaults to true in Development and false in Production. It must be explicitly set to true in Production for seeding to run.
  • SEED__MODE (bool) β€” Sets the API into CLI seeding mode. If true or the command line flag --seed is passed, the API runs seeding and exits immediately with code 0 (or 1 on error).
  • SEED_ADMIN__EMAIL (string) β€” The email address of the default Admin user to create.
  • SEED_ADMIN__PASSWORD (string) β€” The password for the default Admin user.
  • SEED_ADMIN__FIRSTNAME (string, optional) β€” First name of the Admin user (defaults to System).
  • SEED_ADMIN__LASTNAME (string, optional) β€” Last name of the Admin user (defaults to Admin).

Running with Docker Compose

You can run the seeding process using the cinema-seeder service defined in docker-compose.yaml:

# Start the seeder manually (it will wait for the database and exit once done)
docker compose run --rm cinema-seeder

Or pass variables explicitly if you want to override them:

docker compose run --rm -e SEED_ADMIN__EMAIL=admin@example.com -e SEED_ADMIN__PASSWORD=SecretPassword123! cinema-seeder

πŸ“§ Email Configuration

Gmail Setup

  1. Enable 2-factor authentication on your Google account
  2. Generate an App Password: Google Account β†’ Security β†’ App passwords
  3. Use the app password in SMTP_PASSWORD environment variable

Custom SMTP Server

Configure any SMTP server in appsettings.json:

{
  "SmtpSettings": {
    "Host": "smtp.yourserver.com",
    "Port": 587,
    "Username": "your-username",
    "Password": "your-password",
    "SenderEmail": "noreply@yourcinema.com"
  }
}

πŸ”„ Event-Driven Architecture

Domain Events

  • OrderPaidEvent β€” Raised when order payment is successful
  • Handled by multiple handlers:
    • OrderPaidEventHandler β€” Updates seat status
    • OrderPaidIntegrationEventHandler β€” Publishes to RabbitMQ

Integration Events (RabbitMQ)

  • TicketPurchasedMessage β€” Message contract for ticket purchases
  • Published by: OrderPaidIntegrationEventHandler
  • Consumed by: TicketPurchasedConsumer
  • Content: Order details, user info, movie info, download URL

Benefits

  • Decoupling: Email sending doesn't block order processing
  • Reliability: RabbitMQ ensures message delivery
  • Scalability: Multiple consumers can process emails in parallel
  • Resilience: Automatic retries for failed deliveries

πŸ“œ License

This project is licensed under the MIT License.

About

SoftServe Practice Project // Backend Part

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors