System Overview
The Product Distribution Dashboard follows a modern three-tier architecture with clear separation between data, business logic, and presentation layers.Backend Architecture
The backend is built with Spring Boot 3.4.5 and follows a layered architecture pattern.Core Layers
Controllers
REST API endpoints for frontend communication
Services
Business logic and orchestration
Repositories
Data access using Spring Data JPA
Key Services
The backend contains several specialized services that work together:DistributionService
Core service responsible for the product distribution algorithm:- Load products, stores, and warehouses from JSON sources
- Execute configurable warehouse selection strategies
- Calculate adjusted demand based on expected return rates
- Allocate inventory while respecting capacity constraints
- Track unfulfilled demands with reasons (stock vs. capacity)
- Cache eviction for metrics recalculation
The distribution algorithm can be found in
/backend/src/main/java/com/productdistribution/backend/services/DistributionService.java:192JsonDataLoaderService
Handles loading data from external JSON sources:- Uses Spring WebFlux WebClient for async HTTP calls
- Configurable data source URLs via application properties
- Jackson ObjectMapper for JSON deserialization
- Error handling for network and parsing failures
Other Services
- MetricsService: Calculates global and detailed metrics with caching
- GeoDistanceService: Computes Haversine distances between coordinates
- ProductService, StoreService, WarehouseService: Domain-specific data management
- StockAssignmentService, UnfulfilledDemandService: Result persistence
Entity Model
The domain model consists of six main entities:Product
Product catalog with brand and available sizes
Store
Store locations with geolocation, capacity, and demand
Warehouse
Warehouse locations with inventory
ProductItem
Individual product items by size and quantity
StockAssignment
Distribution assignments from warehouses to stores
UnfulfilledDemand
Unmet demands with reasons
Technology Stack
The backend leverages modern Spring Boot capabilities:- Spring Data JPA: Repository abstraction and database access
- Spring Web: RESTful API with
@RestController - Spring WebFlux: Reactive WebClient for external HTTP calls
- Spring Cache: Method-level caching for metrics
- Spring Validation: Request validation with Bean Validation
- Spring Actuator: Health checks and operational endpoints
- Flyway: Database migration management
- Lombok: Reduce boilerplate with annotations
- MapStruct: Type-safe object mapping
- HikariCP: High-performance connection pooling
Frontend Architecture
The frontend is built with Angular 18 using standalone components and follows a component-based architecture.Component Structure
Key Components
DashboardMapComponent
Interactive map visualization using Leaflet:- Marker clustering for warehouses and stores
- Polyline routes with directional arrows
- Popup details for stock assignments
- Hover and click interactions
- Responsive filtering
The map component implementation is in
/frontend/src/app/dashboard-map/dashboard-map.component.ts:1Services
Angular services handle all HTTP communication with the backend:- MetricsService: Fetch global and detailed metrics
- StockAssignmentService: Query stock assignments with filtering
- ProductService, StoreService, WarehouseService: Domain data retrieval
Frontend Technology Stack
- Angular 18: Modern framework with standalone components
- TypeScript: Type-safe development
- Leaflet: Interactive mapping library
- Leaflet.markercluster: Marker clustering
- Leaflet-polylinedecorator: Directional arrows on routes
- Chart.js / ng2-charts: Data visualization
- ng-select: Enhanced dropdown controls
- RxJS: Reactive programming with Observables
- ESLint & Prettier: Code quality and formatting
Database Schema
The PostgreSQL database schema is managed by Flyway migrations and consists of six main tables.Schema Diagram
Table Descriptions
products & product_sizes
products & product_sizes
products stores the product catalog with unique IDs and brand associations.product_sizes is a join table storing the available sizes for each product.Migration:
V1__Create_products_table.sqlstores
stores
Stores have geolocation (latitude, longitude), capacity constraints, and expected return rates.The
remaining_capacity field is dynamically updated during distribution to track available space.Migration: V2__Create_stores_table.sqlwarehouses
warehouses
Warehouses are simpler entities with just geolocation and country information.Their inventory is tracked in the
product_items table.Migration: V3__Create_warehouses_table.sqlproduct_items
product_items
Represents individual product inventory items, either in warehouses or demanded by stores.Each item has a product ID, size, quantity, and either a store_id (demand) or warehouse_id (stock).Includes indexes on
store_id, warehouse_id, and product_id, size for query performance.Migration: V4__Create_product_items_table.sqlstock_assignments
stock_assignments
The result of the distribution algorithm - represents the decision to send specific quantities from a warehouse to a store.Includes the calculated distance in kilometers for analytics.Multiple composite indexes support efficient querying by warehouse, store, product, and distance.Migration:
V5__Create_stock_assignments_table.sqlunfulfilled_demands
unfulfilled_demands
Tracks demands that couldn’t be fulfilled, along with the reason:
STOCK_SHORTAGE: No warehouse had available inventoryCAPACITY_SHORTAGE: Store reached maximum capacity
V6__Create_unfulfilled_demands_table.sqlData Flow
The system processes data through several distinct phases:Initialization
On application startup:
- Flyway runs database migrations to create/update schema
- Spring Boot initializes all beans and services
- Backend is ready to accept requests
Data Loading
When triggered (manually or via scheduler):
JsonDataLoaderServicefetches JSON from configured URLs- Jackson deserializes JSON into entity objects
- Services persist data to PostgreSQL via JPA repositories
- Products, stores (with demand), and warehouses (with stock) are loaded
Distribution Execution
The
DistributionService.distributeProducts() method:- Loads fresh data from JSON sources
- For each store and each demand item:
- Calculates adjusted demand based on return rate
- Selects candidate warehouses using configured strategy
- Allocates stock while respecting capacity constraints
- Creates
StockAssignmentrecords - Tracks
UnfulfilledDemandfor shortages
- Persists all assignments and unfulfilled demands
- Updates store remaining capacity
- Evicts metrics cache to trigger recalculation
Metrics Calculation
The
MetricsService computes:- Global metrics: Total assignments, fulfillment rate, average distance, capacity utilization
- Detailed metrics: Per-warehouse and per-store breakdowns
- Results are cached for performance
Distribution Algorithm
The core distribution algorithm operates as follows:Pseudocode
Warehouse Selection Strategies
The system supports pluggable warehouse selection strategies:- DistanceOnlyStrategy (default): Selects warehouses sorted by geographic distance
- Custom strategies can be implemented by extending
WarehouseSelectionStrategy
Caching Strategy
The backend uses Spring Cache for performance optimization:- Metrics caching: Global and detailed metrics are cached to avoid expensive recalculations
- Cache eviction: Automatically cleared when distribution runs (via
@CacheEvict) - Cache names:
globalMetrics,detailedMetrics
API Endpoints
The backend exposes RESTful endpoints (examples):GET /api/stock-assignments- Retrieve all stock assignmentsGET /api/stock-assignments?storeId={id}- Filter by storeGET /api/stock-assignments?warehouseId={id}- Filter by warehouseGET /api/metrics/global- Get global metricsGET /api/metrics/detailed- Get detailed breakdownsGET /api/stores- List all storesGET /api/warehouses- List all warehousesGET /api/products- List all productsPOST /api/stock-assignments/distribute- Trigger distribution manually
The exact endpoint paths depend on the controller implementations. Check the source code for the complete API reference.
Deployment Architecture
The application supports two deployment modes:Local Development (Docker Compose)
- All services run in Docker containers on a single machine
- PostgreSQL data persists in Docker volumes
- Frontend served via Angular dev server (port 4200)
- Backend runs with Spring Boot DevTools for hot reload
Production (Render)
- Backend: Deployed as a Docker service with
prodprofile - Frontend: Built as static site and served from CDN
- Database: External PostgreSQL (Microsoft Azure)
- Health checks:
/actuator/healthendpoint - Environment variables: Database connection, data URLs, scheduler config
render.yaml in the repository root.
Performance Considerations
Database Indexing
Strategic indexes on foreign keys and frequently queried columns for fast lookups
Caching
Metrics cached to avoid expensive aggregation queries on every request
Connection Pooling
HikariCP optimized for high throughput with configurable pool sizes
Batch Processing
Batch inserts for stock assignments and unfulfilled demands
What’s Next?
API Reference
Explore the REST API endpoints and data models
Configuration Guide
Learn how to configure data sources, strategies, and deployment
Backend Development
Guidelines for backend development, testing, and services
Frontend Development
Guidelines for frontend development and components
Deployment
Deploy to production environments like Render or AWS