Garment State Transitions
Garment State Transitions
Entity: GarmentEntity States: Available, Reserved, Packed, InTransitOutbound, Delivered, InUse, InTransitReturn, ReceivedReturn, Quarantine, Refurbish, Repair, Lost, Retired, Disposed
State Diagram
┌─────────────┐
│ Created │
└──────┬──────┘
│ intake
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ reserve ┌─────────────┐ pack ┌───────────┐ │
│ │ Available │───────────────▶│ Reserved │─────────────▶│ Packed │ │
│ └─────────────┘ └─────────────┘ └─────┬─────┘ │
│ ▲ │ │ │
│ │ │ unassign │ ship │
│ │ ▼ ▼ │
│ │ (back to Available) ┌─────────────┐ │
│ │ │InTransit │ │
│ │ │Outbound │ │
│ │ └──────┬──────┘ │
│ │ │ │
│ │ │deliver │
│ │ ▼ │
│ │ ┌─────────────┐ │
│ │ │ Delivered │ │
│ │ └──────┬──────┘ │
│ │ │ │
│ │ │wear │
│ │ ▼ │
│ │ ┌─────────────┐ │
│ │ │ InUse │ │
│ │ └──────┬──────┘ │
│ │ │ │
│ │ │return │
│ │ ▼ │
│ │ ┌─────────────┐ │
│ │ │InTransit │ │
│ │ │Return │ │
│ │ └──────┬──────┘ │
│ │ │ │
│ │ │receive │
│ │ ▼ │
│ │ ┌─────────────┐ │
│ │ ┌─────────────────────────│Received │ │
│ │ │ │Return │ │
│ │ │ └──────┬──────┘ │
│ │ │ │ │
│ │ │ quarantine │inspect │
│ │ ▼ ▼ │
│ │ ┌─────────────┐ ┌─────────────────┐ │
│ │ │ Quarantine │ │ Refurbish │ │
│ │ └──────┬──────┘ └────────┬────────┘ │
│ │ │ │ │
│ │ │ resolve │ complete │
│ │ ▼ │ │
│ │ ┌─────────────┐ │ │
│ │ │ Repair │───────────────────────┘ │
│ │ └─────────────┘ │ │
│ │ │ │
│ └────────────────────────────────────────────────────────┘ │
│ (if lifecycle OK) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Exit States (terminal):
┌───────────┐ ┌───────────┐ ┌───────────┐
│ Lost │ │ Retired │ │ Disposed │
└───────────┘ └───────────┘ └───────────┘
Transition Contracts
T-G001: Available → Reserved
Trigger: Cycle allocation selects garment for upcoming box.
Preconditions:
garment.asset_state == 'Available'garment.current_cycle_id == nullgarment.over_limit == falsegarment.condition_grade != 'F'target_cycle.cycle_state == 'Scheduled'
Actions:
- Set
garment.asset_state = 'Reserved' - Set
garment.current_cycle_id = target_cycle.cycle_id - Emit event:
GarmentReserved
Postconditions:
- Garment is locked to this cycle
- Garment cannot be reserved for another cycle
Error Codes:
E001- Garment already reserved for another cycleE005- Lifecycle exceededE007- Condition grade too low
T-G002: Reserved → Available (Unassign)
Trigger: Cycle cancelled or garment swapped before packing.
Preconditions:
garment.asset_state == 'Reserved'garment.current_box_id == null(not yet packed)
Actions:
- Set
garment.asset_state = 'Available' - Clear
garment.current_cycle_id - Emit event:
GarmentUnassigned(compensating)
Postconditions:
- Garment is available for other cycles
Error Codes:
E008- Cannot unassign after packing
T-G003: Reserved → Packed
Trigger: Operator scans garment into box during packing.
Preconditions:
garment.asset_state == 'Reserved'garment.current_cycle_id != nulltarget_box.container_state == 'Picking'target_box.cycle_id == garment.current_cycle_id
Actions:
- Set
garment.asset_state = 'Packed' - Set
garment.current_box_id = target_box.box_id - Add garment to
target_box.actual_contents - Emit event:
GarmentPacked
Postconditions:
- Garment is physically in box
- Box actual_contents includes this garment
Error Codes:
E009- Box not in Picking stateE010- Garment/box cycle mismatch
T-G004: Packed → InTransitOutbound
Trigger: Box ships.
Preconditions:
garment.asset_state == 'Packed'garment.current_box_id != nullbox.container_state == 'Shipped'
Actions:
- Set
garment.asset_state = 'InTransitOutbound' - Emit event:
GarmentShipped
Postconditions:
- Garment custody is external (carrier)
Error Codes:
E011- Box not yet shipped
T-G005: InTransitOutbound → Delivered
Trigger: Delivery confirmation received.
Preconditions:
garment.asset_state == 'InTransitOutbound'box.container_state == 'Delivered'
Actions:
- Set
garment.asset_state = 'Delivered' - Emit event:
GarmentDelivered
Postconditions:
- Garment is at user location
T-G006: Delivered → InUse
Trigger: Wear window opens (automatic or explicit).
Preconditions:
garment.asset_state == 'Delivered'cycle.cycle_state == 'WearWindowOpen'
Actions:
- Set
garment.asset_state = 'InUse' - Emit event:
GarmentInUse
Postconditions:
- Garment is being worn
T-G007: InUse → InTransitReturn
Trigger: Return initiated.
Preconditions:
garment.asset_state == 'InUse'box.container_state IN ('ReturnInitiated', 'Returning')
Actions:
- Set
garment.asset_state = 'InTransitReturn' - Emit event:
GarmentReturning
Postconditions:
- Garment is in transit back to facility
T-G008: InTransitReturn → ReceivedReturn
Trigger: Box received at facility, garment scanned.
Preconditions:
garment.asset_state == 'InTransitReturn'box.container_state == 'Received'
Actions:
- Set
garment.asset_state = 'ReceivedReturn' - Emit event:
GarmentReceived
Postconditions:
- Garment is at facility pending inspection
T-G009: ReceivedReturn → Refurbish
Trigger: Inspection passes, normal refurbishment needed.
Preconditions:
garment.asset_state == 'ReceivedReturn'garment.condition_grade IN ('A', 'B', 'C')garment.over_limit == false
Actions:
- Set
garment.asset_state = 'Refurbish' - Increment
garment.wear_count - Emit event:
GarmentToRefurbish
Postconditions:
- Garment is in cleaning/refresh queue
T-G010: ReceivedReturn → Quarantine
Trigger: Inspection finds contamination or safety issue.
Preconditions:
garment.asset_state == 'ReceivedReturn'inspection.safety_flag == true
Actions:
- Set
garment.asset_state = 'Quarantine' - Emit event:
GarmentQuarantinedwithreason
Postconditions:
- Garment is isolated from circulation
T-G011: ReceivedReturn → Retired
Trigger: Lifecycle bounds exceeded or condition failed.
Preconditions:
garment.asset_state == 'ReceivedReturn'garment.over_limit == true OR garment.condition_grade == 'F'
Actions:
- Set
garment.asset_state = 'Retired' - Set
garment.retired_at = NOW() - Clear
garment.current_cycle_id - Clear
garment.current_box_id - Emit event:
GarmentRetiredwithreason
Postconditions:
- Garment permanently ineligible for circulation
T-G012: Refurbish → Available
Trigger: Refurbishment complete.
Preconditions:
garment.asset_state == 'Refurbish'garment.over_limit == falserefurbishment.complete == true
Actions:
- Set
garment.asset_state = 'Available' - Increment
garment.wash_count - Clear
garment.current_cycle_id - Clear
garment.current_box_id - Update
garment.condition_gradebased on inspection - Emit event:
GarmentAvailable
Postconditions:
- Garment is ready for next cycle
T-G013: Quarantine → Repair
Trigger: Quarantine resolved, repair needed.
Preconditions:
garment.asset_state == 'Quarantine'quarantine.resolution == 'repair'
Actions:
- Set
garment.asset_state = 'Repair' - Emit event:
GarmentToRepair
Postconditions:
- Garment is in repair queue
T-G014: Repair → Refurbish
Trigger: Repair complete, needs refurbishment before return to circulation.
Preconditions:
garment.asset_state == 'Repair'repair.complete == true
Actions:
- Set
garment.asset_state = 'Refurbish' - Increment
garment.repair_count - Emit event:
GarmentRepaired
Postconditions:
- Garment proceeds to standard refurbishment
T-G015: Any → Lost
Trigger: Garment declared non-recoverable.
Preconditions:
garment.asset_state IN ('InTransitOutbound', 'Delivered', 'InUse', 'InTransitReturn')declaration.reason != null
Actions:
- Set
garment.asset_state = 'Lost' - Emit event:
GarmentLostwithreason - Trigger settlement in UserContractEnforcementSubsystem
Postconditions:
- Garment removed from active tracking
- Financial settlement required
T-G016: Retired → Disposed
Trigger: Physical removal from system.
Preconditions:
garment.asset_state == 'Retired'
Actions:
- Set
garment.asset_state = 'Disposed' - Emit event:
GarmentDisposedwithmethod(resale/donation/recycle)
Postconditions:
- Garment lifecycle complete