| # Setup at implementation time Introduction The implementation described here is based on the following assumptions: In the Exchange scheme, the ASCII file name will be equivalent to the table code, and the ASCII field names will be equivalent to the column code. A create XML file type of action is defined. This action has a transformation script defined. In that transformation script, the following is programmed: The event type is changed: The standard events are replaced by a specific event. The class is changed: The table code is replaced with a logical name. The attributes that are not required in the output, but that only had to check the condition, are removed. The attributes that are required in the output are renamed. Note that these assumptions are not mandatory. For example, the user can use other, more descriptive ASCII file and field names, which reduces the transformations in the trigger. However, in that case, the limitations of the Exchange module must be taken into account. More specifically, the ASCII file and field names cannot be greater than eight characters in length and the ASCII file names will always be in lowercase. In addition, for the transformation script, you can follow one of the following two approaches: Adhere to the standard event structure. In this case, the incoming event is updated as described previously. Use a proprietary structure: In this case, the attribute values are picked up from the incoming event, and a new XML is created. In this case, any XML can be created and can be completely tuned to the needs of the workflow engine that receives the XML files. Audit setup Audit is switched on for the tables involved: whwmd215 and tdsls400. For details about Audit Management, refer to the Web Help and to the Infor10 ERP Enterprise Server (LN) Technical Manual (U8172 US). Important! By default, unchanged columns are not audited in case of an update action. As a result, for example, if the stoc (inventory on hand) is changed in whwmd215, the values for the primary key fields ( cwar and item) and the changed field ( stoc) are included, but the unchanged fields are not included. Note that this can impact filtering by conditions, because you cannot check an attribute that is unavailable. To avoid this limitation, use the Audit Fields by Table (ttaud3125m000) session to specify that unchanged fields must be audited (set the audit type to "Always"). For details, refer to "Unchanged table fields" in chapter 2, "To set up triggering". Exchange scheme setup A single exchange scheme is created to pick up the relevant changes. As a result, the job for each of these situations runs at the same frequency, which results in less overhead. If the frequency for checking the changes must differ for the tables, you can create multiple batches or exchange schemes. The batch includes the two batch lines, covering the following table fields:
Table | tdsls400 | whwmd215
Fields | orno ofbp sotp corg | item stoc allo
Exchange scheme properties
Exchange Scheme | workflow
Description | Workflow Scheme for Triggering
Path for Exchange Objects | /home/exchange/workflow
Path for Condition Errors | /home/exchange/workflow
Path for Seq. Files | /home/exchange/workflow
Path for Definition Files | /home/exchange/workflow
Based on Audit | Yes
Based on Indicators | Yes
Default Date Format | YYYYDDMM
Control character y/n | No
Separator | |
Enclosing Character |
Parent Exchange Scheme |
Control character, separator, and enclosing character are irrelevant because no file is created. Batch properties
Exchange Scheme | workflow (Workflow Scheme for Triggering)
Batch | BATCH
Sequence No. | 10
Description | Workflow Export Batch
Company | 996
Exchange Using Audit | Yes
ASCII file formats Exchange Scheme: workflow (Workflow Scheme for Triggering) ASCII file: Item Inventory by Warehouse (whwmd215)
Field No. | 10 | 20 | 240 | 260
Field Name | Cwar | Item | Stoc | Allo
Description | Warehouse | Item | Inventory on Hand | Allocated Inventory
Field Type | Alphanumeric | Alphanumeric | Numeric | Numeric
Start Pos | 1 | 4 | 246 | 286
Length | 3 | 16 | 20 | 20
Date Format |  |  |  |
Floating Dec. | No | No | No | No
Dec.Pos. | 0 | 0 | 0 | 0
Exchange Scheme: workflow (Workflow Scheme for Triggering) ASCII file Sales Orders 9 (tdsls400)
Field No. | 10 | 20 | 50 | 70
Field Name | orno | ofbp | corg | sotp
Description | Sales Order | Customer | Origin | Order Type
Field Type | Numeric | Alphanumeric | Numeric | Alphanumeric
Start Pos | 1 | 7 | 22 | 28
Length | 6 | 6 | 3 | 3
Date Format |  |  |  |
Floating Dec. | No | No | No | No
Dec.Pos. | 0 | 0 | 0 | 0
Field Type, Start Position, Length, and so on are irrelevant, because no ASCII file is created. Table and field relations (export) Exchange Scheme: workflow (Workflow Scheme for Triggering) Batch: BATCH (Workflow Export Batch)
Batch Line | 10 | 20
ASCII File | whwmd215 | tdsls400
Desc. | Item Inventory by Warehouse | Sales Orders
Table | whwmd215 | tdsls400
ASCII File Name | whwmd215.S | tdsls400.S
Active | Yes | Yes
bdbpre | No | No
Range | No | No
Index | 1 | 1
Cond. |  |
Exchange Scheme: workflow (Workflow Scheme for Triggering) Batch: BATCH (Workflow Export Batch) Batch Line: 10 (whwmd215)
Serial No. | 10 | 20 | 240 | 260
Field Name | cwar | item | stoc | allo
Table Field | cwar | item | stoc | allo
Array Element | 0 | 0 | 0 | 0
Condition |  |  |  |
Fixed value |  |  |  |
Exchange Scheme: workflow (Workflow Scheme for Triggering) Batch: BATCH (Workflow Export Batch) Batch Line: 20 (tdsls400)
Serial No. | 10 | 20 | 50 | 70
Field Name | orno | ofbp | corg | sotp
Table Field | orno | ofbp | corg | sotp
Array Element | 0 | 0 | 0 | 0
Condition |  |  |  |
Fixed value |  |  |  |
Export triggers Exchange Scheme: workflow (Workflow Scheme for Triggering) Batch: BATCH (Workflow Export Batch)
Batch Line | 10 | 20
Trigger for Each Row | wf_inventory | wf_salesorder
Create ASCII File | No | No
Trigger for Batch Line End |  |
Optimizations If required, to implement optimizations, you can move conditions from the Trigger to the Exchange scheme. For example, you can create a range for batch line 20 ( tdsls400) on the corg (origin) column to only include sales orders created by means of EDI. This reduces the number of XML events that the Exchange module creates. Note, however, that the Exchange export cannot filter on action type, in this example, only include inserts, skip updates, and deletes. Application customization To perform the implementation, you must customize the function(s) that check the credit limit of a Business Partner, which is used in the sales order related program scripts. The customization adds a check to see whether 80 percent of the credit limit is exceeded. If so, the function creates an event and invokes a trigger. Note You must check that the previous value of the Credit in Use did not exceed the 80 percent threshold. Otherwise, the process will be triggered multiple times for the same customer, which is undesirable. If the trigger you invoke is not in use for any other events, no conditions must be defined. The action that you must take is to create a file that contains the XML event. Implementation Note The information in this document is for educational purposes only, by way of example. The information is not intended to describe a complete and tested solution that will work in a live LN environment. Assume that a library exists that contains a function to check the credit limit. Further assume that the following variables are available in that function: invoice.to.bp: the business partner (customer) to which the invoice must be sent order.number: The sales order being processed credit.limit: The business partner’s credit limit old.credit.in.use: The credit already used before processing the sales order new.credit.in.use: The old.credit.in.use plus the order amount for the new sales order The original version of the library function contains the following code:
    if new.credit.in.use > credit.limit then
            return(true) | credit limit exceeded
        else
            return(false) | credit limit not exceeded
    endif
In a customized version of library, if the usual credit limit check is passed, the 80 percent check is carried out:
    if new.credit.in.use > credit.limit then
            return(true) | credit limit exceeded
        else
            if new.credit.in.use > 0.8 * credit.limit and
               old.credit.in.use <= 0.8 * credit.limit
            then
                generate.credit.trigger(invoice.to.bp,
                            order.number,
                            credit.limit,
                            old.credit.in.use,
                            new.credit.in.use)
            endif
            return(false) | credit limit not exceeded
    endif
At the end of the DLL, the following function is added:
    function generate.credit.trigger(
                domain  tccom.bpid  i.invoice.to.bp,
                domain  tcorno  i.order.number,
                domain  tcamnt  i.credit.limit,
                domain  tcamnt  i.old.credit.in.use,
                domain  tcamnt  i.new.credit.in.use)
    {
    #pragma used dll odatrgapi
    #pragma used dll odatrgevent

    #define MY_TRIGGER  "credit"
    #define ERR_IF_NONZERO(value)
    ^           if value <> 0 then
    ^               | here some error logging can be implemented,
    ^               | for example
    ^               return
    ^           endif

        long    event       |tree containing trigger event
        long    retl            |return value to be checked
        string  error.mess(256) |error message from trigger
        string  error.details(256)  |error details from trigger

        |add event to trigger
        retl = datrgevent.simpleevent.create("Customer",
                        "creditLimitIsNear", event)
        ERR_IF_NONZERO(retl)
        retl = datrgevent.simpleevent.set.value(event,
                "customerID", i.invoice.to.bp)
        ERR_IF_NONZERO(retl)
        retl = datrgevent.simpleevent.set.value(event,
                "orderNumber", str$(i.order.number))
        ERR_IF_NONZERO(retl)
        retl = datrgevent.simpleevent.set.value(event,
                "creditLimit", str$(i.credit.limit))
        ERR_IF_NONZERO(retl)
        retl = datrgevent.simpleevent.set.value(event,
                "creditInIse", str$(i.new.credit.in.use))
        ERR_IF_NONZERO(retl)
        retl = datrgevent.simpleevent.set.old.value(event,
                "creditInUse", str$(i.old.credit.in.use))
        ERR_IF_NONZERO(retl)

        |invoke trigger
        retl = datrgapi.trigger.do(MY_TRIGGER, event,
                        error.mess, error.details)
        ERR_IF_NONZERO(retl)
    }
Trigger setup Triggers Assume that the following three triggers are defined: wf_inventory (for whwmd215) wf_salesorder (for tdsls400) wf_creditlimit (for the application trigger) Trigger conditions In the trigger conditions, you do not have to check the class or table code. If a single trigger was used for multiple classes, you must include the class condition, and you must have the same action performed for each class. The following conditions are defined: Trigger wf_salesorder:
Seq Nr | 10 | 20
And/Or |  | And
Condition Type | Event Type | Attribute
Attribute |  | corg
Operator | = | =
Value | create | 3
Becomes |  | No
Trigger wf_inventory:
Seq Nr | 10
And/Or |
Condition Type | Attribute
Attribute | stoc
Operator | <
Value | 20
Becomes | Yes
Trigger wf_creditlimit will not have any conditions specified, because the conditions are checked in the application. Trigger actions For each trigger, a create XML file action is specified. The local path, file transfer program, and target path are defined. Additionally, if required, a transformation script is defined that translates the generic event into an event that the workflow engine can understand. The minimum requirement will likely be simply to rename the event type into a specific event to enable the workflow engine to detect what event occurred. Note that the class and standard event type are insufficient. The event type will always be Create, Change, or Delete, and the class is not unique because two changes on the same table/class can result in two different workflow processes. If you do not rename the event, the workflow engine must duplicate the conditions as defined for the triggers. In addition, the attributes must be renamed to UDAs that the workflow engine knows. The previous values can be moved to give the values a unique name. For more information, refer to "XML used at runtime," later in this chapter for examples. Finally, rather than use the standard event structure, the transformation script can build up a new event structure. |