Stock Levels
Overview
Stock levels in PowerEPOS are managed onsite and are designed to operate with concurrent consumption from multiple onsite terminals and/or through external third party providers. The onsite systems are the point of truth for the moment by moment stock levels.
The remote ordering stock level API has been designed to offer a "best effort" representation of the onsite stock. It cannot make any firm guarantees about stock availability until it comes time to actually consume the stock through submitting an order. What is offered is a snapshot of the general StockLevel associated with an individual product.
Stock levels are tied to a specific productId independent of productModifierId. That is, productModifierId will NOT change the actual stock being consumed by an order (it may however affect the quantity of stock but that's handled by PowerEPOS). The stock level information can be used to alter the display of MenuItem and/or to warn the user before submitting a RemoteOrderProduct specifying productId
We now offer two methods of stock level notifications.
- Stock Status Changes (ROS) - this is the original stock status notification system that is integrated into ROS and is always enabled.
- Realtime Stock Levels (POS) - this is a new optional system that can be enabled to send near realtime stock counts for products directly from the POS system.
Stock Status Changes (ROS)
This is the original stock status notification system that was integrated into ROS. In this system the ROS will only send notifications when the "status" of a product changes, ie when the status changes between the states of SufficientStock, LowStock or OutOfStock. In this system ROS will post the notifications to the provider via the webhook when necessary. Webhook traffic is kept to a minimum in this system.
How it works
Whenever productId changes its status StockLevel a Webhook Notification will be sent with the WebhookNotificationType set to ProductStockLevel and the body will be a ProductStockLevelWebhookBody
These will be sent whether stocklevels are being increased or decreased. Under normal circumstances they should arrive within seconds of the site actually changing the stock levels.
Checking the current stock status
The provider can also request the current stock status from ROS if required (eg after a server restart). The webhook notifications should be relied upon after that point.
GET /remoteorders/stocklevels/{providerId}/{outletId}
Required Headers
Authorization: Bearer <token>
See AccessToken for creating a bearer token.
Returns
HTTP 200on successHTTP 401on invalid/missing Authorization token (do not resubmit without updating Authorization)HTTP 403on a correct authorization token but for the wrong outlet (or the outlet has disabled the integration). Do not resubmit.HTTP 503on service is starting up or is not yet ready to process your request, please wait 30 seconds and retry.HTTP 5XXon an error internal to ROS. This would typically only occur due to an internal transient connection issue, please retry for a limited number of attempts after a short delay.
On success the response body will contain a single JSON encoded FetchProductStockLevelResponse containing all productId's that are NOT StockLevel Sufficient
Remarks
In order to reduce the size of the response ONLY productId values that are NOT StockLevel SufficientStock will be returned. It can be safely assumed that any productId not found in this response can be considered having stockLevel SufficientStock
This endpoint is designed to be quick to respond and can be polled (within reason) but the preference is to depend on the webhook notification and to use this endpoint in the event of a prolonged outage or when onboarding a new outlet.
Realtime Stock Levels (POS)
This is a new optional system that can be enabled on the POS to send near realtime stock counts for products directly to the provider from the POS system on site. There is a setting that must be enabled when the integration is setup to turn this feature on.
Note This feature can create a lot of additional webhook traffic.
Note The webhook notifications in this system will be sent directly from a POS machine at the outlet, rather than through the ROS server that normally delivers webhook notifications. It should also be noted that outlet's often do not have static IP's, so if the provider's webhook server requires the whitelisting of IP's for incoming connections, the outlet will need to purchase a static IP from their ISP before they will be able to use this feature.
Note This feature runs along side the default existing "Stock Status Changes" system. This means when using this system, you can still expect to see stock status notifications from ROS as well as the realtime stock levels from POS. It is recommended that the stock status change notifications from ROS are ignored when using this system.
Note The POS may be tracking stock levels for products that the provider does not know about (ie that arent in any of the remote ordering menus). The provider may receive notifications for these products as well, so they will need to ignore them if they are not a product they need to track.
How it works
Whenever productId changes its stock level or state, a Webhook Notification will be sent with the WebhookNotificationType set to LiveProductStockLevel and the body will be a LiveProductStockLevelsWebhookBody
These will be sent whenever there is any change to the stock tracking status of a product on the POS. (eg Stocklevel increased or decreased, WarningLevel changed, Stock Countdown disabled or deleted). Under normal circumstances they should arrive within seconds of the site actually changing the stock levels.
The LiveProductStockLevelsWebhookBody model contains a "StockLevels" field which is list of LiveProductStockLevel. This will contain one or more updates to the stock levels for one or more products. The LiveProductStockLevelsWebhookBody also contains a field called "IsFullRefresh" which is used to indicate if the StockLevels list contains a complete list of all current stock tracked products.
When "IsFullRefresh" is TRUE, the provider should discard any existing stock tracking states they have for all products and replace them with the results from the "StockLevels" list. When "IsFullRefresh" is FALSE, the provider should update the tracking for only the products contained within the "StockLevels" list, as this should be considered a subset of the total tracked products.
The LiveProductStockLevel contains the following fields, some which require special consideration
- StockLevel - This is the current count of stock for that particular product. Note that this field name is the same as is used in the ROS stock status notification system, however in that notification system the StockLevel field represents a status, rather than a count.
- WarningLevel - This is the "warning" count as defined on the POS. Basically this is used on the POS to determine when to start indicating to the user that the stock level is low.
- Status - This is the StockLevel status value for this product, as it would be from the ROS stock status notification system.
- IsDisabled - This indicates if stock countdown has been temporarily disabled for this product on the POS. When IsDisabled is TRUE, the stock levels should be ignored and the product should always be considered available.
- IsDeleted - This indicates that the product is being completely removed from stock countdown tracking. When IsDeleted is TRUE, the providers tracking of stock levels for this product should be deleted and the product should always be considered available. No further updates to this product will be received in the stock notifications unless the product has stock countdown reactivated on the POS.
Remarks
IMPORTANT It is important that the provider respond to LiveProductStockLevel webhook notifications in a timely manner. Ideally the provider should acknowledge the notification immediately and perform any processing as a separate background task. Delays in responding to these notifications can have an impact in the remote order processing speed of the POS.
When the provider responds to the webhook LiveProductStockLevel notifications from the POS, the following codes are expected
Expected Response Codes
HTTP 200SuccessHTTP 4xxWill be treated as an unrecoverable failure, the POS will discard the notification and will not try again.HTTP 5xxWill be treated as a transient error and the POS will retry the notification up to 3 times before discarding it.
The X-ROS-Id: <Unique ID for the ROS server making the outgoing request> header in the notifications sent from the POS ssyetm will insetad be populated with a contactinated ID of ||PSVR
Example LiveProductStockLevel Notifications
An example of a full refresh of stock levels from the POS.
{
"Type": 6,
"Body": {
"OrganisationCode": "TestOrgCode",
"Kapow": "50f32d44-a361-4509-bdef-16347dd7a93c",
"OutletID": "1fc58ba7-ebb4-4570-9e7e-ddaa89573871",
"IsFullRefresh": true,
"StockLevels": [{
"ProductID": "bd047b4d-e14d-49d0-bbf9-1ec13b65e925",
"Status": 1,
"StockLevel": 0,
"WarningLevel": 0,
"IsDisabled": false,
"IsDeleted": false
}, {
"ProductID": "bad90218-2ba9-4850-9d49-c59a5d60418a",
"Status": 3,
"StockLevel": 0,
"WarningLevel": 0,
"IsDisabled": true,
"IsDeleted": false
}, {
"ProductID": "5d1415b2-c685-4e9b-8d47-b1b2e292f0ba",
"Status": 2,
"StockLevel": 1,
"WarningLevel": 1,
"IsDisabled": false,
"IsDeleted": false
}
]
}
}
An example of an update of stock levels from the POS.
{
"Type": 6,
"Body": {
"OrganisationCode": "TestOrgCode",
"Kapow": "50f32d44-a361-4509-bdef-16347dd7a93c",
"OutletID": "1fc58ba7-ebb4-4570-9e7e-ddaa89573871",
"IsFullRefresh": false,
"StockLevels": [{
"ProductID": "5d1415b2-c685-4e9b-8d47-b1b2e292f0ba",
"Status": 3,
"StockLevel": 10,
"WarningLevel": 3,
"IsDisabled": false,
"IsDeleted": false
}
]
}
}