Cookbook — Ordering ↔ Warehouse
Two collaborating modules, zero Application/Domain imports across the boundary.
Story
- Place order — Ordering must know stock is available now → sync ACL (validate before commit).
- Fulfill order — Warehouse must deduct reserved stock after success → async Domain Event (idempotent consumer).
Module sketches
Ordering/
├── Application/
│ ├── DTO/Order/PlaceOrderDTO.php
│ └── UseCases/Order/PlaceOrderUseCase.php
│ MarkOrderFulfilledUseCase.php
├── Domain/
│ ├── Entities/OrderEntity.php
│ ├── Events/OrderFulfilled.php # eventId, schemaVersion, rich payload
│ └── Ports/
│ ├── Order/OrderRepositoryInterface.php
│ └── Acl/WarehouseAvailabilityPortInterface.php
└── Infrastructure/
└── ExternalServices/WarehouseAvailabilityAclAdapter.php
Warehouse/
├── Application/
│ ├── DTO/.../DeductStockForFulfilledOrderDTO.php
│ └── UseCases/.../DeductStockForFulfilledOrderUseCase.php
├── Domain/
│ └── Ports/Module/WarehouseAvailabilityModuleInterface.php # thin façade
└── Infrastructure/
├── Messaging/OrderFulfilledTranslationListener.php
└── Persistence/…/ProcessedEventStore (eventId idempotency)
Flow A — place order (ACL)
Port names only: Ordering Use Cases never see the Warehouse *ModuleInterface.
Flow B — fulfill (Event)
Payload: lines, quantities, item codes, order reference — enough that Warehouse does not call back into Ordering Domain on the happy path.
Replaceability checkpoints
| Change | What you rewrite | What stays |
|---|---|---|
| Warehouse becomes HTTP | WarehouseAvailabilityAclAdapter (+ listener ingress) | Ordering Use Cases, local port, Warehouse inbound Use Case |
| Ordering becomes external publisher | Warehouse listener becomes webhook/message consumer | DeductStockForFulfilledOrderUseCase |
Do not
- Import Catalog/Sales/Inventory (or any product-app) trees into this story
- Treat another repository’s class dump as the architecture standard
- Put stock enums into Shared “for convenience”
- Span one DB transaction across Ordering + Warehouse tables
Related Core: ACL · Events · Contracts · Event delivery · Decision tree.