Upload SCM Data (ASYNC)
Overview
This document covers the process of uploading SCM data to the Scantrust API to be processed asynchronously. To upload data synchronously, see section Upload SCM Data (SYNC)
UAT token permissions
The UAT token needs to have access to the following permissions:
- codes_view
- scm_bulk_edit
- scm_code_edit
- product_view
The UAT token must be set in the header fields of all requests as described in Authentication & Tokens.
Components
- Upload handler: Formats, pre validates and uploads the data.
- Endpoint: on the server, that accepts a batch of records.
- Status check: Check the job status
Prerequisites
There are 3 main prerequisites:
-
Brand owner/SCM User account on the Scantrust portal: Scantrust will provide a developer test-account as well as a production account.
-
A campaign that is setup to include the desired SCM fields:
- Example of SCM fields: production_date, intended_market, rfid, case_number..
- Please note: SCM fields not included in the campaign will be discarded by the system.
- Valid codes: for testing; from a work order for a product that is included in the campaign, which has valid codes.
Constraints
In order to upload information for codes, constraints must be chosen to select the desired codes to upload data for.
There are 3 ways to determine constraints:
-
The constraint could be extended_id (the unique message each code holds).
-
The constraint can also be set to serial_number if they are set on the codes.
-
SCM data can also be used as constraints:
- Codes with RFID tags can be uploaded by key ‘rfid’ and value of each tag.
- Codes with a Logistic Unit can be updated based on the unit.
Multiple constraints can be set for one upload.
Date Format
The date format for SCM fields of type “Date” should be be YYYY-MM-DD
.
Other formats will be accepted and saved as-provided. However, this will result in issues displaying the data in the portal, and using the online data editor.
If you wish to store date data in other formats, please use the text format
Upload Handler
The upload handler will communicate with the API endpoint, handle the data to be uploaded, and processes the response from the server. The workflow is split up in the below steps:
- Pre-validate data to be uploaded
- Format data to be uploaded to the specified JSON structure
- Upload JSON data to the API
- Process the response
- Check the job status
Pre-Validation of uploaded file
It is recommended to pre-validate the data to be uploaded. This prevents unnecessary calls to the API.
Following pre-validation should be done:
-
Format Checking:
- Verify the data constraints to be either 'extended_id' and/or the desired SCM key.
-
Preliminary Error Checking:
- Verify that no constraint value is duplicated.
- Verify that no constraint value is blank.
Format data to be uploaded
Data must be uploaded using JSON as the format. The API will accept a maximum of 5 constraints, with a maximum of 1K values. Data must be split into batches of items that contain the same SCM data. It is recommended to keep a log file containing the keys/batch # of previously uploaded items so they can be skipped when uploading. This prevents items from getting uploaded twice if the API intercepts a defective item in a specific batch.
General flow
- Process the data and create an array of JSON objects
- Create batches based on SCM data to upload
- Ignore previously uploaded rows
- Convert all values to strings
- Send request
- Send a request and save the constraint values as 'uploaded' in a logfile:
- Subsequent runs should ignore all keys that are in the 'uploaded' file
- Check the status based on the returned transaction ID
API Design /api/v2/scm/upload/async/
Posting data to this endpoint will create an ASYNC server job that can edit any code in your company to contain the desired SCM data. The endpoint will return a task_id which can be used to check the status of the job.
Attribute | Required? | Type | Description |
---|---|---|---|
constraints | required | json | Define the constraints which are used to lookup the codes. Constraints must be present in the code as field/SCM field. Match will be CASE SENSITIVE and EXACT.Example uses: - Use the rfid SCM field as a constraint - Use the extended_id as a constraint Maximum 5 different constraints allowed, containing 1K items Disallowed constraints: - message (must be passed as extended_id) - product/product_id (not allowed) - campaign/campaign_id (optional outside constraints) |
scm_data | required | json | List of scm data in key/value pairs, to upload to individual codes. Each key needs to reference the key of the SCM field as defined the campaign. The names of the keys can be confirmed by downloading the template.csv file from the SCM T&T tab for the campaign. Special keys: -product (specify a product SKU/ID) - activation_status (0=inactive, 1=active, 2=blacklisted) - blacklist_reason Disallowed keys: - extended_id/serial_number/message (can not be changed) - product_id (must be passed as product) - status (must be passed as activation_status) |
campaign | optional | int | ID of a campaign. If passed, system checks if all constraints’ scm-keys exist in the campaign. |
reference | optional | string | Human readable name for task grouping. Tasks can be grouped using this field. |
Body Parameters POST (application/json)
{
"constraints": {
"rfid": ["rfid1", "rfid2", "rfid3"],
...
},
"scm_data": {
"client_custom_field": "some_val",
...
},
"campaign": 11,
"reference": "SCM upload 11202020-10"
}
In this example all codes containing the SCM field rfid
with value rfid1
, rfid2
or rfid3
will be updated to have the SCM data "client_custom_field": "some_val"
. The API will check if client_custom_field
is a valid field for campaign ID 11
Response (200): Status OK
If the post is succesfull, the API will return a task_id
which can be used to lookup the job status.
{
"task_id": "your_task_uuid"
}
Response (400) : Invalid Data Format
An exception will be raised (with an appropriate error message) if the posted format/values are not valid:
Example:
{
"campaign": ["Incorrect type. Expected pk value, received str."],
"scm_data": {
"extended_id": "Invalid key name",
"status": "Invalid key name, use 'activation_status' instead"
},
"constraints": {
"message": "Invalid constraint name, please use 'extended_id' instead"
}
}
Special Cases
Special SCM fields can be used to alter the code and internal functions (assign a product, activation status, LU assignment, ...)
See docs: Special SCM Fields
Task Status Checks
When posting an async SCM upload, the task will be processed in the background. You will need to check back later to see the status of the task based on the returned task_id
. Checks might need to happen multiple times if the status of the task is still pending
. Jobs will be processed as soon as possible but might experience delay in busy periods.
API Design /api/v2/scm/tasks/
Task states
A task can have 4 different states:
- pending (The task is in the queue and awaits processing)
- in-progress (The task is currently being processed)
- complete (The task has been completed, values can now be interpreted)
- failed (The task has failed, the errors can be interpreted)
GET: /api/v2/scm/tasks/{id}/
Gets information for a specific task.
Response (200): Status OK
{
"id": "efe7dcd5-aa25-4fc1-b1d3-38640b86e593",
"reference": "",
"state": "complete",
"codes_affected": 322,
"created_by": 1638,
"created_at": "2019-08-22T16:00:11.449543Z",
"started_at": "2019-08-22T16:00:11.514456Z",
"completed_at": "2019-08-22T16:00:11.526948Z",
"details": {
"constraints": {
"rfid": "test_rfid"
},
"scm_data": {
"intended_market": "test"
}
}
}
It is advised to compare the codes_affected
with the number of items that is expected to be updated.
GET: /api/v2/scm/tasks/
List of all created tasks by user
Filters may be added by appending the path ?filter_name=value
e.g. /api/v2/scm/tasks/?state=pending
Filter Fields:
- state: pending, in-progress, complete, failed
- created_at: datetime
- reference: string value
Response (200): Status OK
Example response (paginated result):
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": "6913d938-d6c3-4139-97d1-27c59c113ef0",
"state": "complete",
"reference": "",
"codes_affected": 777,
"created_by": 1638,
"created_at": "2019-08-22T16:00:12.996409Z",
"started_at": "2019-08-22T16:00:13.057840Z",
"completed_at": "2019-08-22T16:00:13.070875Z"
},
{
"id": "ef183d35-cc7c-4925-a95a-906c02e291ef",
"state": "complete",
"reference": "",
"codes_affected": 228,
"created_by": 1638,
"created_at": "2019-08-22T16:00:12.218396Z",
"started_at": "2019-08-22T16:00:12.277734Z",
"completed_at": "2019-08-22T16:00:12.289489Z"
}
]
}
POST: /api/v2/scm/tasks/
Attribute | Required? | Type | Description |
---|---|---|---|
task_ids | required | list(string) | List of task_ids to retrieve from the API. Example: ['taskID1', 'taskID2'] |
(For Example Response See List view)
GET: /api/v2/scm/task-groups/{reference}/
Get a group of tasks based on reference ref1
Response (200): Status OK
{
"reference": "ref1",
"tasks_count": 3,
"codes_affected": 6,
"completed": true,
"state_stats": {
"pending": 0,
"in-progress": 0,
"complete": 3,
"failed": 0
},
"started_at": "2019-08-22T16:00:12.277734Z",
"completed_at": "2019-08-22T16:00:12.289489Z"
}