Examples·Weekend package checkout

Weekend package checkout

The weekend package checkout is the flagship Blue example. It models a real two-stage checkout: customer payment is secured first, the reseller attaches or creates the hotel and restaurant orders, the PayNote requests completion only after both merchant confirmations arrive, and the parent package order becomes ready_to_use only after payment completion.

The source example is reseller-weekend-package-offer-contract-bex-authoring.yaml. The full document is embedded near the end of this page, after the guided explanation, with the first section visible and the rest hidden behind a read-more disclosure.

§Why this example is perfect for Blue

Most workflow examples are too small. They change a status and call it a day. Real business flows are harder:

  • the customer pays one seller for a package;
  • the package includes more than one merchant deliverable;
  • payment should be secured before the seller commits downstream orders;
  • payment should not complete until the included orders are confirmed;
  • duplicate delivery should not create duplicate component orders;
  • invalid attachments should produce inspectable rejection events;
  • the final package state should be explainable from document state and timeline evidence.

The weekend package example has all of that without becoming abstract. It has a recognizable product: a romantic weekend with a hotel stay and restaurant dinner. It has concrete roles: customer, reseller, hotel, restaurant, and payment guarantor. It has obvious business safety rules. It has enough BEX to show real guards and state transitions.

It is perfect because it is the same model as Counter, scaled to a flow people actually care about.

§The story

The offer is sold by ITC / mega-pakiety.pl. The customer buys a package that includes:

  • a weekend stay for two at Hotel Badura;
  • a premium dinner for two at Restaurant Cud Malina;
  • a package price of 499.00 PLN, represented as 49900 minor units.

The package order starts in a cautious state. It is not ready for checkout until the provider confirms and attaches a checkout payload. The customer payment is represented by a PayNote. The PayNote secures funds first and requests completion only after both included merchant orders confirm.

At the end, the package order should say:

YAML
1status: ready_to_use
2payment:
3 state: completed

That final state is not a hand-written status update. It is the result of processing events across the package order, embedded PayNote, and embedded merchant orders.

§Document map

The source document has this shape:

Snippet
1Package Offer
2├─ product-facing fields
3│ ├─ seller
4│ ├─ price
5│ └─ customerSummary
6├─ orderTemplate
7│ └─ document: Package Order
8│ ├─ status
9│ ├─ payment
10│ ├─ components
11│ ├─ embeddedDocs
12│ │ ├─ packagePayNote
13│ │ └─ orders
14│ │ ├─ hotelOrder
15│ │ └─ restaurantOrder
16│ └─ contracts
17│ ├─ customer/investor channels
18│ ├─ embedded PayNote event channel
19│ ├─ process embedded docs
20│ ├─ package operations
21│ └─ BEX Compute workflows
22└─ offer-level contracts
23 ├─ anchors
24 ├─ investor channel
25 └─ lifecycle initialization

This structure is important. The offer is not the live order. The offer contains an order template. A live customer order can be created from that template and then processed through its own timeline entries.

That is a practical pattern for commerce documents. Product content and process template live together, but each customer order becomes its own processable document.

§State first, contracts second

Before reading any BEX, read the package order state:

YAML
1orderTemplate:
2 document:
3 name: Romantic Weekend with a Premium Dinner for Two Order
4 kind: Package Order
5 status: awaiting_provider_confirmation
6 price:
7 amountMinor: 49900
8 currency: PLN
9 payment:
10 tokenAttached: false
11 payNoteAttached: false
12 state: not_started
13 paymentToken: ''
14 expectedPayNoteDescriptor: {}
15 checkoutMetadata: {}
16 components:
17 hotel:
18 status: not_started
19 orderAttached: false
20 restaurant:
21 status: not_started
22 orderAttached: false
23 embeddedDocs:
24 orders: {}

This is the business surface. Even without reading contracts, you can see the initial assumptions:

  • the provider has not confirmed the package order;
  • no checkout token has been attached;
  • no PayNote has been attached;
  • payment has not started;
  • no hotel or restaurant order has been attached.

The contracts explain how those fields are allowed to change.

§Actors and channels

The source document uses several channels:

YAML
1customerChannel:
2 type: MyOS/MyOS Timeline Channel
3investorChannel:
4 type: MyOS/MyOS Timeline Channel
5embeddedPackagePayNoteEvents:
6 type: Core/Embedded Node Channel
7 childPath: /embeddedDocs/packagePayNote

Inside the PayNote descriptor, there are payer, payee, and guarantor channels:

YAML
1payerChannel:
2 type: MyOS/MyOS Timeline Channel
3payeeChannel:
4 type: MyOS/MyOS Timeline Channel
5guarantorChannel:
6 type: MyOS/MyOS Timeline Channel

Read these as boundaries of authority and evidence. The reseller/provider uses one channel to confirm the package and attach checkout payloads. The PayNote uses participant and guarantor channels for payment lifecycle evidence. Embedded node channels let parent and child documents observe each other's emitted events.

The exact production trust model belongs to the host timeline provider. The document still makes the routing explicit.

§Lifecycle overview

The flow can be read as a sequence of state transitions:

StepTriggerMain result
1Offer existskind: Offer, status: active, order template available.
2Package order startsOrder begins awaiting_provider_confirmation.
3Reseller confirmsStatus moves toward checkout preparation.
4Reseller attaches checkout payloadPayment token and expected PayNote descriptor are stored; order becomes ready_for_checkout.
5PayNote is attachedPayNote snapshot is embedded; payment.payNoteAttached = true.
6PayNote secures fundsParent package marks payment.state = payment_secured.
7Hotel order attachesHotel order snapshot is embedded; hotel component is marked attached.
8Restaurant order attachesRestaurant order snapshot is embedded; restaurant component is marked attached.
9Hotel confirmsHotel order confirmation status becomes confirmed.
10Restaurant confirmsRestaurant order confirmation status becomes confirmed.
11PayNote observes both confirmationsPayNote emits PayNote/Complete Payment Requested.
12Payment completesPayNote emits PayNote/Payment Completed.
13Parent reacts to PayNote completionPackage status becomes ready_to_use; payment state becomes completed.

The order is the point. Payment is not completed merely because the customer clicked checkout. It completes after merchant confirmation evidence is present.

§Operation: confirm the package order

The package order has a confirmOrder operation. Its job is to move the order from awaiting provider confirmation into a state where checkout can be prepared.

The workflow checks whether the order is already in a later state. If so, it returns unchanged. Otherwise, it writes a provider-confirmed pending-payment-token state and emits an order-confirmed event.

This is a basic but important guard pattern:

YAML
1- $if:
2 cond:
3 $or:
4 - $eq: [ { $document: /status }, provider_confirmed_pending_payment_token ]
5 - $eq: [ { $document: /status }, ready_for_checkout ]
6 - $eq: [ { $document: /status }, ready_to_use ]
7 then:
8 - $return:
9 changeset:
10 $changeset: true
11 events:
12 $events: true

The exact source uses the ordinary BEX YAML shape rather than the compact inline list style above. The concept is the same: do not repeat a state transition that already happened.

§Operation: attach the payment token

attachPaymentToken stores a one-time checkout token and an expected PayNote descriptor prepared by the reseller.

The operation is guarded in three ways:

  1. If a token is already attached, return unchanged.
  2. If the provider has not confirmed the package, reject the attachment.
  3. If the payload is missing a token or PayNote descriptor, reject the attachment.

The successful branch writes several fields:

YAML
1- $appendChange:
2 op: replace
3 path: /payment/tokenAttached
4 val: true
5- $appendChange:
6 op: replace
7 path: /payment/paymentToken
8 val:
9 $event: /message/request/paymentToken
10- $appendChange:
11 op: replace
12 path: /payment/expectedPayNoteDescriptor
13 val:
14 $event: /message/request/expectedPayNoteDescriptor
15- $appendChange:
16 op: replace
17 path: /status
18 val: ready_for_checkout
19- $appendEvent:
20 type: Conversation/Event
21 kind: Payment Token Attached
22 orderKind: package

This is a good Stripe-like moment in the flow: checkout readiness is not a vague boolean. It is the result of a provider-confirmed package order plus a stored payment token plus an expected PayNote descriptor.

§The PayNote descriptor

The expected PayNote descriptor says what payment document should appear:

YAML
1expectedPayNoteDescriptor:
2 document:
3 name: Customer to ITC / mega-pakiety.pl Package PayNote
4 type: PayNote/PayNote
5 kind: PayNote
6 description: Customer package payment secured before provider orders.
7 state:
8 type: Text
9 currency: PLN
10 amount:
11 expectedTotal: 49900
12 context:
13 scenario: reseller-weekend-package
14 paymentKind: customer_package_purchase

A PayNote is a document that governs one transaction. It is not the payment rail. It records the participant roles, expected amount, lifecycle state, requests, guarantor responses, and evidence around securing and completing the transaction.

In this example, the PayNote's purpose is specific: secure the customer package payment before provider orders, then complete payment after both merchant orders confirm.

That is exactly the kind of rule that should not be buried in a checkout controller.

§Operation: attach the PayNote

attachPayNote embeds the real PayNote snapshot under the package order:

YAML
1- $appendChange:
2 op: add
3 path: /embeddedDocs/packagePayNote
4 val:
5 $event: /message/request/initialSnapshot
6- $appendChange:
7 op: replace
8 path: /payment/payNoteAttached
9 val: true

Before that, the workflow validates that the snapshot looks like the expected package PayNote:

  • it must have kind: PayNote;
  • it must have context.paymentKind: customer_package_purchase;
  • it must refer to the current package order document id;
  • payment must not already have a PayNote attached.

If validation fails, the workflow emits a PayNote attachment rejection event. That makes invalid evidence visible.

If validation succeeds, the package embeds the PayNote and may move payment state to paynote_attached unless payment is already secured or completed.

§Reacting to funds secured

The parent package order listens to events from the embedded PayNote:

YAML
1embeddedPackagePayNoteEvents:
2 type: Core/Embedded Node Channel
3 childPath: /embeddedDocs/packagePayNote

When the embedded PayNote emits PayNote/Funds Secured, the parent workflow marks payment secured:

YAML
1- $appendChange:
2 op: replace
3 path: /payment/state
4 val: payment_secured

This matters because the package should not start treating downstream merchant orders as safe until the payment is secured. Again, Blue is not moving money. It is recording and reacting to authoritative payment evidence delivered through the PayNote.

§Operation: attach component orders

The package includes two merchant orders: hotel and restaurant. The same operation shape can attach either one:

YAML
1attachComponentOrder:
2 type: Coordination/Operation
3 description: Attaches an initial snapshot of one included merchant order to this package order.
4 channel: investorChannel
5 request:
6 kind:
7 type: Text
8 initialSnapshot:
9 kind: Order
10 orderKind:
11 type: Text
12 context:
13 packageOrderDocumentId:
14 type: Text
15 orderSessionId:
16 type: Text

The BEX checks the requested kind and snapshot shape. A hotel attachment must include a hotel order snapshot. A restaurant attachment must include a restaurant order snapshot.

The key idempotency logic compares existing and incoming identity:

YAML
1sameExisting:
2 $or:
3 - $var: sameExistingByDocumentId
4 - $var: sameExistingBySessionId

If an order is already attached and the new snapshot is different, the workflow emits a rejection event:

YAML
1- $appendEvent:
2 type: Conversation/Event
3 kind: Component Order Attachment Rejected
4 orderKind: hotel
5 reason: component_order_already_attached

If there is no existing order, it adds the snapshot. If the existing order matches, it can replace/update the slot. The patch operation is chosen dynamically:

YAML
1op:
2 $choose:
3 cond:
4 $var: hasExisting
5 then: replace
6 else: add

This is one of the best parts of the example. It shows BEX doing real workflow work: not just arithmetic, but safe document evolution under duplicate and conflicting inputs.

§The PayNote completion gate

Inside the PayNote, completion should be requested only after both merchant orders confirm. The PayNote observes embedded hotel and restaurant order events through embedded node channels.

The guard checks three things:

  1. Hotel confirmation status is confirmed.
  2. Restaurant confirmation status is confirmed.
  3. Completion has not already been requested.

The core shape is:

YAML
1- $if:
2 cond:
3 $or:
4 - $ne:
5 - $document: /embeddedDocs/orders/hotelOrder/confirmation/status
6 - confirmed
7 - $ne:
8 - $document: /embeddedDocs/orders/restaurantOrder/confirmation/status
9 - confirmed
10 - $truthy:
11 $document: /completionRequested
12 then:
13 - $return:
14 changeset:
15 $changeset: true
16 events:
17 $events: true
18- $appendChange:
19 op: replace
20 path: /completionRequested
21 val: true
22- $appendEvent:
23 type: PayNote/Complete Payment Requested
24 amount: 49900

This is the heart of the checkout safety model. A single merchant confirmation is not enough. A duplicate confirmation after completion has already been requested is not enough. Only the first moment when both confirmations are present produces the completion request.

§Parent ready state

The parent package order becomes ready when the embedded PayNote emits PayNote/Payment Completed.

The parent workflow writes:

YAML
1- $appendChange:
2 op: replace
3 path: /status
4 val: ready_to_use
5- $appendChange:
6 op: replace
7 path: /payment/state
8 val: completed

It can also emit a package-ready event:

YAML
1- $appendEvent:
2 type: Conversation/Event
3 kind: Package Ready To Use
4 orderKind: package

Notice the layering. The PayNote requests completion after both confirmations. The guarantor or payment rail eventually provides completion evidence. The parent package reacts to that evidence. The package does not mark itself ready merely because the PayNote requested completion.

That separation is what makes the flow auditable.

§Invariants to test

The source document is large, but the core invariants are clear:

InvariantWhy it matters
A payment token cannot be attached before provider confirmation.Prevents checkout before the seller accepts the package order.
A PayNote must match the current package order.Prevents embedding a payment document for the wrong order.
A component order cannot be replaced by a different order after attachment.Prevents corrupting the package with conflicting merchant snapshots.
Payment completion is requested only after both merchant confirmations.Enforces the two-stage checkout rule.
Completion is requested only once.Prevents duplicate capture/settlement requests.
The package becomes ready_to_use only after PayNote completion.Keeps customer readiness tied to payment governance evidence.

These invariants should become tests.

§Suggested replay test

Build a replay fixture around the full source document embedded below:

  1. Load the offer.
  2. Initialize or clone the order template into a live package order.
  3. Deliver provider confirmation.
  4. Deliver attachPaymentToken with a token and expected PayNote descriptor.
  5. Deliver attachPayNote with a PayNote snapshot bound to this package order.
  6. Deliver a PayNote/Funds Secured event from the embedded PayNote.
  7. Deliver attachComponentOrder for the hotel order.
  8. Deliver attachComponentOrder for the restaurant order.
  9. Deliver hotel confirmation from the hotel order scope.
  10. Assert no completion request before restaurant confirmation if only hotel has confirmed.
  11. Deliver restaurant confirmation.
  12. Assert exactly one PayNote/Complete Payment Requested event.
  13. Deliver PayNote completion evidence.
  14. Assert parent package status is ready_to_use.
  15. Assert parent payment state is completed.
  16. Replay duplicate entries and assert they do not create duplicate effects.

This replay test should be the integration benchmark for the docs.

§What the example deliberately does not do

The document does not call a card API. It does not call Hotel Badura's booking system. It does not call Restaurant Cud Malina's reservation system. It does not decide by itself that a payment rail action has succeeded.

Those actions belong to host systems. Blue represents the process state and deterministic rules around the evidence those systems deliver.

For example, PayNote/Complete Payment Requested is a document event. A payment adapter may listen for it and attempt capture or settlement. The authoritative result comes back as a guarantor/payment event, such as payment completed, failed, declined, reversed, or cancelled depending on the PayNote profile.

That boundary is exactly why the example is good. It does not pretend document logic replaces external systems. It shows how document logic can make external-system coordination inspectable.

§How to read the full source

Do not read the full document top to bottom on the first pass. Read it in this order:

  1. Offer summary: name, description, seller, price, customerSummary.
  2. Order template state: status, payment, components, embeddedDocs.
  3. Channels and embedded processing contracts.
  4. Package operations: confirmOrder, attachPaymentToken, attachPayNote, attachComponentOrder.
  5. PayNote descriptor and PayNote internal contracts.
  6. Completion gates inside PayNote.
  7. Parent reaction to PayNote funds-secured and payment-completed events.
  8. Offer-level lifecycle initialization.

This order keeps the business story ahead of the contract mechanics.

§How this relates to Counter

Counter:

Snippet
1increment entry
2 -> operation
3 -> Compute
4 -> replace /counter
5 -> emit event

Weekend package:

Snippet
1checkout/payment/component/confirmation entries
2 -> operations and embedded event channels
3 -> Compute guards
4 -> replace payment/component/status fields
5 -> emit package, PayNote, and rejection events

The weekend package is not a different architecture. It is Counter with more state surfaces, more actors, and stronger guards.

That is why the docs should keep only these two examples. Counter teaches the loop. Weekend package proves the loop is worth learning.

Full source document

The complete reseller package source is included here so the example can be read without leaving the docs. The first part is visible immediately; expand the rest when you want to inspect the full BEX and contract surface.

yaml
name: Romantic Weekend with a Premium Dinner for Two
description: A subsidized romantic weekend package from ITC / mega-pakiety.pl that combines a Hotel Badura stay with a Restaurant
  Cud Malina dinner. Customer payment is secured first and completed only after both included orders are confirmed.
type: Common/Record
kind: Offer
offerKind: package
status: active
seller:
  name: ITC / mega-pakiety.pl
price:
  amountMinor: 49900
  currency: PLN
customerSummary:
  description: Payment is secured first and captured only after hotel and restaurant orders are confirmed.
  headline: Romantic weekend with a premium dinner
  included:
    hotel:
      description: Deluxe room for 2 people
      title:
        en: Weekend for 2 at Hotel Badura
        pl: Weekend dla 2 osób w Hotelu Badura
      localizedDescription:
        en: Deluxe room for 2 people
        pl: Pokój Deluxe dla 2 osób
      fields:
      - label:
          en: Beds
          pl: Łóżka
        fieldType: text
        fieldValue:
          en: 1 large double bed
          pl: 1 duże podwójne łóżko
      - label:
          en: Stay
          pl: Pobyt
        fieldType: text
        fieldValue:
          en: One-night weekend stay
          pl: Jednonocny pobyt weekendowy
      - label:
          en: Meals
          pl: Wyżywienie
        fieldType: text
        fieldValue:
          en: Breakfast included
          pl: Śniadanie w cenie
      - label:
          en: Check-in from
          pl: Zameldowanie od
        fieldType: time
        fieldValue: '15:00'
      - label:
          en: Check-out until
          pl: Wymeldowanie do
        fieldType: time
        fieldValue: '11:00'
      - label:
          en: Location
          pl: Lokalizacja
        fieldType: text
        fieldValue:
          en: Comfortable stay in a quiet area of Wadowice
          pl: Komfortowy pobyt w spokojnej okolicy Wadowic
      - label:
          en: Address
          pl: Adres
        fieldType: text
        fieldValue: Wenecja 4, 34-100 Wadowice
    restaurant:
      description: Premium romantic dinner for two at Cud Malina Restaurant
      title:
        en: Dinner at Cud Malina Restaurant
        pl: Kolacja w Restauracji Cud Malina
      localizedDescription:
        en: Premium romantic dinner for two at Cud Malina Restaurant
        pl: Romantyczna kolacja premium dla dwojga w Restauracji Cud Malina
      fields:
      - label:
          en: Menu
          pl: Menu
        fieldType: plainText
        fieldValue:
          en: Starter, main course, and dessert selected from the menu, plus wine
          pl: Przystawka, danie główne i deser wybrane z menu oraz wino
      - label:
          en: Address
          pl: Adres
        fieldType: plainText
        fieldValue: Plac Tadeusza Kościuszki 22, 34-100 Wadowice
orderTemplate:
  document:
    name: Romantic Weekend with a Premium Dinner for Two Order
    description: The customer's order for the Romantic Weekend with a Premium Dinner package. This order tracks checkout,
      the included hotel and restaurant orders, and readiness to use.
    type: Common/Record
    kind: Package Order
    status: awaiting_provider_confirmation
    price:
      amountMinor: 49900
      currency: PLN
    payment:
      tokenAttached: false
      payNoteAttached: false
      state: not_started
      paymentToken: ''
      expectedPayNoteDescriptor: {}
      checkoutMetadata: {}
    components:
      hotel:
        title:
          en: Weekend for 2 at Hotel Badura
          pl: Weekend dla 2 osób w Hotelu Badura
        status: not_started
        orderAttached: false
      restaurant:
        title:
          en: Dinner at Cud Malina Restaurant
          pl: Kolacja w Restauracji Cud Malina
        status: not_started
        orderAttached: false
    embeddedDocs:
      orders: {}
    contracts:
      customerChannel:
        type: MyOS/MyOS Timeline Channel
      investorChannel:
        type: MyOS/MyOS Timeline Channel
      anchors:
        type: MyOS/Document Anchors
        payments:
          name: Payments
          type: MyOS/Document Anchor
      links:
        type: MyOS/Document Links
        packageOffer:
          type: MyOS/Document Link
          anchor: orders
          documentId: ''
      embeddedPackagePayNoteEvents:
        type: Core/Embedded Node Channel
        childPath: /embeddedDocs/packagePayNote
      processEmbeddedDocs:
        type: Core/Process Embedded
        paths:
        - /embeddedDocs/packagePayNote
        - /embeddedDocs/orders/hotelOrder
        - /embeddedDocs/orders/restaurantOrder
      markPaymentSecuredFromPayNoteEvent:
        type: Coordination/Sequential Workflow
        channel: embeddedPackagePayNoteEvents
        event:
          type: PayNote/Funds Secured
        steps:
        - name: BuildPaymentSecuredPatch
          type: Coordination/Compute
          emitEvents: true
          do:
          - $if:
              cond:
                $or:
                - $eq:
                  - $document: /payment/state
                  - payment_secured
                - $eq:
                  - $document: /payment/state
                  - completed
              then:
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $appendChange:
              op: replace
              path: /payment/state
              val: payment_secured
          - $return:
              changeset:
                $changeset: true
              events:
                $events: true
      markReadyFromPayNoteCompletedEvent:
        type: Coordination/Sequential Workflow
        channel: embeddedPackagePayNoteEvents
        event:
          type: PayNote/Payment Completed
        steps:
        - name: BuildReadyPatch
          type: Coordination/Compute
          emitEvents: true
          do:
          - $if:
              cond:
                $and:
                - $eq:
                  - $document: /status
                  - ready_to_use
                - $eq:
                  - $document: /payment/state
                  - completed
              then:
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $appendChange:
              op: replace
              path: /status
              val: ready_to_use
          - $appendChange:
              op: replace
              path: /payment/state
              val: completed
          - $if:
              cond:
                $ne:
                - $document: /status
                - ready_to_use
              then:
              - $appendEvent:
                  type: Conversation/Event
                  kind: Package Ready To Use
                  orderKind: package
          - $return:
              changeset:
                $changeset: true
              events:
                $events: true
      overview:
        type: Conversation/Document Section
        relatedFields:
        - /name
        - /description
        - /price
        title: Package
      paymentSafety:
        type: Conversation/Document Section
        relatedFields:
        - /payment
Read more: show the rest of the source document
yaml
        - /payment/checkoutMetadata
        summary: Payment is secured first and captured only after hotel and restaurant orders are confirmed.
        title: Secure checkout
      includedOrders:
        type: Conversation/Document Section
        relatedFields:
        - /embeddedDocs/orders/hotelOrder
        - /embeddedDocs/orders/restaurantOrder
        title: Included orders
      statusSection:
        type: Conversation/Document Section
        relatedFields:
        - /status
        - /embeddedDocs/packagePayNote
        title: Status
      confirmOrder:
        type: Coordination/Operation
        description: Seller confirmation that this package order is accepted and checkout can be prepared.
        channel: investorChannel
      confirmOrderImpl:
        type: Coordination/Sequential Workflow Operation
        operation: confirmOrder
        steps:
        - name: BuildConfirmation
          type: Coordination/Compute
          emitEvents: true
          do:
          - $if:
              cond:
                $or:
                - $eq:
                  - $document: /status
                  - provider_confirmed_pending_payment_token
                - $eq:
                  - $document: /status
                  - provider_confirmed
                - $eq:
                  - $document: /status
                  - ready_for_checkout
                - $eq:
                  - $document: /status
                  - ready_to_use
              then:
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $appendChange:
              op: replace
              path: /status
              val: provider_confirmed_pending_payment_token
          - $appendEvent:
              type: Conversation/Event
              kind: Order Confirmed
              orderKind: package
          - $return:
              changeset:
                $changeset: true
              events:
                $events: true
      attachPaymentToken:
        type: Coordination/Operation
        description: Attaches a one-time checkout token and PayNote descriptor prepared by ITC / mega-pakiety.pl.
        channel: investorChannel
        request:
          paymentToken:
            type: Text
          expectedPayNoteDescriptor:
            document:
              name: Customer to ITC / mega-pakiety.pl Package PayNote
              type: PayNote/PayNote
              kind: PayNote
              description: Customer package payment secured before provider orders.
              payNoteInitialStateDescription:
                summary: Payment for the Romantic Weekend with a Premium Dinner package.
                details: 'This PayNote secures the customer''s package payment to ITC / mega-pakiety.pl. The payment is completed
                  only after both included merchant orders are confirmed: Hotel Badura confirms the weekend stay order and
                  Restaurant Cud Malina confirms the dinner order. Once both confirmations are present, the package payment
                  is completed and the package becomes ready to use.'
              state:
                type: Text
              currency: PLN
              amount:
                expectedTotal: 49900
              context:
                scenario: reseller-weekend-package
                paymentKind: customer_package_purchase
                packageOrderDocumentId:
                  type: Text
                packagePayNoteSessionId:
                  type: Text
                packagePayNoteDocumentId:
                  type: Text
              embeddedDocs:
                orders: {}
              completionRequested:
                type: Boolean
              contracts:
                payerChannel:
                  type: MyOS/MyOS Timeline Channel
                payeeChannel:
                  type: MyOS/MyOS Timeline Channel
                guarantorChannel:
                  type: MyOS/MyOS Timeline Channel
                links:
                  type: MyOS/Document Links
                  packageOrder:
                    type: MyOS/Document Link
                    documentId:
                      type: Text
                    anchor: payments
                  packageOffer:
                    type: MyOS/Document Link
                    documentId:
                      type: Text
                    anchor: customerPayNotes
                embeddedHotelOrderEvents:
                  type: Core/Embedded Node Channel
                  childPath: /embeddedDocs/orders/hotelOrder
                embeddedRestaurantOrderEvents:
                  type: Core/Embedded Node Channel
                  childPath: /embeddedDocs/orders/restaurantOrder
                processEmbeddedComponentOrders:
                  type: Core/Process Embedded
                  paths:
                  - /embeddedDocs/orders/hotelOrder
                  - /embeddedDocs/orders/restaurantOrder
                completeWhenOrdersConfirmedFromHotelEvent:
                  type: Coordination/Sequential Workflow
                  channel: embeddedHotelOrderEvents
                  event:
                    type: Conversation/Event
                    kind: Order Confirmed
                  steps:
                  - name: BuildCompletion
                    type: Coordination/Compute
                    emitEvents: true
                    do:
                    - $if:
                        cond:
                          $or:
                          - $ne:
                            - $document: /embeddedDocs/orders/hotelOrder/confirmation/status
                            - confirmed
                          - $ne:
                            - $document: /embeddedDocs/orders/restaurantOrder/confirmation/status
                            - confirmed
                          - $truthy:
                              $document: /completionRequested
                        then:
                        - $return:
                            changeset:
                              $changeset: true
                            events:
                              $events: true
                    - $appendChange:
                        op: replace
                        path: /completionRequested
                        val: true
                    - $appendEvent:
                        type: PayNote/Complete Payment Requested
                        amount: 49900
                    - $return:
                        changeset:
                          $changeset: true
                        events:
                          $events: true
                completeWhenOrdersConfirmedFromRestaurantEvent:
                  type: Coordination/Sequential Workflow
                  channel: embeddedRestaurantOrderEvents
                  event:
                    type: Conversation/Event
                    kind: Order Confirmed
                  steps:
                  - name: BuildCompletion
                    type: Coordination/Compute
                    emitEvents: true
                    do:
                    - $if:
                        cond:
                          $or:
                          - $ne:
                            - $document: /embeddedDocs/orders/hotelOrder/confirmation/status
                            - confirmed
                          - $ne:
                            - $document: /embeddedDocs/orders/restaurantOrder/confirmation/status
                            - confirmed
                          - $truthy:
                              $document: /completionRequested
                        then:
                        - $return:
                            changeset:
                              $changeset: true
                            events:
                              $events: true
                    - $appendChange:
                        op: replace
                        path: /completionRequested
                        val: true
                    - $appendEvent:
                        type: PayNote/Complete Payment Requested
                        amount: 49900
                    - $return:
                        changeset:
                          $changeset: true
                        events:
                          $events: true
                attachComponentOrder:
                  type: Coordination/Operation
                  description: Attaches an included merchant order snapshot so package payment can complete after both confirmations.
                  channel: payeeChannel
                  request:
                    kind:
                      type: Text
                    initialSnapshot:
                      type: Common/Record
                      kind: Order
                      orderKind:
                        type: Text
                      status:
                        type: Text
                      context:
                        packageOrderDocumentId:
                          type: Text
                        orderSessionId:
                          type: Text
                      orderDetails:
                        type: Dictionary
                      payment:
                        tokenAttached:
                          type: Boolean
                        paymentToken:
                          type: Text
                      confirmation:
                        status:
                          type: Text
                      fulfillment:
                        status:
                          type: Text
                      contracts:
                        type: Dictionary
                attachComponentOrderImpl:
                  type: Coordination/Sequential Workflow Operation
                  operation: attachComponentOrder
                  steps:
                  - name: BuildComponentAttachment
                    type: Coordination/Compute
                    emitEvents: true
                    do:
                    - $if:
                        cond:
                          $and:
                          - $and:
                            - $eq:
                              - $event: /message/request/kind
                              - hotel
                            - $eq:
                              - $event: /message/request/initialSnapshot/kind
                              - Order
                            - $eq:
                              - $event: /message/request/initialSnapshot/orderKind
                              - hotel
                          - $eq:
                            - $event: /message/request/initialSnapshot/context/packageOrderDocumentId
                            - $document: /context/packageOrderDocumentId
                        then:
                        - $appendChange:
                            op: add
                            path: /embeddedDocs/orders/hotelOrder
                            val:
                              $event: /message/request/initialSnapshot
                        - $appendEvent:
                            type: Conversation/Event
                            kind: Component Order Attached
                            orderKind: hotel
                        - $return:
                            changeset:
                              $changeset: true
                            events:
                              $events: true
                    - $if:
                        cond:
                          $and:
                          - $and:
                            - $eq:
                              - $event: /message/request/kind
                              - restaurant
                            - $eq:
                              - $event: /message/request/initialSnapshot/kind
                              - Order
                            - $eq:
                              - $event: /message/request/initialSnapshot/orderKind
                              - restaurant
                          - $eq:
                            - $event: /message/request/initialSnapshot/context/packageOrderDocumentId
                            - $document: /context/packageOrderDocumentId
                        then:
                        - $appendChange:
                            op: add
                            path: /embeddedDocs/orders/restaurantOrder
                            val:
                              $event: /message/request/initialSnapshot
                        - $appendEvent:
                            type: Conversation/Event
                            kind: Component Order Attached
                            orderKind: restaurant
                        - $return:
                            changeset:
                              $changeset: true
                            events:
                              $events: true
                    - $appendEvent:
                        type: Conversation/Event
                        kind: Component Order Attachment Rejected
                        orderKind:
                          $event: /message/request/kind
                    - $return:
                        changeset:
                          $changeset: true
                        events:
                          $events: true
            channelBindings:
              payerChannel:
                type: MyOS/MyOS Timeline Channel
                accountId:
                  type: Text
              payeeChannel:
                type: MyOS/MyOS Timeline Channel
                accountId:
                  type: Text
              guarantorChannel:
                type: MyOS/MyOS Timeline Channel
                accountId: '0'
          checkoutMetadata:
            type: Dictionary
      attachPaymentTokenImpl:
        type: Coordination/Sequential Workflow Operation
        operation: attachPaymentToken
        steps:
        - name: BuildPaymentTokenPatch
          type: Coordination/Compute
          emitEvents: true
          do:
          - $if:
              cond:
                $eq:
                - $document: /payment/tokenAttached
                - true
              then:
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $if:
              cond:
                $or:
                - $and:
                  - $ne:
                    - $document: /status
                    - provider_confirmed_pending_payment_token
                  - $ne:
                    - $document: /status
                    - provider_confirmed
                - $not:
                    $truthy:
                      $event: /message/request/paymentToken
                - $not:
                    $truthy:
                      $event: /message/request/expectedPayNoteDescriptor/document
              then:
              - $appendEvent:
                  type: Conversation/Event
                  kind: Payment Token Attachment Rejected
                  reason: provider_not_confirmed_or_missing_checkout_payload
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $appendChange:
              op: replace
              path: /payment/tokenAttached
              val: true
          - $appendChange:
              op: replace
              path: /payment/paymentToken
              val:
                $event: /message/request/paymentToken
          - $appendChange:
              op: replace
              path: /payment/expectedPayNoteDescriptor
              val:
                $event: /message/request/expectedPayNoteDescriptor
          - $appendChange:
              op: replace
              path: /payment/checkoutMetadata
              val:
                $default:
                - $event: /message/request/checkoutMetadata
                - $emptyObject: true
          - $appendChange:
              op: replace
              path: /status
              val: ready_for_checkout
          - $appendEvent:
              type: Conversation/Event
              kind: Payment Token Attached
              orderKind: package
          - $return:
              changeset:
                $changeset: true
              events:
                $events: true
      attachPayNote:
        type: Coordination/Operation
        description: Attaches the secured customer package PayNote discovered through the order's payments anchor.
        channel: investorChannel
        request:
          initialSnapshot:
            kind: PayNote
      attachPayNoteImpl:
        type: Coordination/Sequential Workflow Operation
        operation: attachPayNote
        steps:
        - name: BuildPayNoteAttachment
          type: Coordination/Compute
          emitEvents: true
          do:
          - $if:
              cond:
                $or:
                - $ne:
                  - $event: /message/request/initialSnapshot/kind
                  - PayNote
                - $ne:
                  - $event: /message/request/initialSnapshot/context/paymentKind
                  - customer_package_purchase
                - $not:
                    $truthy:
                      $document: /contracts/initialized/documentId
                - $ne:
                  - $event: /message/request/initialSnapshot/context/packageOrderDocumentId
                  - $document: /contracts/initialized/documentId
              then:
              - $appendEvent:
                  type: Conversation/Event
                  kind: PayNote Attachment Rejected
                  reason: invalid_paynote_snapshot
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $if:
              cond:
                $eq:
                - $document: /payment/payNoteAttached
                - true
              then:
              - $appendEvent:
                  type: Conversation/Event
                  kind: PayNote Attachment Rejected
                  reason: paynote_already_attached
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $appendChange:
              op: add
              path: /embeddedDocs/packagePayNote
              val:
                $event: /message/request/initialSnapshot
          - $appendChange:
              op: replace
              path: /payment/payNoteAttached
              val: true
          - $if:
              cond:
                $and:
                - $ne:
                  - $document: /payment/state
                  - completed
                - $ne:
                  - $document: /payment/state
                  - payment_secured
                - $ne:
                  - $document: /payment/state
                  - paynote_attached
              then:
              - $appendChange:
                  op: replace
                  path: /payment/state
                  val: paynote_attached
          - $return:
              changeset:
                $changeset: true
              events:
                $events: true
      attachComponentOrder:
        type: Coordination/Operation
        description: Attaches an initial snapshot of one included merchant order to this package order.
        channel: investorChannel
        request:
          kind:
            type: Text
          initialSnapshot:
            kind: Order
      attachComponentOrderImpl:
        type: Coordination/Sequential Workflow Operation
        operation: attachComponentOrder
        steps:
        - name: BuildComponentAttachment
          type: Coordination/Compute
          emitEvents: true
          do:
          - $if:
              cond:
                $and:
                - $eq:
                  - $event: /message/request/kind
                  - hotel
                - $eq:
                  - $event: /message/request/initialSnapshot/kind
                  - Order
                - $eq:
                  - $event: /message/request/initialSnapshot/orderKind
                  - hotel
              then:
              - $appendChange:
                  op: add
                  path: /embeddedDocs/orders/hotelOrder
                  val:
                    $event: /message/request/initialSnapshot
              - $appendChange:
                  op: replace
                  path: /components/hotel/orderAttached
                  val: true
              - $appendChange:
                  op: replace
                  path: /components/hotel/status
                  val: order_attached
              - $appendEvent:
                  type: Conversation/Event
                  kind: Component Order Attached
                  orderKind: hotel
                  orderSessionId:
                    $event: /message/request/initialSnapshot/context/orderSessionId
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $if:
              cond:
                $and:
                - $eq:
                  - $event: /message/request/kind
                  - restaurant
                - $eq:
                  - $event: /message/request/initialSnapshot/kind
                  - Order
                - $eq:
                  - $event: /message/request/initialSnapshot/orderKind
                  - restaurant
              then:
              - $appendChange:
                  op: add
                  path: /embeddedDocs/orders/restaurantOrder
                  val:
                    $event: /message/request/initialSnapshot
              - $appendChange:
                  op: replace
                  path: /components/restaurant/orderAttached
                  val: true
              - $appendChange:
                  op: replace
                  path: /components/restaurant/status
                  val: order_attached
              - $appendEvent:
                  type: Conversation/Event
                  kind: Component Order Attached
                  orderKind: restaurant
                  orderSessionId:
                    $event: /message/request/initialSnapshot/context/orderSessionId
              - $return:
                  changeset:
                    $changeset: true
                  events:
                    $events: true
          - $appendEvent:
              type: Conversation/Event
              kind: Component Order Attachment Rejected
              orderKind:
                $event: /message/request/kind
          - $return:
              changeset:
                $changeset: true
              events:
                $events: true
contracts:
  anchors:
    type: MyOS/Document Anchors
    orders:
      name: Orders
      type: MyOS/Document Anchor
    customerPayNotes:
      name: Customer PayNotes
      type: MyOS/Document Anchor
  investorChannel:
    type: MyOS/MyOS Timeline Channel
  initLifecycleChannel:
    type: Core/Lifecycle Event Channel
    event:
      type: Core/Document Processing Initiated
  initializeOrderTemplateSourceOfferLink:
    type: Coordination/Sequential Workflow
    channel: initLifecycleChannel
    steps:
    - name: BuildOrderTemplateLinkPatch
      type: Coordination/Compute
      emitEvents: true
      do:
      - $if:
          cond:
            $or:
            - $not:
                $truthy:
                  $document: /contracts/initialized/documentId
            - $eq:
              - $document: /orderTemplate/document/contracts/links/packageOffer/documentId
              - $document: /contracts/initialized/documentId
          then:
          - $return:
              changeset:
                $changeset: true
              events:
                $events: true
      - $appendChange:
          op: replace
          path: /orderTemplate/document/contracts/links/packageOffer/documentId
          val:
            $document: /contracts/initialized/documentId
      - $return:
          changeset:
            $changeset: true
          events:
            $events: true
  packageSection:
    type: Conversation/Document Section
    relatedFields:
    - /name
    - /description
    - /seller
    - /price
    title: Package summary
  includedSection:
    type: Conversation/Document Section
    relatedFields:
    - /customerSummary/included
    title: Included experiences
  checkoutSection:
    type: Conversation/Document Section
    relatedFields:
    - /customerSummary
    - /orderTemplate
    title: Secure checkout