Business workflow hooks

This document describes the business process hooks that can be implemented to put some additional business logic to your business process.

None of these hooks needs to be implemented, simple business process can only rely on configuration.

You need to implement one or several of these hooks if you want to apply out some dynamic business logic that goes beyond what can be configured.

Hooks are very powerful as you can write any needed code, but you need to be careful on the choice of the hook to put your logic in. The choice depends on the nature of the considered business logic.

The hooks examples below are given using the scripted Java (rhino engine) syntax. In such scripts the this variable correspond to the business process itself, it must be explicitly used (it can't be implicit like in Java code). These code examples can easily be transposed to legacy Java hooks code.

Process definition and right-related hooks

Post instanciate hook

The postInstanciate hook is called once when the process definition is loaded.
It can therefore be used to modify the static process definition of each instance.

By static we mean the definition settings that will remain the same all along
the user session (i.e. not the dynamic ones that may be updated in other hooks)

For instance it can be used to:

Example:

MyProcess.postInstantiate = function(grant) {  

    // Get the instance used by the process
    var o = grant.getProcessObject("MyObject");
    // Extend the form by default
    o.setMoreOnForm(false);

    // Show/Hide some fields
    o.getField("myField").setVisibility(ObjectField.VIS_HIDDEN);
    o.getField("myOtherField").setVisibility(ObjectField.VIS_BOTH);

    // Limit the search to employees
    if (this.getGrant().hasReponsibility("EMPLOYEE"))
        o.setDefaultSearchSpec("(t.amount > 1000 and t.enabled='1')");
};

Pre/Post activate hook

The preActivate/ postActivate hook are called before/after the process is activated.
Activate a process auto-validate the BEGIN activity and returns the first user activity.

Example:

MyProcess.preActivate = function() {  
    // Activity definition (Data, Translation...)
    var a = this.getActivity("ACTIVITY_CODE");  
    console.log("activity = " + a.toString());
    // Activity instance in this process
    var context = getContext(a);
    console.log("context = " + context.toString());
    // Force a filter on a search
    context.setDataFile("Filter", "cliType", "someValue");
    // Force a value on a form
    context.setDataFile("Field", "cliType", "someValue");
    ...
};

Pre/Post lock hook

The preLock/postLock hook are called before/after one activity is locked. The lock means that only one user is allowed to validate the activity, the hooks are call before the activity is displayed/validated.

Example:

MyProcess.preLock = function(context) {
    // Access denied to big amount for simple employee
    var a = this.getActivity("STEP-DEMAND");
    var amount = this.getContext(a).getDataValue("Field", "demAmount");
    if (amount && parseInt(amount)>10000 && this.getGrant().hasResponibility("EMPLOYEE")) {
        var m = new Message();
        m.raiseError("ERR_BIG_AMOUNT_DENIED");
        return m;
    }
};
MyProcess.postLock = function(context) {  
    // Force a value
    if (context.getActivity().getStep()=="STEP-1")
        context.setDataFile("Field", "cliType", "someValue");
};

Pre/Post validate hook

The preValidate/ postValidate hook are called before/after one activity is validated.
Allows to add business rules before/after the activity is validated (on UI next button is clicked).

Example:

MyProcess.preValidate = function(context) {  
    // At the client step
    var step = context.getActivity().getStep();  
    if (step=="STEP-CLIENT") {  
        // Check if the name is set
        var name = context.getDataValue("Field", "cliName");  
        if (!name) {
            var m = new Message();
            m.raiseError("ERR_CLIENT_NAME");
            return m;
        }
        // Change the activity result if the address is empty
        var adresseId = context.getDataValue("Field", "cliAdresseFK");  
        if (!adresseId || adresseId=="") {  
            console.log("empty address");
            // EmptyAddress is set in a transition condition
            context.setDataFile("Return", "Code", "EmptyAddress");  
        }  
    } 
};

Pre/Post abandon hook

The preAbandon /postAbandon hooks are called when the process is abandoned.

Allows to add specific business rules (before/after) in the case the process is abandoned.

Example:

MyProcess.preAbandon = function() {

    // Rewrite the Forward of the last activity
    var url = HTMLTool.getListURL("objDemand", "the_objDemand", true);
    var end = this.getContext(this.getEnd());
    if (end) end.setDataFile("Forward", "Page", url);

    // Delete the created object during the workflow
    var id = this.getContext(this.getActivity("MY-STEP-CREATE")).getDataValue("Field", "row_id");
    if (id && id!=ObjectDield.DEFAULT_ROW_ID) {
        var o = this.getGrant().getTmpObject("objDemand");
        o.resetFilters();
        if (o.select(id)) o.del();
    }

    // Return a Message to cancel the abandon ?
    if (someRule) {
        var m = new Message();
        m.raiseError("MY_ERROR");
        return m;
    }
    return null; // continue
};

Pre/Post cancel hook

The preCancel/postCancel hook are called when the activity is canceled.
Allows to add specific business rules (before/after) in the case the activity is canceled.

Example:

MyProcess.preCancel = function(context) {  
    var step = context.getActivity().getStep();  
    // Billing step is canceled ?
    if (step=="STEP-BILLING") {
        // Force the status of the demand step
        var a = this.getActivity("STEP-DEMAND");
        this.getContext(a).setDataFile("Field", "demStatus", "UNPAID");
    }
};

Pre/Post unlock hook

The preUnlock/ postUnlock hook is called when the activity is unlocked by user.

Example:

MyProcess.preUnlock = function(context) {  
    var step = context.getActivity().getStep();  
    if (step=="STEP-DEMAND") {
        // Reset fields
        context.setDataFile("Field", "demAmount", "");
        context.setDataFile("Field", "demNote", "");
    }
};

Pre/Post terminate hook

The preTerminate/ postTerminate hooks is called when the process is terminated = END activity is reached.

Example:

MyProcess.postTerminate = function() {  
    // Client ID
    var a = this.getActivity("STEP-CLIENT");
    var clientId = this.getContext(a).getDataValue("Field", "row_id");
    var cli = this.getGrant().getProcessObject("MyClient");
    if (cli.select(clientId)) {
        // Invoke a scripted action to send email
        cli.invokeAction("sendEmailToClient");
    }
};