2. Creating a case

Create a case using the product’s information.

For each step, get the global variable definitions

In the previous step, we retrieved a product iteration, including the step definitions. Now we’re going to use these definitions to figure out the additional parameters the cases need to be created successfully.

  • Products can have parameters, they are called global variables
  • These global variables are used to generate custom forms in the Portal, one per product. These forms are usually manually filled when creating a case from the Portal, but here we’re going to automate it.

Where to find them

Let’s see where we can find the global variable definitions. Here’s an extract of a product iteration. There are two possible versions for backward compatibility reasons.

1
2
3
4
5
6
7
8
9
{
  ...,
  "steps": [
    {
        "globalVariables": {
          "gvars": [ ... ] <= Here
        }
    }
}
1
2
3
4
5
6
7
{
  ...,
  "steps": [
    {
        "globalVariables": [ ... ] <= Here
    }
}

You must support both style of global variables, a product iteration can contain steps which uses old and new style, depending on when the step’s component was created.

Here is some python pseudo-code to illustrate how to access all global variable definitions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def get_step_global_variable_definitions(step):
    """Extract the global variables's definitions from a step

    Args:
        step (dict): A product iteration's step

    Returns:
        list(dict): a list of global variable definitions
    """
    # Get the steps' componentIteration
    componentIteration = step["componentIteration"]
    # Get the componentIteration's metadata
    metadata = componentIteration["globalVariables"]

    # From the metadata, get the global variable definitions
    #
    # For backward-compatibility, we check if the metadata is just the list of
    # global variables (as opposed to a dict).
    if type(metadata) == list:
        gvars = metadata
    else:
        gvars = metadata["gvars"]
    return gvars


product_iteration = get_product_iteration(...)

for step in product_iteration['steps']:
    gvars = get_step_global_variable_definitions(step)
    for global_variable_definition in gvars:
        ...

What do they contain?

Now that we know where to find the list of global variable defintions, we can look at one example of a global variable defintion.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "arraySize": 1,
  "confidential": false,
  "interaction": "Automatic",  <=== 1
  "label": "Scan",             <=== 2
  "mode": "Input",
  "proxyProperties": [
    {
      "propertyName": "FileName",
      "proxyName": "Input"
    }
  ],
  "required": true,
  "title": "Scan",
  "type": "string" <=== 3
}

The three most important parts are the

  1. Its interaction: Whether is a Manual or Automatic variable.
  2. Its label: it is what the system uses to identify the variable. The other attribute title is a more user-friendly name that is shown when building a form to fill the variable’s values in the Portal.
  3. Its type.

You only need to provide the values for the Manual variables, the Automatic variables are automatically filled by the system.

Taking the snippet “to access all global variable definitions”:

1
2
3
4
5
6
7
for step in product_iteration['steps']:
    gvars = get_step_global_variable_definitions(step)
    for global_variable_definition in gvars:
        # Ignore the "non-manual"  global variables
        if gvar_def['interaction'] != 'Manual':
              * [ ] continue
        ...

Building the request to create a case

To create the case, you need to make an HTTP POST request with multipart form data to the path /v1/orders-tracking (remember: cases in the Portal are called order-tracking in the API).

There are two required parameters:

  • the product iteration, named products, because of backward compatibilty
  • the list of options for each step, each named options[]

And one optional parameter:

  • the reference id, named referenceId, which is used by our client to link the cases to their management systems

Here is one example of an options[], it is a JSON-encoded string that specifies the options (global variables) for which step (stepOrder) and then provides a value for each options. In this example, we set the boolean global variable named “Left” for step 1, to true.

1
2
3
4
5
6
7
8
{
  "options": [
    {
      "Left": true
    }
  ],
  "stepOrder": 1
}

Finally, the requests must also contain the input scan file.

Here is some python pseudo-code to build the right request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
data = {
    'products': product_iteration['id'],
    'referenceId': referenceId,
    # The library "requests", recognize form-data names endings with "[]".
    # The library will take each element of the list and add one form-data
    # key/value pair with the name "options[]".
    # Said otherwise, we're sending multiple "options[]", each of them
    # containing a string (which contains serialized JSON).
    'options[]': [json.dumps(o) for o in options]
}
# filename might be "C:\\sphere.stl" for example
with open(filename, 'rb') as input:
    files = {
        # here we pass a tuple (name, content)
        'files': (os.path.basename(filename), input),
    }
    response = requests.post(
        url,
        data,
        files=files,
        headers=make_authorization_header(token))
    response.raise_for_status()
    cases = response.json()

To see how options was built and how this snippet fits with the rest of the workflow, see the function create_case in the full example script

Start the case

Once you have created the case you need to start the processing. To do so, you need to make a HTTP PATCH request to /v1/orders-tracking/{case_id} to change the first step’s status to Start Process.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def start_case(token, case_id):
    """Start an existing case

    Args:
        token (str): The authorisation token.
        case_id (str): The caseId of the case to start.
    """
    response = requests.patch(f'{API_BASE_URL}/v1/orders-tracking/{case_id}',
                              data={"stepOrder": 0, "status": "Start Process"},
                              headers=make_authorization_header(token))
    response.raise_for_status()
    log.info('Case started')