Skip to main content
PRERELEASE CONTENT

Defining the Transformation Itself

Each transformation rule of a template must define an actual transformation of data. These transformation are applied to the preliminary set of records identified by the transformation preprocessor.

After transformation, the system can validate the possibilities and discard impossible or unfeasible possibilities (the next phase in the template).

How a Transformation Is Used

For each call to the scenario analysis API, the system does the following:

  1. Iterates over the transformation rules, and for each one:

    1. Uses the applicable preprocessor to obtain a list of IDs, which correspond to the records to be transformed by this rule.

    2. Iterates over that set of records and applies the transformation rule each time.

    Notice that the system performs the iteration. Your transformation rule simply describes how to simulate an individual possibility.

    If there is no preprocessor, the system applies the transformation rule once. In this case, the transformation rule must be very specific.

Template Syntax

The following template fragment shows a transformation rule so you can see where to include the actual transformation:

    "transformation": {
        "name": "Replenishment Strategies",
        "rules": [
            {
                "description": "Move Inventory from Another Warehouse",
                "name": "Move Inventory",
                "type": "ObjectScript",
                "expression": "##class(Transformations.MoveInventory).MoveInventoryFromAtoB()",
                "parameters": [
                    "quantity",
                    "productId",
                    "destinationLocationId"
                ],
                "preprocessor": {
                  ...
                },
                "callAction": "CallActionForMoveInventoryBPL"
            },...

Formally:

  • The transformation object is a top-level property of the template, and its rules property contains the transformation rules.

  • Each transformation rule has the following properties:

    • description—Describes the rule.

    • name—Provides a name for the rule.

    • type—Specifies how this rule is implemented. Use one of the following values for this property: "Python", "ObjectScript", "SQL"

    • expression—Specifies the code to execute when using this rule. 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"

      This code performs the actual transformation.

    • parameters—Specifies an array of parameters to pass to the given code, in the same order expected by that code. The context object provides the values for these parameters.

      The code can accept additional parameters, inserted into the argument list by the transformation preprocessor,

    • preprocessor—Specifies the optional transformation preprocessor.

    • callAction—Specifies the call action.

Implementing in Python

To implement the actual transformation logic in Python, create a Python function as follows:

  • The function must accept arguments as follows:

    1. All the values specified in parameters array of the template, in that order.

    2. Any additional argument inserted into the argument list by the transformation preprocessor.

    3. Two additional arguments at the end (samRunContext and snapshot).

  • The function must update values of fields in the snapshot. To do so, it must use the interface provided by the snapshot object; see Using the Snapshot to Run Queries.

  • The function does not need to return a value.

Implementing in ObjectScript

To implement the actual transformation logic 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:

    1. All the values specified in parameters array of the template, in that order.

    2. Any additional argument inserted into the argument list by the transformation preprocessor.

    3. Two additional arguments at the end (samRunContext and snapshot).

  • The method must update values of fields in the snapshot. To do so, it must use the interface provided by the snapshot object; see Using the Snapshot to Run Queries.

  • The method must return a %StatusOpens in a new tab value.

For example (with artificial line breaks for readability):

ClassMethod MoveInventoryFromAtoB(quantity As %String, 
                                  productId As %String, 
                                  originWarehouseId As %String, 
                                  destinationWarehouseId As %String, 
                                  samRunContext As %DynamicObject, 
                                  snapshot As SC.Core.Analytics.SAM.Data.Internal.Snapshot) As %Status
{
    do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogInfo(samRunContext, 
                       snapshot.uid, 
                       "Moving inventory from "_originWarehouseId_" to "_destinationWarehouseId)
    // update quantity at origin location
    set params = ##class(%DynamicArray).%New()
    set query = "UPDATE SC_Data.ProductInventory set quantity = quantity - ? where siteLocationId = ? and productId = ?"
    set purchaseOrderUid = $System.Util.CreateGUID()
    do params.%Push(quantity)
    do params.%Push(originWarehouseId)
    do params.%Push(productId)
    set result = snapshot.Query(query, params)
    if result.%SQLCODE < 0 {
        do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogError(samRunContext, 
                     snapshot.uid, 
                     "Error while running Move inventory transformation: "_result.%Message)
        return $$$ERROR($$$SQLCode, result.SQLCODE, result.%Message)
    }

    do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogInfo(samRunContext, 
                       snapshot.uid, 
                       "Inventory updated at Origin Location - "_originWarehouseId)

    // update quantity at destination location
    set params = ##class(%DynamicArray).%New()
    set query = "UPDATE SC_Data.ProductInventory set quantity = quantity + ? where siteLocationId = ? and productId = ?"
    set purchaseOrderUid = $System.Util.CreateGUID()
    do params.%Push(quantity)
    do params.%Push(destinationWarehouseId)
    do params.%Push(productId)
    set result = snapshot.Query(query, params)
    if result.%SQLCODE < 0 {
        do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogError(samRunContext, 
                     snapshot.uid, 
                     "Error while running Move inventory transformation: "_result.%Message)
        return $$$ERROR($$$SQLCode, result.SQLCODE, result.%Message)
    }

    do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogInfo(samRunContext, 
           snapshot.uid, 
           "Inventory updated at Destination Location - "_destinationWarehouseId)

    // add warehouseId in the contexts
    do snapshot.AddContext("","","supplierId", originWarehouseId)

    return $$$OK
}

Here is another example (with artificial line breaks for readability):

ClassMethod PurchaseProductFromSupplier(supplierId As %String, 
                                        destinationLocationId As %String, 
                                        productId As %String, 
                                        quantity As %Integer, 
                                        samRunContext As %DynamicObject, 
                                        snapshot As SC.Core.Analytics.SAM.Data.Internal.Snapshot) 
                                        As %Status
{
    do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogInfo(samRunContext, 
                      snapshot.uid, "Placing purchase order from supplier "_supplierId)
    // create purchase order from the supplier
    set params = ##class(%DynamicArray).%New()
    set query = "INSERT INTO SC_Data.PurchaseOrder(uid, supplierId, shipToLocationId) VALUES ( ?, ?, ?)"
    set purchaseOrderUid = $System.Util.CreateGUID()
    do params.%Push(purchaseOrderUid)
    do params.%Push(supplierId)
    do params.%Push(destinationLocationId)
    set result = snapshot.Query(query, params)
    if result.%SQLCODE < 0 {
        do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogError(samRunContext, 
             snapshot.uid, "Error while running Purchase from supplier transformation: "_result.%Message)
        return $$$ERROR($$$SQLCode, result.SQLCODE, result.%Message)
    }

    do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogInfo(samRunContext, 
            snapshot.uid, "Purchase order created - "_purchaseOrderUid)
    
    // create purchase order line items for the purchase order
    set params = ##class(%DynamicArray).%New()
    set query = "INSERT INTO SC_Data.PurchaseOrderLine(uid, purchaseOrderId, productId, shipToLocationId, lineNumber, quantity) VALUES (?, ?, ?, ?, ?, ?)"
    do params.%Push($System.Util.CreateGUID())
    do params.%Push(purchaseOrderUid)
    do params.%Push(productId)
    do params.%Push(destinationLocationId)
    do params.%Push(1)
    do params.%Push(quantity)
    set result = snapshot.Query(query, params)
    if result.%SQLCODE < 0 {
        do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogError(samRunContext, 
               snapshot.uid, "Error while running Purchase from supplier transformation: "_result.%Message)
        return $$$ERROR($$$SQLCode, result.SQLCODE, result.%Message)
    }

    do ##class(SC.Core.Analytics.SAM.Util.SAMLogger).LogInfo(samRunContext, 
              snapshot.uid, "Purchase order line items added")

    return $$$OK
}

Implementing in SQL

To implement the actual transformation logic in SQL, create a .sql file that updates the data as needed.

Also see SQL Limitations.

Checklist

FeedbackOpens in a new tab