# Orders

### Overview

Order synchronization is **bidirectional**:

* **Omnium → Flow:** When an order is created or updated in Omnium (e.g., a web order), it is sent to Flow via a webhook event. Flow creates the order locally for processing in the POS.
* **Flow → Omnium:** When a POS transaction occurs in Flow (sale, return, cancellation), the order is pushed to Omnium through the async job queue.

Both **Click & Collect** and **Online** order types from Omnium are supported, each with their own handling flow in Flow.

### Omnium → Flow (inbound orders)

#### How inbound orders arrive

1. An order is created or updated in Omnium
2. Omnium sends a **webhook event** to Flow's Omnium Event API endpoint
3. Flow creates an **inbound sync job** in the `external_order_sync` queue
4. The sync engine picks up the job and fetches the full order from Omnium's REST API
5. The order is created or updated in Flow

Deduplication is built in — if a pending sync job already exists for the same order, no duplicate job is created.

#### Click & Collect orders

When the order type is `ClickAndCollect`:

1. The order is created in Flow with state `PARKED`
2. A **Click & Collect handling** task is attached to the order (configured via `OMNIUM_CLICK_COLLECT_ORDERHANDLING_UID`)
3. If `OMNIUM_CLICK_COLLECT_EXPIRY_DAYS` is set and the order has no `validUntil` date, a pickup deadline is calculated using working days from the current date
4. Store staff can then process the order — pick items, notify the customer, and complete the handover

#### Online orders

When the order type is `OnlineOrder`:

1. The order is created in Flow with state `CONFIRMED`
2. An **Online order handling** task is attached (configured via `OMNIUM_ONLINE_ORDER_HANDLING_UID`)
3. The order is ready for shipping or further processing

#### Order updates from Omnium

When an existing order is updated from Omnium:

1. Flow reopens the order (sets state to `OPEN`)
2. New line items from Omnium are added to the Flow order
3. Existing line items are updated if quantities, prices, or discounts have changed
4. Line items removed from Omnium are deleted from the Flow order (unless they are referenced returns)
5. Order deliveries are synchronized (created, updated, or removed)
6. Additional notes are synced
7. The order state is set back to `PARKED` or `CONFIRMED`

If the update adds items that weren't in the Omnium order, a new outbound sync job is created to push the changes back.

#### Delivery processing from Omnium

When an Omnium order reaches state `COMPLETE` with delivery information:

1. Flow compares its order items with Omnium's shipment line items
2. For each item with a `deliveredQuantity` in Omnium, Flow triggers a delivery
3. If the shipment warehouse differs from the Flow item's warehouse, the warehouse is updated first
4. Items are delivered only if the reserved quantity is sufficient

### Flow → Omnium (outbound orders)

#### Order creation (POS sales)

When a sale is completed in Flow POS:

1. An outbound sync job is added to the queue
2. The sync engine checks if the order already exists in Omnium (GET by order UID)
3. If not found (404), the order is created in Omnium
4. Omnium returns the created order with assigned IDs
5. Flow updates its order heading with the `externalOrderNumber` from Omnium
6. Flow updates each order line with the `externalId` from Omnium's response

#### Order updates

When a Flow order that already exists in Omnium is modified:

1. The current Omnium order is fetched
2. Line items removed from Flow are cancelled in Omnium via the cancel order line API
3. The Flow order is mapped to an Omnium order and **merged** with the existing Omnium data
4. The merged order is sent as an update
5. Shipment statuses are updated individually via Omnium's workflow API
6. The order status is updated via Omnium's workflow API

#### Order cancellation

When a Flow order is cancelled:

1. The Omnium order status is updated to `OrderCanceled` via the workflow API

#### Return orders

Returns are handled differently depending on whether they reference an original order:

**Referenced returns** (with credit links to original order lines):

1. The original order is locked to prevent concurrent modifications
2. A return request is created in Omnium using the `Returns` API, referencing the original order's line items
3. If the return includes new sales lines (exchange), an **exchange order** is created in Omnium
4. The exchange order is then updated with full order details

**Non-referenced returns** (standalone returns without links):

* Treated as regular orders and created directly in Omnium
* Return quantities are sent as negative `creditQuantity` values on the line items

Only settled return orders are exported — unsettled returns are skipped and retried later.

#### Invoice and receipt sync

When `OMNIUM_SEND_ORDER_RECEIPT_TO_OMNIUM` is enabled:

1. After the order is synced, Flow checks for pending receipt sync records
2. For each receipt, a PDF is generated from the Flow receipt
3. An **invoice** is created in Omnium with line items and payment details
4. The PDF is attached to the invoice as a file
5. The sync record is marked as complete

Two invoice types are supported:

* **Standard invoice** — maps order receipt line items and settlements
* **Payment invoice** — for payment-type orders (e.g., down payments), uses a single `REMITTANCE` line item

### Order status mapping

#### Flow → Omnium

Flow's order state is a combination of three fields (`orderState`, `settleState`, `deliveryState`), which maps to a single Omnium status:

| Flow state                                                                      | Omnium status          |
| ------------------------------------------------------------------------------- | ---------------------- |
| `PARKED`                                                                        | `Parked`               |
| `CONFIRMED`                                                                     | `Confirmed`            |
| `CANCELED`                                                                      | `OrderCanceled`        |
| `COMPLETE` + settle `NOT_STARTED`                                               | `AwaitingPayment`      |
| `COMPLETE` + settle `IN_PROGRESS`                                               | `SettlementInProgress` |
| `COMPLETE` + settle `COMPLETE` + delivery `NOT_STARTED`                         | `DeliveryNotStarted`   |
| `COMPLETE` + settle `COMPLETE` + delivery `IN_PROGRESS`                         | `Picking`              |
| `COMPLETE` + settle `COMPLETE` + delivery `COMPLETE`                            | `PickedUp`             |
| `COMPLETE` + settle `COMPLETE` + delivery `COMPLETE` + Click & Collect complete | `PickedUpAndPaid`      |
| `COMPLETE` + settle `COMPLETE` + delivery `COMPLETE` + Online order complete    | `Ship`                 |

#### Click & Collect / Online handling states

When an order has a handling task and is not yet settled, the handling state overrides the order status:

| Handling state | Omnium status    |
| -------------- | ---------------- |
| `NotStarted`   | `InProgress`     |
| `Complete`     | `ReadyForPickup` |

#### Omnium → Flow

| Omnium status        | Flow orderState | Flow settleState | Flow deliveryState |
| -------------------- | --------------- | ---------------- | ------------------ |
| `Parked`             | `PARKED`        | `NOT_STARTED`    | `NOT_STARTED`      |
| `Confirmed`          | `CONFIRMED`     | `NOT_STARTED`    | `NOT_STARTED`      |
| `OrderCanceled`      | `CANCELED`      | `NOT_STARTED`    | `NOT_STARTED`      |
| `CompletedInPos`     | `COMPLETE`      | `COMPLETE`       | `COMPLETE`         |
| `DeliveryNotStarted` | `COMPLETE`      | `COMPLETE`       | `NOT_STARTED`      |
| `Picking`            | `COMPLETE`      | `COMPLETE`       | `IN_PROGRESS`      |
| `PickedUp`           | `COMPLETE`      | `COMPLETE`       | `COMPLETE`         |

#### Shipment status mapping

| Delivery state             | Omnium shipment status |
| -------------------------- | ---------------------- |
| `DeliveredAtSale`          | `CompletedInPos`       |
| `Delivered` (online order) | `Ship`                 |
| `Delivered` (other)        | `PickedUp`             |
| Default with items         | `PartiallyPickedUp`    |
| Default without items      | `DeliveryNotStarted`   |
| Order is `PARKED`          | `Parked`               |

### Order field mapping (Flow → Omnium)

#### Order header

| Omnium field          | Flow source                             | Notes                                        |
| --------------------- | --------------------------------------- | -------------------------------------------- |
| `id`                  | `order.Uid`                             | —                                            |
| `orderNumber`         | `order.OrderNumber`                     | —                                            |
| `orderType`           | `"FlowPos"`                             | Set on creation only                         |
| `status`              | Derived                                 | See status mapping above                     |
| `storeId`             | `order.Store.Uid`                       | —                                            |
| `marketId`            | `store.ExternalId`                      | —                                            |
| `customerId`          | `customer.ExternalId` or `customer.Uid` | ExternalId preferred                         |
| `customerType`        | Derived                                 | `"B2C"` or `"B2B"` based on customer/address |
| `customerEmail`       | `orderAddress.Email`                    | —                                            |
| `customerName`        | Display name                            | From order address                           |
| `customerPhone`       | `orderAddress.Mobile`                   | —                                            |
| `billingAddress`      | Invoice address or order address        | Invoice address preferred                    |
| `billingCurrency`     | `tenant.Country.Currency`               | —                                            |
| `total`               | `orderTotals.GrandTotal`                | Converted to float                           |
| `subTotal`            | `orderTotals.SubTotal`                  | Converted to float                           |
| `taxTotal`            | `orderTotals.TotalVat`                  | Converted to float                           |
| `discountTotalIncVat` | `orderTotals.TotalDiscount`             | Converted to float                           |
| `lineItemsCost`       | `orderTotals.TotalCost`                 | Converted to float                           |
| `remainingPayment`    | `settlementTotals.Remaining`            | Converted to float                           |
| `salesPersonId`       | `tenantUser.UserCode`                   | —                                            |
| `salesPersonName`     | `tenantUserDisplayName`                 | —                                            |
| `orderOrigin`         | `order.Origin`                          | —                                            |
| `created`             | `order.OrderDate` or `order.CreatedAt`  | With regional timezone                       |
| `modified`            | `order.LastModifiedAt`                  | With regional timezone                       |
| `orderNotes`          | `order.Note` + `order.AdditionalNotes`  | —                                            |

#### Line items

| Omnium field                | Flow source                    | Notes                                                |
| --------------------------- | ------------------------------ | ---------------------------------------------------- |
| `lineItemId`                | `orderLine.Uid`                | —                                                    |
| `code`                      | `orderLine.Sku`                | —                                                    |
| `displayName`               | `orderLine.Name`               | —                                                    |
| `quantity`                  | `orderLine.QtyOrdered`         | Absolute value for sales                             |
| `returnQuantity`            | `orderLine.QtyOrdered`         | Absolute value for returns                           |
| `deliveredQuantity`         | `orderLine.QtyDelivered`       | 0 if order is parked                                 |
| `placedPrice`               | `orderLine.Price`              | Converted to float                                   |
| `extendedPrice`             | `orderLine.LineTotal`          | Converted to float                                   |
| `discounted`                | `orderLine.LineDiscountAmount` | Converted to float                                   |
| `cost`                      | `orderLine.CostPrice`          | Converted to float                                   |
| `costTotal`                 | `orderLine.LineCostPrice`      | Converted to float                                   |
| `taxRate`                   | `orderLine.VatRate`            | Converted to float                                   |
| `taxTotal`                  | `orderLine.LineVatAmount`      | Converted to float                                   |
| `serialNumber`              | `orderLine.SerialNumber`       | —                                                    |
| `comment`                   | `orderLine.Note`               | —                                                    |
| `imageUrl`                  | `orderLine.CoverImage.MainUrl` | —                                                    |
| `reservedInventory`         | `orderLine.QtyReserved != 0`   | Boolean                                              |
| `reservedInventoryQuantity` | `orderLine.QtyReserved`        | Converted to float                                   |
| `isBackorder`               | Derived                        | True if reservation type is purchase order           |
| `createPurchaseOrder`       | Derived                        | True if reservation type is `REQUEST_PURCHASE_ORDER` |
| `updateStock`               | `orderLine.QtyDelivered != 0`  | Boolean                                              |
| `isPackage`                 | Derived                        | True for package products                            |
| `returnType`                | `orderLine.ReturnReasonCode`   | —                                                    |

#### Line item properties

Each line item includes properties with detailed Flow metadata:

| Property key                         | Key group        | Description                                          |
| ------------------------------------ | ---------------- | ---------------------------------------------------- |
| `flow.order_line.id`                 | `flow.OrderLine` | Flow line item ID                                    |
| `flow.order_line.uid`                | `flow.OrderLine` | Flow line item UID                                   |
| `flow.product.id`                    | `flow.OrderLine` | Flow product ID                                      |
| `flow.product.uid`                   | `flow.OrderLine` | Flow product UID                                     |
| `flow.order_line.product_group_uid`  | `flow.OrderLine` | Product group UID                                    |
| `flow.order_line.product_type`       | `flow.OrderLine` | Product type                                         |
| `flow.seller.code`                   | `flow.OrderLine` | Seller user code                                     |
| `flow.vat_code`                      | `flow.OrderLine` | VAT code UID                                         |
| `flow.line_no`                       | `flow.OrderLine` | Line number                                          |
| `flow.warehouse.id`                  | `flow.OrderLine` | Warehouse ID                                         |
| `flow.warehouse.uid`                 | `flow.OrderLine` | Warehouse UID                                        |
| `flow.order_line.voucher_number`     | `flow.OrderLine` | Receipt voucher number                               |
| `flow.discount_reason_code`          | `flow.OrderLine` | Discount reason code                                 |
| `flow.discount_reason_reference`     | `flow.OrderLine` | Discount reference                                   |
| `flow.return_reason_code`            | `flow.OrderLine` | Return reason code                                   |
| `flow.order_line.credit_reference.*` | `flow.OrderLine` | Credit reference details (voucher, order, line)      |
| `flow.main_product.line_no`          | `flow.OrderLine` | Parent product line (for services/insurance/freight) |
| `flow.main_product.link_type`        | `flow.OrderLine` | Link type (INSURANCE, SERVICE, FREIGHT\_SERVICE)     |
| `voyado.order.id`                    | `voyado`         | Voyado order ID (voucher number, for FlowPos orders) |

#### Payments

| Omnium field        | Flow source                       | Notes                                        |
| ------------------- | --------------------------------- | -------------------------------------------- |
| `id`                | `settlement.Uid`                  | —                                            |
| `amount`            | `settlement.Amount`               | Converted to float                           |
| `paymentMethodName` | Omnium mapping or settlement code | Uses Omnium system code mapping if available |
| `paymentType`       | `settlement.SettlementCode`       | —                                            |
| `status`            | Derived                           | `Processed` for complete, `Failed` otherwise |
| `transactionType`   | —                                 | Always `"Sale"`                              |
| `transactionId`     | `settlement.Uid`                  | —                                            |
| `paidDate`          | `settlement.SettledAt`            | —                                            |
| `invoiceId`         | Receipt voucher number            | —                                            |
| `internalReference` | `settlement.DeviceIdentifier`     | —                                            |

Skipped settlements:

* Incomplete or cancelled settlements
* Pre-payments
* Settlements linked to a pre-payment

**Cash/cashback merging:** If both a `CASH` and `CASHBACK` settlement exist, they are merged into a single `CASH` payment before export.

**Rounding:** Rounding settlements have their amount negated before export.

#### Payment properties

| Property key                                 | Key group         | Description                            |
| -------------------------------------------- | ----------------- | -------------------------------------- |
| `flow.settlement.code`                       | `flow.Settlement` | Settlement code                        |
| `flow.settlement.id`                         | `flow.Settlement` | Settlement ID                          |
| `flow.settlement.uid`                        | `flow.Settlement` | Settlement UID                         |
| `flow.settlement.voucher_number`             | `flow.Settlement` | Voucher number                         |
| `flow.settlement.voucher_reference`          | `flow.Settlement` | Original voucher (for linked payments) |
| `flow.settlement.issuer_name`                | `flow.Settlement` | Settlement issuer name                 |
| `flow.settlement.issuer_code`                | `flow.Settlement` | Settlement issuer code                 |
| `flow.settlement.external_payment_reference` | `flow.Settlement` | External payment reference             |
| `flow.settlement.psp_payment_reference`      | `flow.Settlement` | PSP reference                          |
| `flow.settlement.till_number`                | `flow.Settlement` | Till number                            |
| `flow.settlement.device_name`                | `flow.Settlement` | Device name                            |
| `flow.settlement.masked_card_number`         | `flow.Settlement` | Masked card number                     |
| `flow.settlement.approval_code`              | `flow.Settlement` | Approval code                          |
| `flow.settlement.parameter.*`                | `flow.Settlement` | Custom settlement parameters           |
| `flow.settlement.recurring_payment_token`    | `flow.Settlement` | Recurring payment token                |
| `flow.settlement.stored_payment_method_id`   | `flow.Settlement` | Stored payment method ID               |

#### Adyen card properties

For Adyen card payments, additional properties are extracted from the transaction log:

| Property key                                             | Description              |
| -------------------------------------------------------- | ------------------------ |
| `flow.settlement.adyen_properties.acquirerReference`     | Acquirer reference       |
| `flow.settlement.adyen_properties.paymentMethod`         | Payment method           |
| `flow.settlement.adyen_properties.paymentMethodVariant`  | Payment method variant   |
| `flow.settlement.adyen_properties.issuerCountry`         | Issuer country           |
| `flow.settlement.adyen_properties.posAuthAmountCurrency` | POS auth amount currency |
| `flow.settlement.adyen_properties.cardHolderName`        | Card holder name         |
| `flow.settlement.adyen_properties.expiryMonth`           | Card expiry month        |
| `flow.settlement.adyen_properties.expiryYear`            | Card expiry year         |
| `flow.settlement.adyen_properties.cardScheme`            | Card scheme              |
| `flow.settlement.adyen_properties.cardType`              | Card type                |

#### Shipments

| Omnium field           | Flow source                               | Notes                                            |
| ---------------------- | ----------------------------------------- | ------------------------------------------------ |
| `shipmentId`           | `orderDelivery.Uid`                       | —                                                |
| `warehouseCode`        | `orderDelivery.ExternalDeliveryReference` | Derived from item warehouse                      |
| `orderStatus`          | Derived                                   | See shipment status mapping                      |
| `status`               | `"Released"` or `"OnHold"`                | Released when delivered                          |
| `completed`            | `orderDelivery.CreatedAt`                 | Only for delivered state                         |
| `expectedDeliveryDate` | `orderDelivery.DeliveryDateTime`          | —                                                |
| `shippingMethodId`     | Extension parameter or provider mapping   | Default from `OMNIUM_DEFAULT_SHIPPING_METHOD_ID` |
| `shippingMethodName`   | `"PickUpInStore"` or provider name        | —                                                |
| `address`              | Delivery address fields                   | —                                                |
| `lineItems`            | Delivery order items                      | Same mapping as order line items                 |

#### Shipment properties

| Property key                           | Key group       | Description                         |
| -------------------------------------- | --------------- | ----------------------------------- |
| `flow.shipment.process_indicator`      | `flow.Shipment` | Delivery provider process indicator |
| `flow.shipment.pickup_point_id`        | `flow.Shipment` | Pickup point ID                     |
| `flow.shipment.pickup_point_type`      | `flow.Shipment` | Pickup point type                   |
| `flow.shipment.delivery_timeslot_from` | `flow.Shipment` | Delivery timeslot start             |
| `flow.shipment.delivery_timeslot_to`   | `flow.Shipment` | Delivery timeslot end               |

### Order field mapping (Omnium → Flow)

#### Order header

| Flow field              | Omnium source                          | Notes                                          |
| ----------------------- | -------------------------------------- | ---------------------------------------------- |
| `uid`                   | `omniumOrder.Id`                       | Used as Flow order UID                         |
| `orderNumber`           | `omniumOrder.Id`                       | Same as UID                                    |
| `externalOrderNumber`   | `omniumOrder.Id`                       | —                                              |
| `orderType`             | `omniumOrder.OrderType`                | Mapped to `ORDER`                              |
| `orderState`            | `omniumOrder.Status`                   | See status mapping                             |
| `settleState`           | `omniumOrder.Status`                   | Derived from Omnium status                     |
| `deliveryState`         | `omniumOrder.Status`                   | Derived from Omnium status                     |
| `store`                 | Properties or `omniumOrder.StoreId`    | Resolved from `flow.store.id`/`flow.store.uid` |
| `customer`              | Properties or `omniumOrder.CustomerId` | Looked up or created in Flow                   |
| `tenantUser`            | `omniumOrder.SalesPersonId`            | Matched by user code, fallback to webhook user |
| `tenantUserDisplayName` | `omniumOrder.SalesPersonName`          | Defaults to `"Omnium"`                         |
| `origin`                | `omniumOrder.OrderOrigin`              | Defaults to `"OMNIUM"`                         |
| `createdAt`             | `omniumOrder.Created`                  | —                                              |
| `lastModifiedAt`        | `omniumOrder.Modified`                 | —                                              |
| `validUntil`            | Properties                             | `flow.order.valid_until` (or custom prefix)    |

#### Line items

| Flow field       | Omnium source                                    | Notes                                  |
| ---------------- | ------------------------------------------------ | -------------------------------------- |
| `uid`            | Properties `flow.order_line.uid` or `lineItemId` | —                                      |
| `product`        | Properties `flow.product.id` or `code` (SKU)     | Looked up by ID first, then by SKU     |
| `warehouse`      | Shipment `warehouseCode`                         | Resolved from shipment-to-line mapping |
| `qtyOrdered`     | `quantity` or `-returnQuantity`                  | Negative for returns                   |
| `qtyDelivered`   | `deliveredQuantity`                              | —                                      |
| `qtyReserved`    | `reservedInventoryQuantity`                      | —                                      |
| `price`          | `placedPrice`                                    | Converted to cents                     |
| `priceCost`      | `cost`                                           | Converted to cents                     |
| `vatRate`        | `taxRate`                                        | Converted to cents                     |
| `vatAmount`      | `taxTotal`                                       | Converted to cents                     |
| `discountAmount` | `discounted / quantity`                          | Per-unit discount                      |
| `serialNumber`   | `serialNumber`                                   | —                                      |

Cancelled items (where `canceledQuantity == quantity`) are skipped during import.

#### Customer resolution

When creating a Flow order from Omnium, the customer is resolved in this order:

1. Look up by `flow.customer.uid` property
2. Look up by `omniumOrder.CustomerId`
3. If not found, fetch from Omnium API based on customer type (B2B or B2C)
4. Create the customer in Flow

#### Address resolution

The order address is resolved from:

1. Customer data (if customer exists)
2. Billing address from the Omnium order
3. First shipment address (fallback)

### Order properties (header level)

| Property key                | Key group           | Description                   |
| --------------------------- | ------------------- | ----------------------------- |
| `flow.order.id`             | `flow.OrderHeading` | Flow order ID                 |
| `flow.order.uid`            | `flow.OrderHeading` | Flow order UID                |
| `flow.store.id`             | `flow.OrderHeading` | Flow store ID                 |
| `flow.store.uid`            | `flow.OrderHeading` | Flow store UID                |
| `flow.customer.id`          | `flow.OrderHeading` | Flow customer ID              |
| `flow.customer.uid`         | `flow.OrderHeading` | Flow customer UID             |
| `flow.customer.loyalty_id`  | `flow.OrderHeading` | Customer loyalty ID           |
| `flow.customer_contact.id`  | `flow.OrderHeading` | Customer contact ID           |
| `flow.customer_contact.uid` | `flow.OrderHeading` | Customer contact UID          |
| `flow.voucher_numbers`      | `flow.OrderHeading` | JSON array of voucher numbers |

### Configuration reference

| Setting                                      | Description                                        | Default             |
| -------------------------------------------- | -------------------------------------------------- | ------------------- |
| `OMNIUM_CLICK_COLLECT_ORDERHANDLING_UID`     | Handling UID for Click & Collect orders            | Required for C\&C   |
| `OMNIUM_ONLINE_ORDER_HANDLING_UID`           | Handling UID for Online orders                     | Required for online |
| `OMNIUM_DEFAULT_SHIPPING_METHOD_ID`          | Default shipping method ID in Omnium               | Required            |
| `OMNIUM_CLICK_COLLECT_EXPIRY_DAYS`           | Working days until Click & Collect pickup deadline | Not set             |
| `OMNIUM_INCLUDE_MAIN_PACKAGE_IN_ORDER_ITEMS` | Include package parent product in order lines      | `false`             |
| `OMNIUM_SEND_ORDER_RECEIPT_TO_OMNIUM`        | Enable invoice/receipt sync to Omnium              | `false`             |
| `OMNIUM_PROPERTY_PREFIX`                     | Prefix for read-write order properties             | `flow`              |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flowretail.com/docs/integrations/order-management/omnium-oms-integration/orders.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
