Skip to content

adamgracikowski/CarRental

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

77 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš— Car Rental System

ASP.NET Core C# EF Core SQL Server Microsoft Azure SendGrid Blazor WebAssembly Google Maps

CarRental is a full-stack car rental platform that aggregates rental offers from multiple third-party API providers πŸš€. It features a price comparison tool, allowing users to find the best deals.

The project was developed as part of the Web Application Development with .NET course during the winter semester of the 2024/2025 academic year.

πŸ“˜ Table of Contents

  1. πŸ“– Overview
  2. 🎯 Features
  3. πŸš€ Technologies Used
  4. πŸ—οΈ Solution Architecture
  5. ☁️ Cloud Services Architecture
  6. πŸ—„οΈ Database Schema
  7. 🧠 Key Patterns & Technologies
  8. πŸ§ͺ Unit Testing
  9. πŸ“˜ API Documentation
  10. πŸ‘₯ Authors

πŸ“– Overview

The goal of this project is to build a comprehensive πŸš— Car Rental System composed of two main components:

  • 🌐 Web Application
    Allows users to browse, filter, and compare rental prices from multiple car providers in one place.

  • πŸ”Œ Car Provider API
    Integrates with external vehicle‑rental services to manage available cars, reservations, and rental details.

The system is designed for flexibility and extensibility:

  • βž• New car providers can be added at any time via dedicated APIs, ensuring smooth scalability.
  • 🀝 Supports collaboration with other teams offering their own provider APIs, opening the door to future feature enhancements.

🎯 Features

πŸ‘‡ Click on any feature below to see it in action

πŸ“± User Views:


🏠 Home Page

Home Page

🚘 Vehicle Filters

Vehicle Filters

πŸ‘€ Profile Management

Profile Management

🟒 Active Rentals

Active Rentals

βœ… Returned Rentals

Returned Rentals

🧾 Offer Generation

Offer Generation

πŸ—ΊοΈ Google Maps Integration

Google Maps Integration

πŸ§‘β€πŸ’Ό Employee Views


🟒 Active Rentals

Active Rentals - Employee

⏳ Rentals Pending Return

Rentals Pending Return

βœ… Return Confirmation

Return Confirmation

πŸ“– Rental History

Rental History

πŸ“Š Excel Report Generation

Report Generation - Initial View

Excel Report - Table

Excel Report - Pivot Table

πŸ“§ Email Service


πŸ“© Rental Confirmation Email

Rental Confirmation Email

πŸ“¨ Rental Approved Email

Rental Approved Email

↩️ Return Started Email

Return Started Email

βœ… Rental Returned Email

Rental Returned Email

πŸš€ Technologies Used

🌐 Frontend

  • Blazor WebAssembly, MudBlazor, Microsoft Entra Id, GoogleMaps.

βš™οΈ Backend

  • ASP.NET Core, C#, Entity Framework Core, SQL Server, Azure Cache for Redis, SendGrid, Azure Blob Storage, Azure Key Vault, Application Insights.

πŸ—οΈ Solution Architecture

The solution consists of 11 modular projects, organized to ensure:

  • βœ”οΈ Clear code structure
  • πŸ”§ Easy maintenance
  • πŸš€ Expandability without breaking existing functionality

Below is an overview of the logical layers and their responsibilities:

πŸ”¨ Layer πŸ“ Description
Core πŸ“¦ Domain models and enums for car providers and the rental price comparer.
Persistence πŸ’Ύ Data access via Entity Framework Core and the repository pattern.
Infrastructure πŸ”— Business logic and integrations with external services (e.g. Azure Cache for Redis, Azure Blob Storage, Twilio SendGrid).
API 🌐 Exposes REST endpoints, handles authentication & authorization, and validates requests.
Web 🎨 Frontend built with Blazor WebAssembly, hosted as a static app on Azure Static Web Apps.
Tests πŸ§ͺ Unit tests to verify correctness of business logic and data access layers.

The diagrams illustrates the structure of how the projects are organized within the solution:

πŸ”— Project Dependencies Overview

graph TD
  A[CarRental.Comparer.Web]
  B[CarRental.Provider.Persistence] --> C[CarRental.Common.Core]
  D[CarRental.Comparer.Persistence] --> C
  E[CarRental.Provider.Infrastructure] --> B
  E --> F[CarRental.Common.Infrastructure]
  G[CarRental.Comparer.Infrastructure] --> F
  G --> D
  H[CarRental.Provider.API] --> E
  I[CarRental.Comparer.API] --> G
  J[CarRental.Provider.Tests] --> H
  K[CarRental.Comparer.Tests] --> I
Loading

πŸ“ Internal Module Architecture

graph TD
  subgraph CarRental.Common.Core
    A1[ComparerEntities]
    A2[Enums]
    A3[ProviderEntities]
  end

  subgraph CarRental.Common.Infrastructure
    B1[Configurations]
    B2[PipelineBehaviours]
    B3[Middlewares]
    B4[Providers]
    B5[Storages]
  end

  subgraph CarRental.Comparer.API
    C1[DTOs]
    C2[Authorization]
    C3[Controllers]
    C4[Profiles]
    C5[Validators]
    C6[Requests]
    C7[Pagination]
    C8[BackgroundJobs]
  end

  subgraph CarRental.Provider.API
    D1[DTOs]
    D2[Authorization]
    D3[Controllers]
    D4[Profiles]
    D5[Validators]
    D6[Requests]
  end

  subgraph CarRental.Provider.Infrastructure
    E1[Calculators]
    E2[EmailServices]
    E3[BackgroundJobs]
  end

  subgraph CarRental.Comparer.Infrastructure
    G1[HttpClients]
    G2[Providers]
    G3[Cache]
    G4[Reports]
    G5[CarProviders]
    G6[CarComparisons]
  end

  subgraph CarRental.Provider.Persistence
    H1[Specifications]
    H2[Configurations]
    H3[Migrations]
    H4[Options]
    H5[Data]
    H6[Repositories]
  end

  subgraph CarRental.Comparer.Persistence
    I1[Specifications]
    I2[Configurations]
    I3[Migrations]
    I4[Options]
    I5[Data]
    I6[Repositories]
  end

  %% --- ZALEŻNOŚCI LOGICZNE ---

  %% API β†’ Infrastructure
  C3 --> C1
  C3 --> C6
  C3 --> C5
  C3 --> C4
  C3 --> C2
  C6 --> G5
  C6 --> G6
  C8 --> G4
  C7 --> G3

  D3 --> D1
  D3 --> D6
  D3 --> D5
  D3 --> D4
  D3 --> D2
  D6 --> E1
  E3 --> E2

  %% Infrastructure β†’ Persistence
  G5 --> I6
  G6 --> I6
  G2 --> I6
  G4 --> I5
  G3 --> I4

  E1 --> H6
  E2 --> H5

  %% Persistence β†’ Core
  H6 --> A3
  I6 --> A1
  H1 --> A2
  I1 --> A2

  %% Common Infrastructure β†’ Core
  B4 --> A1
  B4 --> A3
  B2 --> A2
  B3 --> A2
  B5 --> A2

  %% API β†’ Common.Infrastructure
  C3 --> B3
  D3 --> B3
  C8 --> B5
  D3 --> B1
Loading

☁️ Cloud Services Architecture

πŸ‘‡ Click to see the diagram

πŸ” Diagram illustrating the cloud services architecture

Cloud Services Architecture Diagram

🧩 Resource Groups Breakdown

The system’s resources are organized into three Resource Groups for clarity and separation of responsibilities:

πŸ”– Resource Group πŸ› οΈ Service Name πŸ“¦ Type πŸ“ Description
carrental-provider-prod-rg carrental-provider App Service Hosts the Car Provider API (CRUD operations for vehicles, offers & reservations).
carrental-provider-kv Key Vault Secure storage for keys, passwords and other secrets.
carrental-provider-ai Application Insights Real‑time monitoring and diagnostics for the provider API.
CarRentalProviderDb SQL Database Relational database storing car provider data.
carrental-comparer-prod-rg carrental-comparer App Service Hosts the Price Comparer API (aggregates and compares rental offers).
carrental-comparer-kv Key Vault Secure storage for keys, passwords and other secrets.
carrental-comparer-ai Application Insights Monitoring and telemetry for the comparer API.
CarRentalComparerDb SQL Database Relational database powering the price comparison engine.
carrental-comparer-web Static Web App Frontend hosting for the price comparison UI.
carrental-common-prod-rg carrentalminisa Blob Storage Static file storage (e.g., vehicle images, brand logos).
carrental-cache Azure Cache for Redis Caching layer to accelerate read operations (e.g., search results).

πŸ—„οΈ Database Schema

The system uses Entity Framework Core to manage the database with a code-first approach 🧩. This means the database schema is automatically generated from your C# model classes, ensuring consistency between the application and the database.

  • In the development environment, we use Microsoft SQL Server running locally (localhost) πŸ–₯️.
  • In production, the solution is deployed on two Azure SQL Database instances β˜οΈβ€”one for the Car Provider API and one for the Price Comparer.

Below are the diagrams illustrating the database structures, table relationships, and key attributes:

πŸš— CarRentalProviderDb


erDiagram
  Insurance {
    int Id PK
    string Name
    string Description
    decimal PricePerDay
  }
  Segment {
    int Id PK
    int InsuranceId FK "Insurance"
    string Name
    string Description
    decimal PricePerDay
  }
  Model {
    int Id PK
    int MakeId FK "Make"
    int SegmentId FK "Segment"
    string Name
    int NumberOfDoors
    int NumberOfSeats
    EngineType EngineType
    WheelDriveType WheelDriveType
  }
  Make {
    int Id PK
    string Name
  }
  Car {
    int Id PK
    int ModelId FK "Model"
    int ProductionYear
    FuelType FuelType
    TransmissionType TransmissionType
    decimal Longitude
    decimal Latitude
    CarStatus Status
  }
  Offer {
    int Id PK
    int CarId FK "Car"
    DateTime GeneratedAt
    DateTime ExpiresAt
    decimal RentalPricePerDay
    decimal InsurancePricePerDay
    string Key
    string GeneratedBy
  }
  Rental {
    int Id PK
    int OfferId FK "Offer"
    int CustomerId FK "Customer"
    RenatlStatus Status
  }
  Customer {
    int Id PK
    string EmailAddress
    string FirstName
    string LastName
  }
  RentalReturn {
    int Id PK
    int RentalId FK "Rental"
    DateTime ReturnedAt
    string Description
    string Image
    decimal Longitude
    decimal Latitude
  }

  Insurance ||--o{ Segment : has
  Segment ||--o{ Model : categorizes
  Make ||--o{ Model : builds
  Model ||--o{ Car : includes
  Car ||--o{ Offer : offers
  Offer ||--o{ Rental : basedOn
  Customer ||--o{ Rental : rents
  Rental ||--o| RentalReturn : mightHave
Loading

πŸš— CarRentalComparerDb


erDiagram
  User {
    int Id PK
    string Name
    string LastName
    string Email
    DateTime Birthday
    DateTime DrivingLicenseDate
    decimal Longitude
    decimal Latitude
  }
  RentalTransaction {
    int Id PK
    int UserId FK "User"
    int ProviderId FK "Provider"
    int CarDetailsId FK "CarDetails"
    string RentalOuterId
    decimal RentalPricePerDay
    decimal InsurancePricePerDay
    DateTime RentedAt
    DateTime ReturnedAt
    decimal PricePerDay
    RentalTransactionStatus Status
    string Description
    string Image
  }
  Provider {
    int Id PK
    string Name
  }
  Employee {
    int Id PK
    int ProviderId FK "Provider"
    string FirstName
    string LastName
    string Email
  }
  CarDetails {
    int Id PK
    int OuterId
    string Make
    string Model
    string Segment
    string FuelType
    string TransmissionType
    int YearOfProduction
    int NumberOfDoors
    int NumberOfSeats
  }

  User ||--o{ RentalTransaction : rents
  Provider ||--o{ RentalTransaction : offers
  Provider ||--o{ Employee : employs
  CarDetails ||--o{ RentalTransaction : describes
Loading

🧠 Key Patterns & Technologies

To ensure modularity and scalability, the system leverages the following design patterns and libraries:

🀝 Mediator Pattern

Using MediatR, we implemented a mediator to handle communication between components, which:

  • πŸ”— Reduces direct dependencies between modules
  • 🎯 Centralizes request/command handling logic

βš–οΈ CQRS (Command Query Responsibility Segregation)

We separate operations into:

  • Commands: Modify system state (e.g. generate offers, create/return rentals, update user data)
  • Queries: Read-only operations (e.g. search available vehicles, fetch rental details)

This separation simplifies logic and improves code clarity.

πŸ—ƒοΈ Repository & Specification Patterns

With Ardalis.Specification, we introduced:

  • Repository Pattern: Abstracts data operations, decoupling business logic from data access
  • Specifications: Encapsulate query criteria in reusable classes for consistent querying

πŸ† Result Pattern

Using Ardalis.Result for standardized operation results:

  • βœ… Indicates success or failure
  • πŸ“ Provides error details (codes/messages)
  • 🚫 Minimizes exception usage in business logic for cleaner, more testable code

πŸ” User Authentication

Integrated Microsoft Entra ID for secure, single-sign‑on access:

  • πŸ§‘β€πŸ’Ό Users log in via SSO
  • πŸ”’ External service integration for robust access control

πŸ‘₯ Role-Based Access

Two main roles are defined:

  • Employee: Manages vehicles, reservations, and system administration
  • User: Browses available cars, compares offers, and rents vehicles

Each role has distinct permissions to enforce proper access control.

⏳ Background Jobs

Handled with Hangfire for asynchronous tasks such as:

  • ⏰ Marking offers as expired based on business rules
  • πŸ”„ Checking rental status updates

Hangfire offers easy scheduling, a web dashboard for monitoring, and seamless integration with Azure.

πŸ§ͺ Data & Request Validation

Employed FluentValidation to declare advanced validation rules:

  • πŸ” Ensures every business operation starts with validated input
  • πŸ“œ Improves readability and maintainability of validation logic

πŸ”„ Object Mapping

Used AutoMapper for rapid object-to-object mapping:

  • βœ‚οΈ Eliminates boilerplate conversion code
  • πŸ”„ Maintains consistent data structures across application layers

πŸ“Š Excel Reporting

Utilized ClosedXML to generate periodic Excel reports:

  • πŸ—οΈ Quickly create and format complex spreadsheets
  • πŸ“ˆ Build dynamic reports from database or runtime data
  • βž— Support advanced formulas and multiple data types for detailed analysis

πŸ§ͺ Unit Testing

The solution includes two dedicated test projects to ensure code quality and reliability:

The following libraries and frameworks are used for testing:

  • 🧰 xUnit: A streamlined testing framework for creating, running, and reporting unit tests.
  • βœ… FluentValidation: Automatically validates input models in tests, enabling precise validation checks.
  • πŸ€– Moq: A mocking library for creating fake objects, allowing isolated testing of business logic without external dependencies.

All tests follow the Arrange-Act-Assert pattern to maintain clarity and ease of debugging.

πŸ“˜ API Documentation

You can access the API docs for both the Car Provider and Price Comparer in your development environment:


πŸ‘‡ Click to see the Swagger UI examples


πŸ“‘ Comparer API Swagger UI

Comparer API Swagger UI

πŸ“‘ Provider API Swagger UI

Provider API Swagger UI

πŸ‘₯ Authors

This project was created by:

The course was taught by πŸŽ“ Marcin Sulecki.

About

Full-stack car rental platform that aggregates rental offers from multiple third-party API providers. It features a price comparison tool, allowing users to find the best deals.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors