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.

  • If a line has an existing status of “other” then the caller must specify “other” as the line_status, i.e. it cannot be changed.
  • If a line has an existing line status that is not “other”, then the caller cannot change it to “other”.
  • If line_type = pickup, then line_status cannot be changed to awaiting_delivery.
  • If line_type = delivery, then line_status cannot be changed to awaiting_pickup.
  • If line_status = “complete” then it cannot be changed.
  • If a line is voided, then you cannot change the line_status.
  • line_status may only be set to “complete” if line_type is set to “Taken”.

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:

  • Reject the request if accounts_receivable_code is NOT set.

 

tender_type

When tender_type = ‘split’ then:

  • There must be an 'accounts_receivable_code' in the request.
  • There must be a 'transaction_payment_split' in the request.
  • The first accounts_receivable_code in 'transaction_payment_split' must be the same as the main accounts_receivable_code in the request.
  • The total of the split_percentage must be 100.00.
  • Only one payment line/type is allowed, and it must be paid in full.
  • “finance_term” is not mandatory.

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”.