This document describes the implementation of automatic trade deal status transition to "delivered" when the importer milestone is recorded.
When a trader records the final "importer" milestone for a funded trade deal, the system automatically:
- Updates the trade deal status from "funded" to "delivered"
- Enqueues a
deal.deliveredjob to trigger escrow release - Ensures atomicity through database transactions
- 5.5: Recording the importer milestone transitions the deal status to delivered
- Transaction Atomicity: Wrapped milestone recording in database transaction
- Status Transition: Added logic to update deal status when milestone is "importer"
- Job Enqueueing: Triggers
deal.deliveredjob for escrow release - Logging: Added transition logging for monitoring
- Dedicated Method: Added
enqueueDealDelivered()method for type safety - Error Handling: Maintains existing error handling patterns
- Dependency Injection: Added QueueModule import for job enqueueing
1. Trader records "importer" milestone
2. System validates:
- Deal exists and is in "funded" status
- User is the assigned trader
- Milestone follows correct sequence (farm → warehouse → port → importer)
3. Within database transaction:
a. Anchor milestone on Stellar blockchain
b. Save milestone record
c. Update trade deal status to "delivered"
d. Enqueue deal.delivered job
4. Log successful transition
5. Return milestone record
The implementation ensures that if any step fails:
- Milestone record is rolled back
- Deal status remains unchanged
- No job is enqueued
- Error is propagated to caller
This prevents partial state where a milestone exists but the deal status wasn't updated.
The system enforces strict milestone sequence:
- farm - Goods collected from farm
- warehouse - Goods stored in warehouse
- port - Goods shipped from port
- importer - Goods received by importer (triggers delivery)
Only the "importer" milestone triggers the status transition and job enqueueing.
Job Pattern: deal.delivered
Payload:
{
"tradeDealId": "uuid-of-trade-deal"
}This job will be consumed by the escrow release processor (implemented in task 11).
- Deal Not Found: Returns 404 if trade deal doesn't exist
- Invalid Status: Returns 422 if deal is not in "funded" status
- Unauthorized: Returns 403 if user is not the assigned trader
- Sequence Error: Returns 422 if milestone is out of sequence
- Database transaction ensures atomicity
- Stellar anchoring failures roll back the entire operation
- Queue job failures roll back milestone and status changes
- Importer Milestone: Verifies status transition and job enqueueing
- Non-Importer Milestones: Verifies no status change occurs
- Transaction Atomicity: Ensures rollback on failures
To test the complete flow:
- Create a funded trade deal
- Record milestones in sequence: farm → warehouse → port
- Record importer milestone
- Verify deal status changed to "delivered"
- Verify
deal.deliveredjob was enqueued
The system logs the following events:
- Successful Transition:
Deal {id} transitioned to delivered — escrow release job enqueued - Job Enqueueing:
Emitted event: deal.delivered(from QueueService) - Errors: All validation and transaction errors are logged
- Idempotency: Consider adding checks to prevent duplicate processing
- Retry Logic: Implement retry mechanisms for failed job enqueueing
- Notifications: Add user notifications for status transitions
- Audit Trail: Enhanced logging for compliance and debugging
This implementation depends on:
- Task 10: POST /shipments/milestones endpoint
- Task 8: Deal funding and status management
- Task 11: Escrow release job consumer (future implementation)
The deal.delivered job produced by this implementation will be consumed by the escrow release system in task 11.5.