Domain model
The domain model of the SalesOrders-API consists of the core object types SalesOrderDraft
, SalesOrder
, Production
, Pickup
and Delivery
.
In essence, a SalesOrderDraft
represents an shopping basket in preparation. Once the preparation is done, the draft gets finalized and becomes an active shopping basket. In that state the enfore platform, e.g. the enforePOS application, can process it to become a SalesOrder
which tracks the Production
and fulfillment (Pickup
, Shipment
) of the items.
SalesOrderDraft
A SalesOrderDraft
represents an active shopping basket in preparation. It can be (almost) freely modified. For example, items may be added or removed and different fulfillment options may be added, removed or updated as necessary.
Sales order draft lifecycle
A sales order draft is essentially a helper object for the creation of a sales order. The normal flow is that a sales order draft is created, items and fulfillments are added, removed, and modified, and then it is finalized to become an active shopping basket. In that state it is SalesOrderDraft anymore.
For example, to create a sales order for two products and with some customer information, the following endpoints would be called (payload/response omitted for brevity):
POST /org/{org-id}/sales-order-drafts/
- create a new draftPUT /org/{org-id}/sales-order-drafts/{sales-order-draft-id}/customer
- add customer informationPOST /org/{org-id}/sales-order-drafts/{sales-order-draft-id}/items
- add first itemPOST /org/{org-id}/sales-order-drafts/{sales-order-draft-id}/items
- add second itemPOST /org/{org-id}/sales-order-drafts/{sales-order-draft-id}/patch
withSalesOrderDraftFinalizationRequest
- finalize draft
Once created, a sales order draft exists until it either is explicitly deleted (via DELETE /org/{org-id}/sales-order-drafts/{sales-order-draft-id}
) or until it is finalized.
Operations on a sales order draft
Between the creation of a new sales order draft and its explicit deletion or finalization, clients may perform any number of operations on the draft.
The order of those operations is not limited by the API. For example, one could create a draft, add two items, update the first item, add customer information, add a pickup, remove the second item, update the customer information and only then finalize the draft.
The only limitations are defined by the need to reference items from the fulfillments (pickups and deliveries). While it is possible to add an "empty" fulfillment (one without any items), for an item to be part of a fulfillment, the item has to first exist.
Note that the deletion of an item will remove all references to the item from any fulfillments or other items that currently reference it. This may cause a fulfillment to become "empty". Such fulfillments are removed when the draft is finalized.
SalesOrder
An SalesOrder
represents a closed shopping basket or finalized list of items that are to be sold. It may still be unconfirmed and can be canceled, but its "content" (i.e., the items and additional information such as the customer) cannot be changed anymore.
Sales order lifecycle
The lifecycle of a sales order is relatively simple. The initial state is NEW
and there are the three final states REJECTED
, COMPLETED
, and CANCELED
. In between, a sales order may be put ON_HOLD
at any time:
The meaning of the states is as follows:
State | Meaning |
---|---|
NEW | The order has been newly create and must not be either confirmed or rejected by the merchant. |
CONFIRMED | The order has been confirmed by the merchant which means that he intends to fulfill it. |
REJECTED | The order has been rejected by the merchant which means that he does not accept it and it won't be fulfilled. |
IN_PROCESS | The order is being fulfilled. That is, items are produced and/or pickups/deliveries are active/outstanding. |
COMPLETED | The order has been completed. That is, all items have been produced and fulfilled (picked up or delivery) as necessary. |
CANCELED | The order has been canceled. That is, it once was confirmed any may have been partially fulfilled but for some reason it was decided to not complete it. |
ON_HOLD | The order has temporarily been put "on hold". That is, the order and its depending items (productions, pickups, deliveries) cannot progress further except by returning to the previous state or by being canceled. |
Related objects
A sales order might have related object such as productions and fulfillments. Those related objects are separate resource in the API with their own status but the sales order holds links to the objects it is related to as well as an aggregated status.
The production_information
field holds a SalesOrderProductionInformation
structure that holds links to and an aggregated status for all productions related to the sales order (i.e., productions for items that are sold via the order).
The fulfillment_information
field holds a SalesOrderFulfillmentInformation
structure that holds links to and an aggregated status for all fulfillments related to the sales order (i.e., pickups and deliveries for items that are sold via the order).
The invoice_information
field holds a SalesOrderInvoiceInformation
structure that holds links to and an aggregated status for all invoices related to the sales order (i.e., invoices for the sales order or parts of the sales order).
The aggregated status only provides a rough overview on the status of the related objects:
State | Meaning |
---|---|
NOT_NECESSARY | There are no such related objects. For example, an order that is completely fulfilled "over the counter" would have NOT_NECESSARY as fulfillment_information.aggregated_status |
PENDING | There are related objects and none of them have been completed yet. |
PARTLY_COMPLETED | There are related objects and at least one of them has been completed and at least another one is not completed yet. |
COMPLETED | There are related objects and all of them are completed. |
Note that the meaning of "completed" differs depending on the type of related object. For a Production
it means that the item has been produced. For an Invoice
it means that it has been fully paid.
Also note that related objects are created when the sales order gets CONFIRMED
. That is a NEW
or REJECTED
order won't have related objects (yet).
Edge cases
While SalesOrders-API is focussed on the "retail" vertical and tries to provide a domain-specific view on the business data, the enfore platform provides some advanced features that cannot easily be mapped to this domain-specific view.
For example, for the "gastro" vertical, the platform allows "gastro orders" be be modified, even after they have already been confirmed and partly fulfilled (e.g., somone ordering a second drink). While such "gastro orders" should not be made available via the SalesOrders-API, we currently cannot easily distingush between "retail orders" and "gastro orders". Therefore, in an organization with mixed registers, the SalesOrders-API might expose such "gastro ordes". Those orders can be interacted with via the API just fine, but contrary to regular SalesOrder objects, they may exhibit mutations (e.g., an added item) that normally do not occur.