Workflow

Estimated reading: 9 minutes

Workflows in LIMBAS

A Workflow for Customer Acquisition

The following example shows a workflow for acquiring new customers for software solutions. Afterwards it is explained how this can be implemented into LIMBAS. The workflow is shown schematically in Illustration 1.

Fig.1

In order to acquire a potential new customer, he is first being sent an advertisement(1). If the customer then shows interest in the product, he is also provided with an online demo access(2). If the customer continues to reaffirm his interest, it is possible to send him a demo CD(3). If the customer is completely convinced, a project appointment should be arranged(4). However, if the customer declines, the customer acquisition workflow is canceled(5). The workflow defines the possible sequence of the individual steps in the customer acquisition. If the workflow has been initiated, the first step is always the sending of an advertising. In this example, it should also be possible to agree on a project deadline if the customer has received a demo or demo CD.
A termination of the customer acquisition is possible up to before the fixation of the project deadline. In addition, the workflow creates an entry for correspondence with the customer after every step. In order to remind the employee after every acquisition action, to contact the customer again after seven days and to inquire about his interest, a reminder is automatically created in Limbas. Finally, the workflow accepts user input via forms and enters them into the corresponding data records. This way, for example the project date is entered into the calendar, or the cancellation reason for the cancellation made by the user is transferred to an automatically generated correspondence entry. Illustration 2 shows the subform Akquise_Absagegrund.

Create a Workflow

The workflow must first be defined in the admin interface. To this end, we create a new workflow called Customer Acquirement. After clicking the Edit button, the individual steps (tasks) of the workflow can be defined.
The table that is to contain the form for the corresponding workflow action is also specified for each task. In our example, this is the customer table for all tasks since the user is to call up a data record of the customer table and to execute the individual actions of the workflow via a form here.
The admin interface also offers the possibility to transfer parameters to the workflow. In this way, configurable workflows can be developed. For example, for tasks 1 to 3, we pass an array with the reminder_days element as a parameter.
This determines how many days after the sending of a brochure, the provision of a demo CD or a demo of the users via a resubmission is to be reminded to contact the customer again.
In order to display rehearsals that are to be created automatically by the workflow after an action is carried out, we need a new re-list.
This can be created via the menu item redeliver in the admin interface. For this purpose, we select the name Acquise and also create customers as the basic table.

Fig. 2

Implement the Workflow

Limbas handles a worklow as an extension. We have created a file named ext_gtab_change.inc in the dependent/EXTENSIONS/workflow/ folder for the script that is presented here.
This file contains our individual workflow functions and the initiation of the workflow, which is shown below:

#limbas workflow engine
require_once("extra/workflow/lwf.lib");
#get wfl instance of dataset
$wfl_inst = lmb_wfl_getRecordInst(1,$gtabid,$ID);
#start Workflow
if(isset($myExt_sendTask)){
 #init Task
 lmb_wfl_init(1,$wfl_inst,$wfl_task,$gtabid,$ID,$params);
}

First we have to integrate the library lwf.lib , which the workflow engine of Limbas provides. In addition, we need three basic informations:

  1. $wfl_id ID of the desired workflow: Generally, an endless number workflows can be created. However, only one workflow is processed at a time.

    Our example contains only one workflow called Acquise and ID # 1
  2. $wfl_task ID of the task to be executed: The TaskID decides which Task is to be executed next. This can, for example, be transferred via a form.
    In our case, the parameters $ myExt_sendTask are passed over a form.
  3. $wfl_inst ID of the current instance: Limbas can assign one or more instances (workflow chains) to each record in a table.
    Whether a record is assigned to an instance can be called using the ‘lmb_wfl_getRecordInst Can be queried.

    In the case of an internal request, LIMBAS transfers the workflow ID
    ($wfl_id) and the instance ID ($inst_id as default) to the instance ID using forms or URLs if available. In our case, we explicitly ask for the instance ID for a particular customer.

    Finally, the function
    lmb_wfl_init initiates the workflow.

The function extra variables are passed as parameters:

  • ‘$ Gtabid’ ‘is the ID of the current table *’ ‘$ ID – ID’ ‘is the ID of the corresponding record *’ ‘$ params – b $ params – user-specific parameter

Task-Functions

After the initiation, Limbas tries to perform the appropriate task. For this purpose, we need an appropriate function for each task.
This function must have the name lmbW!_[TASK_ID] , where TASK_ID must be replaced with the corresponding task ID. In future Limbas versions, these functions should be partially generated by a gray front end. Whether the workflow can only execute the next higher task or any task is entirely in the hands of the developer. In our example, each task can be called so that the acquisition status remains freely changeable. Let’s start with task 0 or start the workflow at (Listing 1). Our task first checks whether the showElements parameter has been passed. This is always the case when a form is displayed.
Then the auxiliary function myExt_showElements is called, which checks what actions the user can perform and then uses a JavaScript function to adjust the form.
In our example, this takes the display of available actionbuttons and the marking of already done actions. If Task 0 is called by the user to initialize the workflow, showElements is not passed.
The workflow calls the next higher task ID with the parameter showElements only when the task has finished successfully. In general, when a task is successfully executed as a function value, it returns the Task ID, which is set as an active task.
In this example, we always set the ID of the last executed task as active Task ID. In order to initialize the workflow successfully, 0 is returned here.
If, however, errors occur during execution, the function false is to be returned. In this case, the Limbas Workflow Engine will undo all changes made to the database by the task.
A task can also return only true if it did not make any workflow changes, e.g. When called with showElements. The next task in our example is sending a brochure to the customer (Listing 2).
Limbas logs the tasks that have already been performed in a history for all instances of a workflow.
For example, to ensure that a workflow action is performed only once, check its existence in the history, which can be called up using the lmb_wfl_getHistory function.
Next, we create a resubmission with the function myExt_createReminder to contact the customer again in the specified time period and to inquire about his interest.
This auxiliary function is essentially based on the extension function lmb_addReminder provided by Limbas. An entry in the correspondence table is then created with wflAddCorrespondence.
Finally, the Acquis status must be set again in the corresponding data field of the customer table. If the execution is successful, the Task-ID 1, otherwise a false is returned.

function lmbWfl_0($wfl_inst, $active_task,
$gtabid = null, $ID = null, $params = null) {
if ($params['showElements']) {
$hist = lmb_wfl_getHistory(1, $wfl_inst);
myExt_showElements($hist);
} else {
// start workflow
return 0;
}
}

(Listing 1)

Creation of the form as user interface for the workflow

Last but not least, we create the corresponding acquisition form for the execution of workflow actions. To do this, we invoke the menu item Forms in the Admin interface and create the form Acquise for the customer table.
In addition to customer data, this form also contains a section for the workflow actions (Fig. 3) . To create buttons for the individual workflow actions, we add a text input field for each action with the corresponding description.
In addition, the onClick attribute is assigned the value myExt_sendTask (Id) , where Id is replaced by the respective task ID. We use this JavaScript help function to submit the corresponding task ID.
The special way to hide or show the buttons in the different tasks is done by means of a JavaScript function which is executed after the form has been loaded This has the advantage of being able to adapt workflow elements, such as the actionbuttons, via the form editor. To do this, we call the workflow initialization function via a PHP form element. This time with the ‘showElements’ parameter set.

Fig.3

Conclusion

Limbas is currently providing all the resources to implement individual workflows for database applications in code. This approach offers the greatest possible flexibility in the implementation of workflows, but also requires advanced knowledge of PHP to implement the corresponding functions.

function lmbWfl_1($wfl_inst, $active_task, $gtabid = null, $ID = null, $params = null) {
  global $gwfl;
  global $session;
  // Get task parameters from admin interface
  $t_params = $gwfl[WFL_ID]['task']['params'];
  // Get history of this workflow instance
  $hist = lmb_wfl_getHistory(WFL_ID, $wfl_inst);
  $days = $t_params['reminder_days'];
 
 if ($params['showElements']) {
  myExt_showElements($hist);
 } else {
  if (!in_array(1, $hist["task_id"])) {
  // Create reminder to contact customer</font>
  if (!myExt_createReminder(lmb_utf8_decode("Kunden kontaktieren"), $days,
  $gtabid, $ID, $wfl_inst))
 
  return false;
  // Create entry in correspondance table
  if (!myExt_wflAddCorrespondence($ID, lmb_utf8_decode("Broschüre"),
  lmb_utf8_decode("Broschüre wurde an den Kunden gesendet.")))
  return false;
  // Set acquisition workflow status
  if (!update_data(array("$gtabid," . ELEMENT_ID_ACQUISITION_STATUS . ",$ID" =>
  lmb_utf8_decode("Broschüre zugesandt"))))
  return false;
  return 1;
  }
  return true;
  }
 }

(Listing 2)

This Wiki-page is based on one of our articles from the PHP-Magazine