Skip to main content

Warehouse Service

Overview​

The Warehouse Service handles warehouse management, inventory allocation, and inventory tracking for order fulfillment. It receives order confirmation events and automatically allocates inventory to the nearest warehouse.

ItemDetails
LanguageJava 17
FrameworkSpring Boot 3.2
DatabaseAurora PostgreSQL (Global Database)
Namespacemall-warehouse
Port8080
Health Check/actuator/health

Architecture​

API Endpoints​

MethodPathDescription
GET/api/v1/warehousesGet warehouse list
GET/api/v1/warehouses/{id}Get warehouse details
POST/api/v1/warehouses/{id}/allocateAllocate order
GET/api/v1/warehouses/{id}/inventoryGet warehouse inventory status

Get Warehouse List​

GET /api/v1/warehouses

Response (200 OK):

[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Seoul Distribution Center",
"location": "Gangnam-gu, Seoul",
"capacity": 10000,
"active": true,
"createdAt": "2024-01-01T00:00:00"
},
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Busan Distribution Center",
"location": "Haeundae-gu, Busan",
"capacity": 8000,
"active": true,
"createdAt": "2024-01-01T00:00:00"
}
]

Get Warehouse Details​

GET /api/v1/warehouses/{id}

Response (200 OK):

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Seoul Distribution Center",
"location": "Gangnam-gu, Seoul",
"capacity": 10000,
"active": true,
"createdAt": "2024-01-01T00:00:00"
}

Allocate Order​

POST /api/v1/warehouses/{id}/allocate

Request:

{
"orderId": "660e8400-e29b-41d4-a716-446655440000"
}

Response (200 OK):

{
"id": "770e8400-e29b-41d4-a716-446655440000",
"warehouseId": "550e8400-e29b-41d4-a716-446655440000",
"warehouseName": "Seoul Distribution Center",
"orderId": "660e8400-e29b-41d4-a716-446655440000",
"status": "ALLOCATED",
"createdAt": "2024-01-15T10:35:00",
"updatedAt": "2024-01-15T10:35:00"
}

Get Warehouse Inventory Status​

GET /api/v1/warehouses/{id}/inventory

Response (200 OK):

{
"warehouseId": "550e8400-e29b-41d4-a716-446655440000",
"warehouseName": "Seoul Distribution Center",
"totalCapacity": 10000,
"activeAllocations": 150,
"availableCapacity": 9850
}

Data Models​

Warehouse Entity​

@Entity
@Table(name = "warehouses")
public class Warehouse {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

@Column(nullable = false)
private String name;

private String location;

@Column(columnDefinition = "INTEGER DEFAULT 0")
private Integer capacity = 0;

@Column(columnDefinition = "BOOLEAN DEFAULT true")
private Boolean active = true;

@Column(name = "created_at")
private LocalDateTime createdAt;
}

Allocation Entity​

@Entity
@Table(name = "allocations")
public class Allocation {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

@ManyToOne
@JoinColumn(name = "warehouse_id")
private Warehouse warehouse;

@Column(name = "order_id", nullable = false)
private UUID orderId;

@Enumerated(EnumType.STRING)
@Column(length = 50)
private AllocationStatus status = AllocationStatus.PENDING;

@Column(name = "created_at")
private LocalDateTime createdAt;

@Column(name = "updated_at")
private LocalDateTime updatedAt;
}

AllocationStatus Enum​

public enum AllocationStatus {
PENDING, // Pending
ALLOCATED, // Allocated
PICKING, // Picking in progress
PACKED, // Packing complete
SHIPPED // Shipped
}

Database Schema​

CREATE TABLE warehouses (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
location VARCHAR(255),
capacity INTEGER DEFAULT 0,
active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE allocations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
warehouse_id UUID REFERENCES warehouses(id),
order_id UUID NOT NULL,
status VARCHAR(50) DEFAULT 'PENDING',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_allocations_warehouse_id ON allocations(warehouse_id);
CREATE INDEX idx_allocations_order_id ON allocations(order_id);
CREATE INDEX idx_allocations_status ON allocations(status);

Events (Kafka)​

Subscribed Topics​

Topic NameDescription
orders.confirmedReceives order confirmation events for automatic allocation

orders.confirmed Processing​

@KafkaListener(topics = "orders.confirmed", groupId = "warehouse-service")
public void handleOrderConfirmed(Map<String, Object> orderData) {
UUID orderId = UUID.fromString(orderData.get("order_id").toString());
warehouseService.allocateOrderToNearestWarehouse(orderId);
}

Received payload:

{
"event": "order.confirmed",
"order_id": "660e8400-e29b-41d4-a716-446655440000",
"user_id": "user-123",
"total_amount": 687000.00
}

Environment Variables​

VariableDescriptionDefault
SPRING_DATASOURCE_URLAurora PostgreSQL connection URL-
SPRING_DATASOURCE_USERNAMEDB username-
SPRING_DATASOURCE_PASSWORDDB password-
SPRING_KAFKA_BOOTSTRAP_SERVERSKafka broker address-
SPRING_KAFKA_CONSUMER_GROUP_IDKafka consumer group IDwarehouse-service
SERVER_PORTService port8080

Service Dependencies​

Automatic Allocation Process​

Allocation Status Flow​

Error Handling​

HTTP Status CodeErrorDescription
404WarehouseNotFoundExceptionWarehouse not found
400IllegalStateExceptionCannot allocate (inactive warehouse, etc.)
400InsufficientCapacityExceptionInsufficient warehouse capacity