Skip to main content

introduction

👷 Under construction

This document requires a basic understanding of stock in EVA.

Since EVA is unified to its core, stock levels should always be as up-to-date as possible to accommodate real-time availability indications.


Stock labels

EVA allows you to create new stock labels or update existing stock labels.

Retrieving stock labels

To check what stock labels are currently in your environment, and their corresponding IDs, you can either call GetEnumValues for StockLabel or call GetStockLabels directly. You can then use these IDs in the relevant stock settings.

Creating stock labels

New stock labels can be created using CreateStockLabel.

Updating stock labels

Stock labels can be updated using UpdateStockLabel.

Exposing stock labels

There are a few properties that are exposed in GetApplicationConfiguration which determine the behaviour/availability of stock labels. These properties themselves contain specific stock labels along with the labels (IDs) you add in certain settings.

The following list shows you the properties, their pre-set stock labels and their related setting:

  • StockLabels:Adjustable
    • Demo
    • Damaged
    • The values set in Stock:SellableSourceStockLabels
  • StockLabels:Movable
    • Demo
    • Damaged
    • Clearance
    • The values set in Stock:SellableSourceStockLabels
  • StockLabels:Returnable
    • StockLabels:SellableSources unless Orders:Returns:AlwaysReturnToSellable is set to true which will make Sellable the only available label for returns

The property StockLabels:SellableSources itself contains whichever values are set in Stock:SellableSourceStockLabels.

  • StockLabelsToCount
    • The values set in App:StockLabels:Available will influence which stock labels are available for counting in the App Suite's Full stock count creation screen.

Updating stock in EVA using stock files

Small batch updates

The UpdateStock service can be used to synchronize a full stock set using a single web service.

The service updates the sellable stock of the given products for a specified OrganizationUnitID, or when left blank, your current organization unit. Products that are not mentioned will not be modified.

Size < 4MB

Only batches smaller than 4MB are accepted by the UpdateStock service.

Example request
{
"OrganizationUnitID": 42,
"Identifier": 1,
"Products": [
{
"ID": 3,
"Quantity": 10
},
{
"ID": 4,
"Quantity": 15
}
]
}
caution

With this service, care for concurrency and timing issues.

Large batch updates

To process larger stock files from your system, we support a two step approach:

  1. Create a blob
  2. Insert the blob for processing

1. Creating a Blob

To do so, call the StoreBlob service. This service contains a Data parameter where you can store your data. To do so, create a JSON file for your data.

Then encode this file in Base64 and use it under Data as a string value. As a response to this call, you’ll receive a Guid (the BlobID). You can see the entire process in the example requests below.

[
{
"ProductID": "Optional, int",
"ProductBackendID": "Optional, string",
"QuantityOnHand": "Required, int, value >= 0"
},
{
"ProductID": "yourproductid",
"ProductBackendID": "yourbackendid",
"QuantityOnHand": "15"
},
...
]

2. Inserting your Blob for processing

Secondly, you call the ProcessStockMutationFile service, in which you can provide the OrganizationUnitID, StockLabelID, IsFullStockMutationFile and BlobID.

  • The BlobID(Guid) you got from the previous call is required.
  • When OrganizationUnitID is not given, the OrganizationUnitID of the callers context will be used.
  • When StockLabelID is not given, the 'Sellable' stock label is used.
  • When IsFullStockMutationFile is set to true, the stock of all products that are not provided in the file will be set to 0. If set to false, only the products in the file are processed.

Bear in mind that when calling the ProcessStockMutationFile service, a task will be started within EVA to process the file. The completion time of this process depends on the amount of work that needs to be done.

Example call:

{
"FileBlobID": "bb190999-0bde-44c4-a298-b806964c32fd",
"IsFullStockMutationFile": false
}

Services for adjusting and moving stock

AdjustStock

The AdjustStock service can be used to create a (delta) stock adjustment. Delta stock adjustments don't provide a whole new stock level, they adjust an existing stock level by adding or removing a certain quantity.

This service is mainly used when new stock is 'found' or 'lost' following e.g. a cycle count in the warehouse.

This services uses relative mutations to your existing stock values in the Quantity field (e.g. '12' for adding stock or '-5' for subtracting stock). This service is not used for uploading absolute stock values.

Example call:

{
"BackendSystemID": "123",
"Adjustments": [
{
"BackendID": "123",
"ProductBackendID": "P123",
"OrganizationUnitID": 42,
"StockLabelID": 1,
"StockMutationReasonID": 3,
"Quantity": 12,
"Remark": "Manual stock movement"
}
]
}

MoveStock

MoveStock service can be used to move stock between stock labels. The service does not 'create' or 'remove' any stock (like AdjustStock could) - it merely changes the stock label of existing stock. It is for example used when moving stock items with the sellable label to the damaged label, in case of a damage inspection.

Example request:

{
"BackendSystemID": "123",
"Movements": [
{
"BackendID": "123",
"ProductBackendID": "P123",
"OrganizationUnitID": 42,
"SourceStockLabelID": 1,
"DestinationStockLabelID": 2,
"StockMutationReasonID": 3,
"Quantity": 12,
"Remark": "Manual stock movement"
}
]
}

Settings relevant to moving and adjusting stock

Not all stock can be moved via the MoveStock service by default. It's hardcoded to include the Clearance, Demo and Damaged labels along with all of the labels mentioned in the Stock:SellableSourceStockLabels setting - which itself defaults to Sellable. This means you can expect to be able to move these 4 mentioned labels, unless you configure this differently.

The setting Returns:AlwaysReturnToSellable ties in with this as well, since it looks at the same Stock:SellableSourceStockLabels setting + Damaged for its values. In the same vein: if you want returned stock to not pop up in your stock feeds as sellable, first move it to a stock label which is explicitly not sellable, such as Demo. This is useful in a scenario where you might want to inspect any returned orders, before making them available to sell again.

Uploading stock to e-commerce

Setting up a stock feed for e-commerce

For feeding your e-commerce storefront with stock data, we have a StockFeed task available. By configuring this task in in Suite's Scheduled tasks, you can create a periodic stock_[name].json file that contains all stock data for a particular OUset. You can then tell your e-commerce front end to retrieve this file periodically from our blobstorage, creating a periodic update of your total e-commerce stock.

With the settings in the stock feed you can determine what kind of stock you would like to see. This may be the OU's own stock, the stock of all OU's which can deliver to your OU, or both. In some cases external stock will be relevant while disregarding your own stock, such as when you want a feed of your Ecommerce stock. Other times, when you for example want a feed of the stock in your warehouse, only your own stock will be relevant while external stock is not at all.

Creating the feed

To set up this task:

  • navigate to Scheduled tasks in Admin Suite's Control room.
  • Select EVA.Primer.Stock.Stockfeed2(note: StockFeed1 is an older version, used for stock of a single OU)
  • Set a schedule using a cronjob to define the interval by which the feed should be updated
  • Take a look at all the Settings that appear and set those you need to true

Requesting the feed

The name of the stock feed file is always prefixed by 'stock_' and this name is what we use for this feed. If no name is supplied, it will default to OrganizationUnitSetID for which the stock feed is created. All feeds in EVA are available on GET https://EVA_ENDPOINT/feed/stock_name.json?authorization=AuthorizationKey

Example:

GET https://api.academy.dev.eva-online.cloud/feed/stock_name.json?authorization=0F93A7E96670071023E7396C4A927918AC817EA1B42

  {
"ID": 29973,
"BackendID": "TU410980",
"CustomID": "1100354",
"OrganizationUnit": {
"ID": 626,
"BackendID": "CONSUMER_NL"
},
"Stock": {
"Internal": {
"OnHand": 0,
"Available": 0
},
"External": {
"OnHand": 1000,
"Available": 926
}
}
}
...
]

Headless possibilities

For a real-time overview of the stock levels for particular products (i.e. on your Product Detail Page), we have the GetProductAvailability service which instantly gives you the real-time stock level. This is especially helpful if you don't want to run total stock updates often or have tight stock margins. It is also used to get real-time data of stock in stores, which you can display on your product page for Click & Collect purposes.

This request contains the desired product's ProductID. Which type of ID is specified at ProductID can be determined at the EVA-IDs-Mode header.

This request can contain as many products as you like.

Below you can see an example of the GetProductAvailability request, with it's mandatory properties. The second tab shows you how to request OU specific information only, while the last one shows you a typical response.

{
"Products": [{
"ID" : 14
}],
"Options" : {
"ProductAvailabilityDetails" : { } // Leave empty to request details for ALL OUs and products
}
}

Negative stock values in stock feed

If you want negative stock values to be shown in the stock feed, include the parameter IncludeNegativeAvailability (which defaults to 'false'). If set to 'true' then negative stock is included in the feed. Note that zero stock still isn’t - unless 'ExcludeOutOfStock' is set to 'false'.

Combine this with IncludeNegativeAvailabilityAsZero to turn negative quantities into 0.

Consumer stock notifications

EVA facilitates the notification of consumers that specific products are back in stock again. You can set this up on a per product basis by means of the following CRUD services.

Note that EVA offers two Create services: one for attaching logged-in users and one that allows for attaching an email address.

{
"ProductID": 65,
"OrganizationUnitID": 12,
"CountryID": null, // Optional
"LanguageID": null // Optional
}
  • GetStockNotification
  • GetStockNotificationForCurrentUser
  • DeleteStockNotification

Stock notification task

By default EVA runs the StockNotificationTask once a day to send out the notifications to users. Note that notifications are sent only once, after which the user is unsubscribed.

The expired stock notifications are removed based on the number of days you can specify in StockNotifications:ExpirationTimeInDays.

Scripting

You can customize the number of notifications you want sent out once a product is back in stock again - you don't want to inform a 1000 people for a single product after all. You can also make multiple scripts, which allows for fine-tuning. To make this a little clearer: you can have a script for a broad upper limit - say a 1000 or so, but you can create an additional script for a specific product that's set to 50.

For a sample script, see our Scripting extension points.

Template

The template called StockNotification needs to be setup for the OU that has the stock. This also allows you to customize the message for your consumer.

Supplier relations

Supplier relations can be constructed using CreateOrganizationUnitSupplier.

Example call:

{
"OrganizationUnitID": 13;
"SupplierOrganizationUnitID": 12;
"Type": 0
}

Type defines the relation type, with 0 being internal and 1 being external.

Syncing external stock mutations

When syncing external stock mutations, all stock of the related products is updated in EVA immediately. However, in addition to storing them in the EVA database, the mutations are also copied to a separate CosmosDB database. This allows for better performance when viewing and interacting with these stock mutations in the Admin UI.

The sync with the CosmosDB is based on the following task: EVA.Azure.StockMutations.SyncStockMutationsTask. In this task you can set the synchronization interval, to make it run hourly for example.

As you can see, the dates in the example below can be set as wide as you like.


QuantityOnHand in Stock events

It's possible to get absolute stock levels in the form of the QuantityOnHand property in your StockMutation Created event exports by means of the setting EventExports:AbsoluteStockLevels:Enabled. Set it to true to have the property included.

Mind that EVA processes stock mutations in batches, so if multiple stock mutations of the same product/ou/stocklabel combination are in a single batch, they get the same stock levels.