Skip to content

ertugruldege/order-processing-system

Repository files navigation

System Architecture & Workflow

Overview

This project implements an Order Management System with an integrated Discount Module using the Chain of Responsibility pattern. It ensures scalability, efficiency, and data consistency through technologies like Symfony, RabbitMQ, Docker, PostgreSQL, Nginx, and Supervisor.

Key Features:

  • Asynchronous Order Processing: Orders are processed using Symfony Messenger and RabbitMQ for reliable and efficient handling.
  • FIFO Queue Handling: Orders are processed in a first-in, first-out manner to prevent race conditions.
  • Discount Rules Engine: Uses Chain of Responsibility to apply multiple discount rules dynamically.
  • DTO-based Validation: Ensures data integrity by validating requests with Symfony DTOs and constraints.
  • Dockerized Infrastructure: Consistent Local & Production Environment Using Docker & Docker Compose
  • Supervised Background Processing: Supervisor manages long-running Symfony Messenger consumers.

1. Order Processing Flow

  1. A new order request is received via the REST API.
  2. The order is placed in the order_create queue (RabbitMQ) for asynchronous processing.
  3. Symfony Messenger Consumer retrieves the message and starts processing.
  4. The system validates stock availability and creates the order.
  5. If stock is sufficient, the system reduces stock levels and sets the order status to CREATED.
  6. If stock is insufficient, the order is still created but marked as FAILED.
  7. After successful processing, an OrderCreatedMessage is dispatched.

Preventing Race Conditions:

  • RabbitMQ is configured for FIFO processing using:
    • x-single-active-consumer: true (Ensures only one worker processes a queue at a time).

2. Discount Processing Flow

The discount module follows the Chain of Responsibility Pattern:

  1. The DiscountProcessor iterates through registered discount rules.
  2. Applicable rules update the discount context, modifying the subtotal.
  3. Each rule operates on the updated values from previous discounts.

Example Discount Rules:

Rule Name Condition Applied Discount
BUY_6_GET_1 Buy 6 items from category 2 1 item free
10_PERCENT_OVER_1000 Order total is over 1000 10% off total
CHEAPEST_20_PERCENT Buy 2+ items from category 1 20% off the cheapest

Example Discount Calculation:

{
    "orderId": 5,
    "originalTotal": "2000.00",
    "discounts": [
        {
            "discountReason": "BUY_6_GET_1",
            "discountAmount": "100.00",
            "subtotal": "1900.00"
        },
        {
            "discountReason": "10_PERCENT_OVER_1000",
            "discountAmount": "190.00",
            "subtotal": "1710.00"
        }
    ],
    "totalDiscount": "290.00",
    "discountedTotal": "1710.00"
}

3. Project Structure

├── src/
│   ├── Controller/API
│   │   ├── ApiController.php                     # API Base Controller
│   │   ├── OrderController.php                   # API Endpoints for orders
│   │   ├── OrderDiscountController.php           # API Endpoints for order discounts
│   ├── Services/
│   │   ├── Order/
│   │   │   ├── OrderFactory.php  
│   │   │   ├── OrderItemFactory.php 
│   │   │   ├── OrderCreateService.php  
│   │   │   ├── OrderDeleteService.php  
│   │   │   ├── OrderDiscountService.php  
│   │   │   ├── OrderProcessingService.php  
│   │   │   ├── OrderValidationService.php 
│   │   ├── Discount/
│   │   │   ├── DiscountContext.php
│   │   │   ├── DiscountProcessor.php
│   │   │   ├── DiscountRuleInterface.php
│   │   │   ├── Rules/
│   │   │   │   ├── Over1000TotalDiscountRule.php             # Discount rule 1
│   │   │   │   ├── CategoryTwoBuySixGetOneFreeRule.php       # Discount rule 2
│   │   │   │   ├── CategoryOneCheapestItemDiscountRule.php   # Discount rule 3
│   ├── Message/Order
│   │   ├── OrderCreatingMessage.php   # Message for order creation
│   │   ├── OrderCreatedMessage.php    # Message when order is created
│   │   ├── OrderDeletedMessage.php    # Message when order is deleted
│   ├── MessageHandler/Order
│   │   ├── OrderCreatingMessageHandler.php # Handles order processing in queue
│   │   ├── OrderCreatedMessageHandler.php
│   │   ├── OrderDeletedMessageHandler.php

4. API Endpoints

Create an Order

POST /api/orders
{
    "customerId": 1,
    "orderItems": [
        { "productId": 1, "quantity": 1 },
        { "productId": 2, "quantity": 1 }
    ]
}

Response:

{
    "success": true,
    "message": "Order creation initialized",
    "data": {
        "uuid": "01JJY9N55AFDHPWNWWNMMVSMDK",
        "status": "creating"
    }
}

List Orders

GET /api/orders

Get Order Details

GET /api/orders/{orderUUID}

Delete Order

DELETE /api/orders/{orderId}

Response:

{
    "success": true,
    "message": "Order deleted successfully!",
    "data": null
}

5. DTO-based Validation

This project uses DTOs (Data Transfer Objects) for request validation, ensuring all data is structured correctly before processing.

Example Validation in DTO:

final class OrderCreateDTO
{
    #[Assert\Positive]
    #[Assert\NotBlank]
    public readonly int $customerId;

    #[Assert\Valid]
    #[Assert\Count(min: 1)]
    public array $orderItems;
}

Conclusion

This project is built to be scalable, maintainable, and efficient, leveraging Symfony Messenger, RabbitMQ, and a modular services structure to handle order management and discount processing effectively.

For installation instructions, refer to the Installation Guide: INSTALLATION.md

About

Order & Discount Processing System

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published