Defining a Transformation Preprocessor
Each transformation rule of a template can have a preprocessor. Given an input context object, the preprocessor identifies the records that are suitable for transformation, such as the warehouses that have stock for the given product or the suppliers that can provide this product.
Later phases of the template will eliminate unfeasible scenarios and will analyze the impact of each scenario. The preprocessor needs only to identify possibilities.
How a Transformation Preprocessor Is Used
For each call to the scenario analysis API, the system does the following:
-
Iterates over the transformation rules in the template, and for each one:
-
Uses the preprocessor for that transformation rule, passing in one or more parameter values, which come from the input context object.
-
From the preprocessor, obtains a list of IDs, which correspond to the records to be transformed.
Note that the system automatically iterates over the transformation rules. Your code only needs to return the IDs to use.
If there is no preprocessor, the system applies each transformation rule once.
-
When performing the transformations, the scenario analysis module will iterate over these IDs, creating a snapshot for each one and then transforming it using the actual transformation logic.
Template Syntax
The following template fragment shows a transformation rule so you can see where to include the preprocessor:
"transformation": {
"name": "Replenishment Strategies",
"rules": [
{
"description": "Move Inventory from Another Warehouse",
"name": "Move Inventory",
...
"preprocessor": {
"expression": "WarehousePreprocessor.sql",
"type": "SQL",
"parameters": [
"productId"
],
"transformationParameterIdx": 3,
"transformationParameter": "warehouseId"
},
"callAction": "CallActionForMoveInventoryBPL"
},...
Formally:
-
The transformation object is a top-level property of the template, and the rules property specifies an array of objects, each of which describes one transformation rule.
-
Each transformation rule includes the preprocessor property, which defines the preprocessor.
-
The preprocessor element has the following structure:
-
expression—Specifies the code to call when running this preprocessor. The syntax used depends on the type property:
-
For "Python", use syntax of the form "PythonFilename.py.FunctionName" or "PythonFilename.py.ClassName.MethodName"
-
For "ObjectScript", use syntax of the form "##class(Package.Class).MethodName()"
-
For "SQL", use syntax of the form "SQLFilename.sql"
-
-
type—Specifies how this preprocessor is implemented. Use one of the following values for this property: "Python", "ObjectScript", "SQL"
-
parameters—Specifies an array of parameters to pass to preprocessor code, in the same order expected by that code. The context object provides the values for these parameters.
-
transformationParameterIdx and transformationParameter specify how to use the output of the preprocessor, when invoking the actual transformation. Specifically, the scenario analysis module inserts a new argument into the parameter list of the actual transformation. transformationParameterIdx indicates the position of the argument (1 means the first argument) and transformationParameter is the name for this parameter.
-
Implementing in Python
To implement a transformation preprocessor in Python, create a Python function as follows:
-
The function must accept arguments as follows:
-
All the values specified in parameters array of the template, in that order.
-
An additional argument, samRunContext, which is always passed as the last argument.
-
-
The method must return a list of IDs from the table that the actual transformation logic will apply to. For example, if the transformation will update the supplier table, the preprocessor code must return IDs from the supplier table.
Implementing in ObjectScript
To implement a transformation preprocessor in ObjectScript, create a class method as follows:
-
The method must be defined as a class method, not an instance method.
-
The method must accept arguments as follows:
-
All the values specified in parameters array of the template, in that order.
-
An additional argument, samRunContext, which is always passed as the last argument.
-
-
The method must return an instance of %ListOfDataTypesOpens in a new tab that contains a set of IDs from the table that the actual transformation logic will apply to. For example, if the transformation will update the supplier table, the preprocessor code must return IDs from the supplier table.
For example:
ClassMethod GetListOfSuppliers(productId As %String, samRunContext As %DynamicObject) As %ListOfDataTypes
{
set query = "SELECT supplierId from SC_Data.ProductSupplier where productId = ? AND supplierType = 'Supplier'"
set result = ##class(%SQL.Statement).%ExecDirect(, query, productId)
if result.%SQLCODE < 0 {
return $$$ERROR($$$SQLCode, result.SQLCODE, result.%Message)
}
set supplierList = ##class(%ListOfDataTypes).%New()
while result.%Next() {
do supplierList.Insert(result.%Get("supplierId"))
}
return supplierList
}
Implementing in SQL
To implement a transformation preprocessor in SQL, create a .sql file containing one SQL SELECT statement as follows:
-
The statement must accept all the parameters provided by the parameters array of the template, in that order.
-
The statement must select a single field. This field should be an ID from the table that the actual transformation logic will apply to.
Also see SQL Limitations.
For example:
SELECT siteLocationId FROM SC_Data.ProductInventory WHERE productId = ? AND quantity > 0;
Checklist
-
Create the Python function, method, or SQL.
-
Within this code, log any errors as well as any intermediate steps that are useful for debugging.
-
Make sure that this code is located appropriately so that it can be found when you use the template.
-
Update the template as shown above.
-
Implement the rest of the transformation rule.