A complete order management system for delivery services, developed as a study project focused on best practices in software architecture and design.
- Overview
- Features
- Technologies
- Prerequisites
- Installation and Setup
- Running the Project
- Project Structure
- API Endpoints
- Design Patterns
- Tests
- CI/CD
- Status
The Delivery System is a complete web platform for managing delivery orders with support for multiple restaurants, clients, and payment methods. The project combines a robust Java/Spring Boot backend with an intuitive web frontend, implementing advanced software architecture concepts such as Domain-Driven Design (DDD) and Clean Architecture.
This is an educational and non-commercial project, developed to study and practice best practices in software development, system architecture, and design pattern implementation.
- Order creation in draft state
- Add menu items to orders
- Remove items from orders
- Decrease item quantities
- Cancel orders
- List orders by client
- Track order status (Draft -> Paid -> Confirmed -> Delivered)
- Restaurant registration
- Menu and menu items management
- Support for multiple currencies (BRL, USD, CAD)
- User account management
- Support for multiple roles (Client, Restaurant Owner)
- Account activity tracking
- Payment processing
- Payment status tracking
- Java 17 - Programming language
- Spring Boot 3.2.4 - Web framework
- Spring JDBC - Data access
- PostgreSQL - Relational database
- JUnit 5 - Testing framework
- Spring Boot Test & MockMvc - Integration testing
- Maven - Dependency manager
- Docker & Docker Compose - Containerization
- GitHub Actions - CI/CD Pipeline
- Nginx - Web server (reverse proxy)
- Java 17 or higher
- Maven 3.6+
- Node.js 18+ (for frontend)
- PostgreSQL 13+ (if running locally without Docker)
- Docker 20.10+
- Docker Compose 2.0+
git clone https://github.com/Smeltier/delivery-system.git
cd delivery-systemdocker-compose up -dThis will:
- Start a PostgreSQL container
- Apply database migrations
- Start the backend server on port 8080
- Start the frontend server on port 3000 (when implemented)
- API Backend: http://localhost:8080
- Frontend Web: http://localhost:3000 (in development)
- Database: localhost:5432
git clone https://github.com/Smeltier/delivery-system.git
cd delivery-systemCreate a database:
CREATE DATABASE delivery_system;Create a .env file in the project root:
# Database
DATABASE_URL=jdbc:postgresql://localhost:5432/delivery_system
DATABASE_USER=postgres
DATABASE_PASSWORD=your_password
# Server
SERVER_PORT=8080psql -U postgres -d delivery_system -f schema.sqlcd backend
# Build the project
mvn clean package
# Run the application
mvn spring-boot:runThe API will be available at http://localhost:8080
cd frontend
npm install
npm startThe frontend will be available at http://localhost:3000
delivery-system/
├── backend/
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/br/com/delivery/
│ │ │ │ ├── domain/ # Domain Layer
│ │ │ │ │ ├── account/ # User accounts
│ │ │ │ │ ├── order/ # Orders
│ │ │ │ │ ├── restaurant/ # Restaurants
│ │ │ │ │ ├── payment/ # Payments
│ │ │ │ │ ├── shared/ # Shared value objects
│ │ │ │ │ └── repositories/ # Repository interfaces
│ │ │ │ ├── application/ # Application Layer
│ │ │ │ │ ├── usecases/ # Use cases
│ │ │ │ │ ├── dto/ # Data transfer objects
│ │ │ │ │ └── mappers/ # Entity mappers
│ │ │ │ ├── infrastructure/ # Infrastructure Layer
│ │ │ │ │ ├── web/ # REST controllers
│ │ │ │ │ ├── persistence/ # JDBC implementation
│ │ │ │ │ ├── config/ # Spring configuration
│ │ │ │ │ └── exception/ # Global exception handling
│ │ │ │ └── DeliveryApplication.java # Main class
│ │ │ └── resources/
│ │ │ └── application.properties # Application configuration
│ │ └── test/ # Tests (Unit and Integration)
│ │ ├── java/br/com/delivery/domain/ # Domain tests
│ │ ├── java/br/com/delivery/application/ # Use case tests
│ │ └── java/br/com/delivery/infrastructure/ # Integration tests
│ ├── pom.xml # Maven dependencies
│ └── Dockerfile # Backend dockerfile
│
├── frontend/ # (In development)
│ ├── src/
│ │ ├── components/
│ │ ├── pages/
│ │ ├── services/
│ │ └── App.tsx
│ ├── package.json
│ └── Dockerfile
│
├── documentation/
│ ├── decisions.md # Architecture Decision Records
│ ├── class_diagram.plantuml # UML Class Diagram
│ └── api_documentation.md # API Documentation
│
├── schema.sql # PostgreSQL schema
├── compose.yml # Docker Compose configuration
├── .env.example # Environment variables example
├── .gitignore
├── .github/
│ └── workflows/
│ └── maven.yml # CI/CD Pipeline
└── README.md
All endpoints return JSON and are documented below.
POST /orders/items
Content-Type: application/json
{
"accountId": "550e8400-e29b-41d4-a716-446655440000",
"restaurantId": "660e8400-e29b-41d4-a716-446655440000",
"menuItemId": "770e8400-e29b-41d4-a716-446655440000",
"quantity": 2
}Responses:
201 Created- Item successfully added400 Bad Request- Validation failed (invalid quantity, restaurant not found, etc)404 Not Found- Account, restaurant or item not found
DELETE /orders/{orderId}/items/{menuItemId}Parameters:
orderId(UUID) - Order IDmenuItemId(UUID) - Menu item ID
Responses:
204 No Content- Item successfully removed404 Not Found- Order or item not found
PATCH /orders/{orderId}/items/{menuItemId}/decrease?quantity=1Parameters:
orderId(UUID) - Order IDmenuItemId(UUID) - Menu item IDquantity(int) - Quantity to decrease
Responses:
200 OK- Quantity successfully decreased400 Bad Request- Invalid quantity404 Not Found- Order or item not found
DELETE /orders/{orderId}Parameters:
orderId(UUID) - Order ID
Responses:
204 No Content- Order successfully cancelled404 Not Found- Order not found400 Bad Request- Order in state that cannot be cancelled
GET /clients/{accountId}/ordersParameters:
accountId(UUID) - Client account ID
Response (200 OK):
{
"orders": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "CONFIRMED",
"totalAmount": 89.90,
"currency": "BRL",
"createdAt": "2024-08-27T10:30:00Z",
"items": [
{
"menuItemId": "770e8400-e29b-41d4-a716-446655440000",
"name": "Margherita Pizza",
"quantity": 2,
"unitPrice": 35.00,
"subtotal": 70.00
}
]
}
]
}The API returns structured JSON errors:
Standard format:
{
"message": "Error description",
"status": 400,
"timestamp": "2024-08-27T10:30:00Z"
}Common HTTP codes:
| Code | Description |
|---|---|
400 Bad Request |
Validation failed, invalid data or business error |
404 Not Found |
Resource not found |
500 Internal Server Error |
Server error |
Business error examples:
- "Quantity must be positive."
- "Restaurant not found"
- "Order cannot be cancelled in this state"
- "Incompatible currencies"
The project implements fundamental DDD principles:
Objects with unique identity that change over time:
Order- Represents an orderClient- Represents a clientRestaurant- Represents a restaurantAccount- Represents a user account
Objects without identity that are immutable:
Money- Represents monetary values with currency validationOrderId,AccountId,MenuItemId,RestaurantId- Typed identifiersAddress- Delivery addressOrderItem- Order item
Clusters of entities functioning as a unit:
- Order Aggregate - Contains Order (root) + OrderItems + Payment
Abstraction for data persistence:
IOrderRepository- Contract for order persistenceIAccountRepository- Contract for account persistenceIRestaurantRepository- Contract for restaurant persistence
Orchestrate business logic:
AddItemToOrderUseCaseRemoveItemFromOrderUseCaseDecreaseItemQuantityFromOrderUseCaseCancelOrderUseCaseFindClientOrdersUseCase
Responsibilities are clearly separated into layers:
- Responsibility: Pure business logic
- Independence: No framework, database or web dependencies
- Examples: Entities, value objects, domain rules, repository interfaces
- Importance: Heart of the system
- Responsibility: Use case orchestration
- Function: Coordinate domain and repositories
- Examples: Use cases, DTOs, mappers
- Flow: Receive input (DTO) -> call repositories and domain -> return output (DTO)
- Responsibility: Technical implementation details
- Examples: Web controllers, JDBC repositories, Spring configuration
- Easy to change: Can replace PostgreSQL with MongoDB without affecting domain/application
- Should not: Contain business logic
The Order follows a well-defined flow with business rules:
+---------+ +------+ +-----------+ +----------+
| DRAFT | --> | PAID | --> | CONFIRMED | --> | DELIVERED|
+---------+ +------+ +-----------+ +----------+
| | |
+------------+--------------+
CANCELLED
Rules:
- An order starts in
DRAFT - Can only be paid once
- Can only be confirmed after payment
- Can be cancelled in any state except
DELIVERED - Must have address before changing to
CONFIRMED
The project has robust test coverage across multiple layers, ensuring quality and reliability.
cd backend
mvn testDomain tests:
mvn test -Dtest=*TestUse case tests:
mvn test -Dtest=*UseCaseTestIntegration tests:
mvn test -Dtest=*IntegrationTestLocation: src/test/java/br/com/delivery/domain/
Test business rules and entity behavior:
-
OrderTest - Tests:
- Order creation and validations
- State transitions
- Adding and removing items
- Total calculations
- Currency validations
-
MoneyTest - Tests:
- Arithmetic operations with Money
- Currency validation
- Comparisons and equality
Location: src/test/java/br/com/delivery/application/
Test use cases with fake repositories:
-
AddItemToOrderUseCaseTest - Tests:
- Adding items to order
- Automatic draft order creation
- Account, restaurant and item validations
- Quantity validation
-
RemoveItemFromOrderUseCaseTest - Tests:
- Item removal
- Existence validation
-
DecreaseItemQuantityFromOrderUseCaseTest - Tests:
- Quantity decrease
- Quantity validations
-
FindClientOrdersUseCaseTest - Tests:
- List orders by client
- Filters and sorting
Location: src/test/java/br/com/delivery/infrastructure/
Test complete HTTP flows with MockMvc:
- OrderControllerIntegrationTest - Tests:
- API endpoints
- JSON serialization/deserialization
- Correct HTTP status codes
- End-to-end flows
To generate coverage report:
mvn test jacoco:reportReport will be generated at target/site/jacoco/index.html
The project uses GitHub Actions for test automation and build.
Location: .github/workflows/maven.yml
What happens on each push:
- Checkout - Code clone
- Setup Java - Configure Java 17
- Start PostgreSQL - Start PostgreSQL container for tests
- Apply Database Schema - Execute migrations
- Run Tests - Execute test suite with Maven
- Build Package - Compile and generate JAR executable
Build Status:
The badge at the top of the README shows current status:
See the complete UML diagram in documentation/class_diagram.plantuml
To visualize, use tools such as:
- PlantUML Online Editor
- VS Code Extension: PlantUML
-
documentation/decisions.md- Architecture Decision Records- Why DDD?
- Why Clean Architecture?
- Persistence patterns
- Separation of concerns
-
documentation/api_documentation.md- Detailed API documentation- All endpoints
- Request/response formats
- Practical examples
Developer: Smeltier
If you have questions, suggestions or find bugs:
- Open an Issue
This project is educational and non-commercial. Feel free to use it as study material.
Developed as a learning project in software architecture