Skip to content

Delivery — version 1

Delivery bounded context — getting a delivery order to the customer’s door. It owns the Address value object (supplied downstream to nobody else here, but a customer-supplier candidate) and enforces the rule that anchors this context: a delivery order must carry a delivery address.

classDiagram
    class DeliveryStatus {
        <<enumeration>>
        Scheduled
        PickedUp
        EnRoute
        Delivered
        Failed
    }
    class Address {
        <<value object>>
        +String street
        +String city
        +String postalCode
        +String country
        +String /formatted
    }
    class Courier {
        <<value object>>
        +String name
        +String phone
    }
    class DeliveryScheduled {
        <<event>>
        +DeliveryId delivery
        +OrderId order
    }
    class DeliveryCompleted {
        <<event>>
        +DeliveryId delivery
    }
    class Delivery {
        <<aggregate root>>
        +DeliveryId id
        +OrderId order
        +Address destination
        +Courier courier
        +DeliveryStatus status
        +Bool /assigned
        +Bool /isDelivered
        +schedule(OrderId order, Address destination) Delivery
        +pickUp(Courier by)
        +depart()
        +complete()
    }
    DeliveryScheduled --> Delivery
    DeliveryCompleted --> Delivery
    Delivery *-- Address
    Delivery *-- Courier
    Delivery *-- DeliveryStatus

The delivery aggregate: one record per delivery order. Being an aggregate root it gains an IDeliveryRepository and joins the context UoW; the repository block adds intention-revealing finders.

Root entity: Delivery (identified by DeliveryId)

Repository finders:

  • enRoute(): List<Delivery>
  • byCourier(courier: Courier): List<Delivery>

Repository operations: getById, add, update

DeliveryScheduled

Raised inside the aggregate when a delivery is scheduled by the factory.

FieldTypeDescription
deliveryDeliveryId
orderOrderId

DeliveryCompleted

Raised when a delivery is completed.

FieldTypeDescription
deliveryDeliveryId
stateDiagram-v2
    [*] --> Scheduled
    Scheduled --> PickedUp
    Scheduled --> Failed
    PickedUp --> EnRoute
    PickedUp --> Failed
    EnRoute --> Delivered
    EnRoute --> Failed
    Delivered --> [*]
    Failed --> [*]
FromToGuard
ScheduledPickedUp
ScheduledFailed
PickedUpEnRoute
PickedUpFailed
EnRouteDelivered
EnRouteFailed
Delivered(terminal)
Failed(terminal)

Assign a courier and have them collect the order.

Preconditions:

  • only a scheduled delivery can be picked up

Effects:

  • courier -> by
  • status -> PickedUp

Send a picked-up delivery on its way.

Preconditions:

  • only a picked-up delivery can depart
  • a delivery cannot depart without a courier

Effects:

  • status -> EnRoute

Mark a delivery as completed at the door.

Preconditions:

  • only an en-route delivery can be completed

Effects:

  • status -> Delivered

Events:

  • DeliveryCompleted(delivery: id)
schedule(order: OrderId, destination: Address)
Section titled “schedule(order: OrderId, destination: Address)”

Schedule a delivery for a placed delivery order. The same-named parameters auto-bind the required fields; status defaults to Scheduled.

Preconditions:

  • a delivery order requires a delivery address

Events:

  • DeliveryScheduled(delivery: id, order: order)

Business rules

  • a delivery order requires a delivery address
  • a delivery en route must have a courier

A street address a pizza can be delivered to. A first-class value object so a delivery destination is never a bare string, validated by shape and normalized via string ops. Owned here and supplied to partners (see context-map).

FieldTypeDescription
streetString
cityString
postalCodeString
countryString
formattedStringderived

Business rules

  • a delivery needs a street
  • a delivery needs a city
  • invalid postal code

A driver assigned to a delivery. A small value object so an assignee is typed.

FieldTypeDescription
nameString
phoneString

Business rules

  • a courier needs a name

How a delivery is doing. Drives the states status { … } machine below.

Values: Scheduled, PickedUp, EnRoute, Delivered, Failed

The application service interface (IDeliveryService).

  • ScheduleDelivery(order: OrderId, destination: Address): DeliveryId

  • CompleteDelivery(delivery: DeliveryId)

KindCoveredTotal
aggregate11
entity11
enum11
event22
query01
readModel01
value22

⚠️ 2 not documented