Sales Orders: Validation Rules
When a sales order is created or modified, validation will be performed on several fields. If any of these validations fail, then the API will return an HTTP-400 response.
All validation from the transactions domain applies, which is covered by the Transactions documentation.
Sales Order
Field |
Validation |
---|---|
sales_order_status |
If an order has a sales_order_status of “complete”, then all PUT requests will be rejected. If all sales order lines have a status of “complete” then the sales order status must also be “complete”. Ignore Sales Order lines where voided = true. If any sales order lines have a status other than “complete” then the sales order cannot have a status of “complete”. Ignore sales order lines where voided = true. The exception to this is the API Sync Service (identified by User Agent = “API Sync Service”) which can change the sales_order_status freely. |
quote_code |
Checks that the specified quote exists. |
owner_site_code |
When a sales order is created or updated, this will be set to the site that the current user is logged in to. |
sales_order_status |
If a sales order has an existing status of “complete” then any attempt to update the order will be rejected. |
Sales Order Line
Field |
Validation |
---|---|
owner_site_code |
When a sales order line is created or updated, this will be set to the site that the current user is logged in to. |
line_type |
If a sales order line has a line_type of “taken” then line_status must be set to “complete”. If line_type = delivery or pickup then the deliveries object must be provided in the request. |
line_status |
The line_status of “other” is reserved for statuses that have not yet been defined within the API. There are restrictions on how the line_status may be changed. The exception to this is the API Sync Service (identified by User Agent = “API Sync Service”) which can change the line_status freely.
|
inventory_source |
The inventory_source of “other” is reserved for sources that have not yet been defined within the API and require downstream actions such as the creation of a purchase order. If a line has an existing inventory source of “other” then the caller must specify “other” as the inventory_source, i.e. it cannot be changed. If a line has an existing inventory_source that is not “other”, then the caller cannot change it to “other”. The exception to this is the API Sync Service (identified by User Agent = “API Sync Service”) which can change the inventory_source freely. |
Sales Order Lock_status (PUT /sales_order/{sales_order_code}/line_dispatch)
When a line is dispatched through the Sales Order API, it will use Invoice API to create an invoice at fulfilment.
The Sales Order API will create a message through RabbitMQ for the Invoice API containing the payload of the dispatched OrderLines by the Sales Order API.
The Invoice API will then consume the message and create the invoice in the correct branch, which will deduct the stock from the fulfilment branch.
Sales Order Lock Status
Field |
Validation |
---|---|
Lock_Status |
The lock status can be created as Restricted or Unlocked; however, an order that has been unlocked can’t be restricted again. POST endpoint can accept statuses Unlocked and Restricted . PUT can accept status Unlock if the status is Restricted . PUT returns errors for the Restricted status if the status is Unlocked. |
POST /sales_order/lock_status
This endpoint sets an order to one of the valid lock_statuses.
HTTP | error_code | Condition |
---|---|---|
409 | SALES ORDER LOCK STATUS ALREADY EXIST | The sales order that you are trying to Restricted/Unlocked already exists in the SalesOrderLockStatus table. |
400 | INVALID_REQUEST | Lock status is not Restricted or Unlocked. |
PUT /sales_order/{sales_order_code}/lock_status
This endpoint updates lock_status for the order.
HTTP | error_code | Condition |
---|---|---|
404 | SALES ORDER LOCK STATUS DOES NOT EXIST | The sales order that you are trying to update doesn’t exist. |
400 | INVALID_REQUEST | Lock status is not Restricted or Unlocked. |
409 | SALES ORDER ALREADY UNLOCKED | The sales order that you are trying to restrict is already unlocked . |
Create a Sales Order with Loyalty Account Code
If account receivable is not passed in the POST request but the Loyalty account code is passed, the Loyalty account code will be used to create the order.
HTTP | error_code | Condition |
---|---|---|
404 | INFINITY CUSTOMER NOT FOUND FOR LOYALTY ACCOUNT CODE xxxx | The Loyalty account code doesn’t have a customer record. |
404 | INFINITY LOYALTY ACCOUNT DOES NOT EXIST | The Loyalty account doesn’t exist. |
Transaction Payments
Field |
Validation |
---|---|
General |
The sum of all the (payment_value – tender_fee – cash_out – change) properties on all payment lines, must be equal to the value of the transaction. If one of the payment method is ‘Account’ then:
|
tender_type |
When tender_type = ‘split’ then:
|
Sales Order Versioning
Once a sales order has been updated, it is distributed to stores and any application that contains sales order functionality. Because the data is distributed, there is the potential for the sales order to be updated in more than one place. The API maintains a sales order version for each sales order, and a line version for each line to ensure that the calling application is working with the most recent version of that sales order.
Sales orders can be created and updated via the POST endpoint. If a new sales order is being created, then the sales_order_version and line_versions must be blank. If an existing sales order is being updated, then the sales_order_version and line_verisons must be provided.
When a sales order is created via POST, the API will assign a sales order version and line versions which will be included in the response as the sales_order_version and line_version properties. When a sales order is updated via PUT, the caller must include the version properties in the request. If the version numbers supplied do not match the current version of the sales order or lines then the call will be rejected with an HTTP-400 error. If the versions match and all other validation passes, the sales order will be updated, and the API will respond with new version numbers.
If an update is rejected, the client may retrieve the new version of the sales order and present the user with the information required to resolve the issue and re-submit their request.
Example:
Action |
Client 1 |
Client 2 |
API |
---|---|---|---|
Salesperson talks to customer and creates a sales order for them |
Creates a new sales order |
|
Sales order is created, responds with sales_order_version of 1 |
|
|
Retrieves the new sales order |
|
Salesperson updates the sales order to add some internal notes |
Updates the sales order, specifying sales_order_version: 1 |
|
Sales order is updated, responds with new sales_order_version of 2 |
Customer calls the store and says that they would like to change the product that is on the sales order |
|
Updates the sales order, specifying sales_order_version: 1 |
Request is rejected as the sales order has changed and the update may be inconsistent |
|
|
Retrieves the sales order updates, including the new sales order version |
|
Salesperson resolves the issue and updates the product on the sales order |
|
Updates the sales order, specifying sales_order_version: 2 |
Sales order is updated, responds with new sales_order_version of 3 |
Idempotency
Sales Order API POST /sales_orders endpoint records timeout as error 504 (or 503) instead of 500.
ExceptionType = “Server.Timeout” instead of “System.Exception”.
This endpoint allows a retry of the same payload and request-id for ExceptionType = “Server.Timeout”.