1
0
Fork 0
mirror of https://github.com/s-frick/effigenix.git synced 2026-03-28 10:09:35 +01:00

feat(inventory): Bestand reservieren mit FEFO-Allokation (#12)

Implementiert Story 4.1: Reservierung von Beständen mit automatischer
FEFO-Allokation (First-Expired-First-Out) über verfügbare Chargen.

Domain: Reservation-Entity, StockBatchAllocation, ReservationDraft,
FEFO-Logik in Stock.reserve(), availableQuantity() berücksichtigt
bestehende Allokationen. Neue Error-Varianten für InsufficientStock,
InvalidReferenceType, InvalidReservationPriority, ReservationNotFound.

API: POST /api/inventory/stocks/{stockId}/reservations → 201 Created.
Liquibase: reservations + stock_batch_allocations Tabellen mit FK- und
CHECK-Constraints.

Tests: 43 neue Tests (22 Domain, 10 UseCase, 11 Integration) für
FEFO-Logik, Validierung, Mengenprüfung, Auth und Edge Cases.
This commit is contained in:
Sebastian Frick 2026-02-23 23:27:37 +01:00
parent b77b209f10
commit 0b49bb2977
38 changed files with 1656 additions and 57 deletions

View file

@ -91,6 +91,7 @@ classDiagram
}
class StockBatchAllocation {
+AllocationId id
+StockBatchId stockBatchId
+Quantity allocatedQuantity
}
@ -163,6 +164,8 @@ classDiagram
StockBatch ..> StockBatchStatus
StockBatch ..> Quantity
StockBatchAllocation ..> AllocationId
StockMovement ..> StockMovementId
StockMovement ..> MovementType
StockMovement ..> MovementDirection
@ -208,6 +211,7 @@ Stock (Aggregate Root)
├── Priority (ReservationPriority: URGENT | NORMAL | LOW)
├── ReservedAt (Instant)
└── StockBatchAllocations[] (Entity)
├── AllocationId (VO)
├── StockBatchId (VO) - Zugeordnete Charge
└── AllocatedQuantity (VO) - Reservierte Menge aus dieser Charge
```
@ -846,6 +850,15 @@ public sealed interface StockError {
record NegativeStockNotAllowed() implements StockError {
public String message() { return "Stock cannot go negative"; }
}
record InvalidReferenceType(String value) implements StockError {
public String message() { return "Invalid reference type: " + value; }
}
record InvalidReferenceId(String reason) implements StockError {
public String message() { return "Invalid reference ID: " + reason; }
}
record InvalidReservationPriority(String value) implements StockError {
public String message() { return "Invalid reservation priority: " + value; }
}
}
public sealed interface StockMovementError {