September 25, 2014

Configuration: How to add/change Screen Tab Icons?


We can add or change Screen Tab Icons by making use of Bitmap Categories.


For example, we need to add Screen Tab Icon for Contacts screen.


1) Create a Bitmap Category:

Name: Contacts

Project: <pick_one>


2) Create a Bitmap

Name: Screen Tab Icon

File Name: contacts_icon.gif


File has to be of type GIF and preferably of size 18x18.

File should be placed in /public/enu/images folder




3) Get the Screen name, query for the screen in Siebel Tools.


4) In Siebel Tools menu, click on View --> Windows --> Properties Window (with screen record highlighted in Objects Edit Window). Pick the Bitmap Category, created in Step 1.




5) Compile the Bitmap Category and Screen objects and you are done!


September 22, 2014

Invoking Business Service from Calculated Field Expression


Recently I came across a requirement where in I had to enable/disable a Button on a Applet if all the given conditions are met. The conditions were not that straight forward, I had to go to different BCs (from different BOs) to check them.

The solution I found was InvokeServiceMethod calculated field expression (not recommended by Siebel though)

SYNTAX: InvokeServiceMethod ("My Business Service", "MyMethod", "inputArg1=" + [Field Name 1] + "," + "inputArg2=" + [Field Name 2], "outputArg")

What I did was,
1. Create a Calculated Field "Enable Button"
2. In Calculated Value I used InvokeServiceMethod, which calls a Business Service (method) with RowId as input and returns Y or N.
3. Used this Calculated Field in Applet User Property "CanInvokeMethod: EnableButton".

How InvokeServiceMethod works?
It invokes given method of a Business Service with Input Arguments, Calculated field refers output argument as its Value.

InvokeServiceMethod ("Enable Button Business Service", "EnableButtonMethod", "RowId=" + [Id], "outEnableButton")

My BS code would look something like this:


if (MethodName == "EnableButtonMethod")
{
  var strRowId = Inputs.GetProperty("RowId");
  var strResult = CheckConditions(strRowId);
  if (strResult == "Y")
  {
    Outputs.SetProperty("outEnableButton", "Y");
  }
  else
  {
    Outputs.SetProperty("outEnableButton", "N");
  }
}


It is not advised to use InvokeServiceMethod if the Calculated Field is exposed in UI. Business Service gets invoked every time you step off a record.

May 21, 2014

Scripting: Invoking a Workflow in asynchronous mode

Here is a good way to invoke a Workflow in asynchronous mode. (Workflow Policies are another option)

var bsSvc = null;
var psInput = null;
var psChild = null;
var psOutput = null;

bsSvc = TheApplication().GetService("Asynchronous Server Requests")
psInput = TheApplication().NewPropertySet();
psChild = TheApplication().NewPropertySet();
psOutput = TheApplication().NewPropertySet();
psInput.SetProperty("Component", "WfProcMgr");
psChild.SetProperty("ProcessName", "Health Plan Process"); //workflow name
psChild.SetProperty("Object Id", ContactId);
psChild.SetProperty("Policy Id", PolicyId);
psChild.SetProperty("OGType", "RatePlan");
psInput.AddChild(psChild);
bsSvc.InvokeMethod("SubmitRequest", psInput, psOutput);

April 30, 2014

Executing a SQL through Scripting

Here is the function which takes SQL File Name as imput which is to be executed.

sConnectString = sUserName + "/" + sPswd + "@" + sDBname;
sSQLCommand = "sqlplus" + " " + sConnectString + " @" + vSQLFile;
Clib.system(sSQLCommand);


It looks straight forward but we need to get few important values like SQLFilePath, Username, Password and DBName.


function ExecuteSQL(sqlFileName)
{
    try
    {
        TheApplication().WriteLog("Inside Function ExecuteSQL:Start");
        TheApplication().WriteLog("SQL File Name:" + sqlFileName);

        var boSysPref = TheApplication().GetBusObject("System Preferences");
        var bcSysPref = boSysPref.GetBusComp("System Preferences");
        var sqlPath;
        var vSQLFile;
        var vPropFileName = "/siebel.properties";
       
        //we have stored SQL file path in system preferences
        with(bcSysPref)
        {
            ClearToQuery();
            SetViewMode(AllView);
            ActivateField("Name");
            ActivateField("Value");
            SetSearchSpec("Name", "SQLPath");
            ExecuteQuery();
            if (FirstRecord())
            {
                sqlPath = GetFieldValue("Value");
            }
        }
        vSQLFile = sqlPath + sqlFileName;

        //Read the siebe;.properties file to get Username, Password and DBName
        var propertyFileName = sqlPath + vPropFileName;
        TheApplication().WriteLog("propertyFileName :" + propertyFileName);
       
        var fp = Clib.fopen(propertyFileName, "r");
        var sUserName = "";
        var sPswd = "";
        var sDBname = "";
        var sConnectString = "";
        var sSQLCommand = "";
        var line;
        var Pattern = /\s*$/;

        for (line = Clib.fgets(fp); line != null; line = Clib.fgets(fp))
        {
            var cells = line.split("=");
            var sName = cells[0];
            var sValue = cells[1];

            sName = sName.replace(Pattern, "");
            sValue = sValue.replace(Pattern, "");

            if (sName == "
oracle.siebel.userName")
            {
                sUserName = sValue;
            }
            else if (sName == "oracle.siebel.password")
            {
                sPswd = sValue;
            }
            else if (sName == "
oracle.siebel.db.name")
            {
                sDBname = sValue;
            }
        }

        //Call to execute SQL
        if ((sUserName.length == 0) || (sPswd.length == 0) || (sDBname.length == 0))
        {
            TheApplication().WriteLog("Insufficient DB connection info");
        }
        else
        {
            sConnectString = sUserName + "/" + sPswd + "@" + sDBname;
            sSQLCommand = "sqlplus" + " " + sConnectString + " @" + vSQLFile;
            Clib.system(sSQLCommand);
        }
    }

    catch (e)
    {
        TheApplication().WriteLog("Error in function ExecuteSQL:" + e.toString());
    }

    finally
    {
        TheApplication().WriteLog("ExecuteSQL:End");
    }
}


Amazing! Isn't it? Hope it helps :)

January 24, 2014

Calculating Earliest Start Date and Latest End Date using MVL & MVF

Recently I had a Requirement where in I have a Parent BC and a Child BC. Child BC has records with "Start Date" and "End Date". Each record has different start and end dates. Parent BC has Earliest Start Date and Latest End Date fields.

What I had to do was, find the least of the Start Dates and max of the End Date from the child and populate them at Parent BCs Earliest Start Date and Latest End Date fields.

For determining Earliest Start Date and Latest End Date, as always first thought that came into my mind was achieving this using Scripting :) But I found a better configuration.

Here is what you have to do.

In the Parent BC:

Create a MVL "Parent Child MVL" between Parent and Child BC. (Link between these BCs must have been there)

Create 2 MVFs =======>

Name: Start Date MVF
MVL: Parent Child MVL
Destination Field: Start Date
Type: DTYPE_DATE

Name: End Date MVF
MVL: Parent Child MVL
Destination Field: End Date
Type: DTYPE_DATE

Create 2 calculated fields =======>

Name: Earliest Start Date Calc
Calculated Value: Min ([Start Date MVF])
Type: DTYPE_DATE

Name: Latest End Date Calc
Calculated Value: Min ([End Date MVF])
Type: DTYPE_DATE

You are ready! You can add a small code to read these Calc fields and populate the Parent BC fields Earliest Start Date and Latest End Date! (there might be a better way though)

Siebel is awesome :)