Real-time license plate tracking, movement management, and location state monitoring for complete warehouse visibility.
The Physical Tracking Service provides comprehensive real-time tracking of physical assets throughout the warehouse. This bounded context manages the complete lifecycle of license plates (pallets, totes, cartons), tracks all physical movements between locations, maintains current location state and occupancy, provides movement history and audit trails, and integrates with RTLS (Real-Time Location Systems) for automated tracking. The service serves as the single source of truth for "where is it now" queries across warehouse operations.
Physical Asset Tracking & Movement - Manages real-time location and movement of physical containers and inventory throughout the warehouse.
- LicensePlate - Root aggregate representing a physical container
- LocationState - Root aggregate representing current state of a location
- LPItem - Item within a license plate
- Movement - Physical movement record
- LicensePlateType - Container type (PALLET, TOTE, CARTON, CASE, EACHES_CONTAINER)
- LicensePlateStatus - LP lifecycle status (CREATED, ACTIVE, AT_LOCATION, IN_TRANSIT, PICKED, PACKED, SHIPPED, CONSUMED, CLOSED)
- MovementType - Movement category (RECEIVE, PUTAWAY, PICK, REPLENISH, TRANSFER, SHIP, CYCLE_COUNT)
- OccupancyStatus - Location state (EMPTY, PARTIALLY_OCCUPIED, FULL, BLOCKED)
- LicensePlateCreatedEvent - New license plate created
- LicensePlateMovedEvent - License plate moved to new location
- ItemAddedToLPEvent - Item added to license plate
- ItemRemovedFromLPEvent - Item removed from license plate
- LocationStateChangedEvent - Location occupancy state changed
- LicensePlateConsumedEvent - License plate emptied
- LicensePlateClosedEvent - License plate lifecycle ended
- License Plate: Physical container holding inventory (pallet, tote, carton)
- License Plate ID: Unique barcode identifier for container
- Location State: Current occupancy and status of warehouse location
- Movement: Physical transfer from one location to another
- Movement History: Complete audit trail of container movements
- Dwell Time: Duration container remains at a location
- In Transit: Container actively being moved
- Consumed: Container emptied of all contents
- RTLS: Real-Time Location System for automated tracking
src/main/java/com/paklog/wes/tracking/
├── domain/ # Core business logic
│ ├── aggregate/ # Aggregates
│ │ ├── LicensePlate.java # LP aggregate root
│ │ └── LocationState.java # Location state aggregate
│ ├── entity/ # Entities
│ │ ├── LPItem.java # Item in license plate
│ │ └── Movement.java # Movement record
│ ├── valueobject/ # Value objects
│ │ ├── LicensePlateType.java
│ │ ├── LicensePlateStatus.java
│ │ ├── MovementType.java
│ │ └── OccupancyStatus.java
│ ├── repository/ # Repository interfaces
│ │ ├── LicensePlateRepository.java
│ │ └── LocationStateRepository.java
│ ├── service/ # Domain services
│ │ ├── MovementTrackingService.java
│ │ └── OccupancyCalculator.java
│ └── event/ # Domain events
├── application/ # Use cases & orchestration
│ ├── service/ # Application services
│ │ └── PhysicalTrackingService.java
│ ├── command/ # Commands
│ │ ├── CreateLicensePlateCommand.java
│ │ ├── MoveLicensePlateCommand.java
│ │ ├── AddItemCommand.java
│ │ └── RemoveItemCommand.java
│ └── query/ # Queries
└── adapter/ # External adapters
├── rest/ # REST controllers
│ └── PhysicalTrackingController.java
├── persistence/ # MongoDB repositories
└── events/ # Event publishers/consumers
- Hexagonal Architecture - Clean separation of domain and infrastructure
- Domain-Driven Design - Rich domain models for tracking
- Event Sourcing Pattern - Complete movement history
- Aggregate Pattern - Consistency boundaries around license plates
- Event-Driven Architecture - Real-time movement notifications
- Repository Pattern - Data access abstraction
- CQRS Pattern - Optimized read models for location queries
- SOLID Principles - Maintainable and extensible code
- Java 21 - Programming language
- Spring Boot 3.3.3 - Application framework
- Maven - Build and dependency management
- MongoDB - Document database for LP and movement data
- Spring Data MongoDB - Data access layer
- Apache Kafka - Event streaming platform
- Spring Kafka - Kafka integration
- CloudEvents 2.5.0 - Standardized event format
- Spring Web MVC - REST API framework
- Bean Validation - Input validation
- OpenAPI/Swagger - API documentation
- Spring Boot Actuator - Health checks and metrics
- Micrometer - Metrics collection
- Micrometer Tracing - Distributed tracing
- Loki Logback Appender - Log aggregation
- JUnit 5 - Unit testing framework
- Testcontainers - Integration testing
- Mockito - Mocking framework
- AssertJ - Fluent assertions
- Docker - Containerization
- Docker Compose - Local development environment
- ✅ Hexagonal Architecture (Ports and Adapters)
- ✅ Domain-Driven Design tactical patterns
- ✅ Event-Driven Architecture
- ✅ Microservices architecture
- ✅ RESTful API design
- ✅ Real-time tracking patterns
- ✅ SOLID principles
- ✅ Clean Code practices
- ✅ Comprehensive unit and integration testing
- ✅ Domain-driven design patterns
- ✅ Immutable value objects
- ✅ Rich domain models with business logic
- ✅ CloudEvents specification v1.0
- ✅ Event-driven movement tracking
- ✅ At-least-once delivery semantics
- ✅ Event versioning strategy
- ✅ Idempotent event handling
- ✅ Structured logging (JSON)
- ✅ Distributed tracing
- ✅ Health check endpoints
- ✅ Prometheus metrics
- ✅ Correlation ID propagation
- Java 21+
- Maven 3.8+
- Docker & Docker Compose
-
Clone the repository
git clone https://github.com/paklog/physical-tracking-service.git cd physical-tracking-service -
Start infrastructure services
docker-compose up -d mongodb kafka
-
Build and run the application
mvn spring-boot:run
-
Verify the service is running
curl http://localhost:8085/actuator/health
# Start all services
docker-compose up -d
# View logs
docker-compose logs -f physical-tracking-service
# Stop all services
docker-compose downOnce running, access the interactive API documentation:
- Swagger UI: http://localhost:8085/swagger-ui.html
- OpenAPI Spec: http://localhost:8085/v3/api-docs
POST /license-plates- Create new license plateGET /license-plates/{lpId}- Get license plate detailsPOST /license-plates/{lpId}/move- Move license plate to locationPOST /license-plates/{lpId}/items- Add item to license plateDELETE /license-plates/{lpId}/items/{itemId}- Remove item from license platePOST /license-plates/{lpId}/close- Close license plateGET /license-plates/location/{locationId}- Get LPs at location
GET /locations/{locationId}/state- Get current location stateGET /locations/{locationId}/occupancy- Get occupancy detailsGET /locations/{locationId}/license-plates- List LPs at location
GET /license-plates/{lpId}/movements- Get movement historyGET /license-plates/{lpId}/current-location- Get current locationGET /movements/recent- Get recent movementsGET /movements/by-type/{movementType}- Query by movement type
- Current Location: Immediate "where is it now" queries
- Movement History: Complete audit trail of all movements
- Dwell Time Calculation: How long at current location
- In-Transit Tracking: Items actively being moved
- Multi-Level Nesting: Track pallets containing totes containing cartons
CREATED → ACTIVE → AT_LOCATION ⟷ IN_TRANSIT → PICKED → PACKED → SHIPPED → CONSUMED → CLOSED
- RECEIVE: Inbound receiving to dock
- PUTAWAY: Move from receiving to storage
- PICK: Remove from storage for order
- REPLENISH: Move from reserve to pick location
- TRANSFER: Internal location transfer
- SHIP: Outbound to carrier
- CYCLE_COUNT: Movement for inventory count
- EMPTY: No license plates present
- PARTIALLY_OCCUPIED: Has LPs, capacity available
- FULL: At maximum capacity
- BLOCKED: Location unavailable for operations
# Run unit tests
mvn test
# Run integration tests
mvn verify
# Run tests with coverage
mvn clean verify jacoco:report
# View coverage report
open target/site/jacoco/index.htmlKey configuration properties:
spring:
data:
mongodb:
uri: mongodb://localhost:27017/physical_tracking
kafka:
bootstrap-servers: localhost:9092
physical-tracking:
movement:
audit-retention-days: 365
enable-location-state-sync: true
license-plate:
auto-consume-when-empty: true
track-nested-containers: truecom.paklog.wes.tracking.lp.created.v1com.paklog.wes.tracking.lp.moved.v1com.paklog.wes.tracking.lp.item.added.v1com.paklog.wes.tracking.lp.item.removed.v1com.paklog.wes.tracking.lp.consumed.v1com.paklog.wes.tracking.lp.closed.v1com.paklog.wes.tracking.location.state.changed.v1
com.paklog.wms.location.created.v1- Initialize location statecom.paklog.inventory.received.v1- Create receiving license platescom.paklog.wes.pick.confirmed.v1- Record pick movementscom.paklog.wes.pack.item.packed.v1- Update LP status for packingcom.paklog.shipment.dispatched.v1- Mark LPs as shipped
All events follow the CloudEvents specification v1.0 and are published asynchronously via Kafka.
- Health: http://localhost:8085/actuator/health
- Metrics: http://localhost:8085/actuator/metrics
- Prometheus: http://localhost:8085/actuator/prometheus
- Info: http://localhost:8085/actuator/info
lp.created.total- Total license plates createdlp.movements.total- Total movements recordedlp.active.count- Currently active license plateslocation.occupancy.percentage- Average location utilizationmovement.dwell.time.seconds- Average dwell time per locationlp.consumed.rate- License plate consumption rate
- Follow hexagonal architecture principles
- Implement domain logic in domain layer
- Maintain complete movement audit trails
- Track license plate lifecycle accurately
- Provide real-time location state
- Write comprehensive tests including movement scenarios
- Document domain concepts using ubiquitous language
- Follow existing code style and conventions
Copyright © 2024 Paklog. All rights reserved.