14 March 2011

SugarCRM: Being Social


SugarCRM is one of the few CRM companies that made all the right noises before Social CRM was known by that name. As I started looking into what the product can do, it was natural enough to have high expectations. Now that I have touched the surface, you will get a chance to sneak-peak as well.
Social CRM, as they say, is customer's territory. As the fact goes, the customer does not give a damn about your beautiful website and the associated paraphernalia. So being Social has been to a large extent providing seamless ways of integrating the product with the external websites that are in the business of getting people to socialize. If the product can achieve that without inflicting pain on its users, it is indeed a welcome development.

I can confidently say Sugar CRM does not disappoint one, although I hasten to add it will not pass in flying colours either. I would have to warn you - all my experiments are confined to  the 'community edition' version. To do justice I would have to go through the enterprise/standard editions one day, but I am not doing any implementation now and I am too lazy to follow-up for a trial version :). Here follows some tidbits:
  • LinkedIn integration stands out indisputably, to such extent that I wondered whether there is any advertising revenue involved! Accounts within Sugar CRM are easily located, and can be processed through whatever LinkedIn offers 
  • There was a lot of gaga about the Twitter integration sometime back. Was quite dismayed to see that it is only present in higher editions. However I did find something on Sugar Exchange which does exactly that, except that it just didn't do it. Well I am quite proud of writing a Twitter connector in Siebel, one of these days I should be repeating that here - with far better customization capabilities
  • As one can expect on an open forum, Sugar Exchange does offer connectors to a few of the well known 'social' platforms out there. But they seem to be nothing but 'connectors' or connecting frameworks, with all the heavy lifting yet to be done to have something that will be of some use. One of the examples I quote is the Jigsaw connector.
  • I tend to think about (& catalog) the 'social crm' part separate from the 'enterprise 2.0' part (sorry, Oracle Social CRM). Integration with Box.net tends to fall into both spaces, and it has a free connector for higher editions (what is with these guys and editions - not enough money in open source, sigh!). But the best and simple example is the Sugar Feed dashlet on the home page. It lets the user type a message and let the world (his world) see - ain't that cool? In the below screenshot you see the user feed below the blog feed.
  • There are also more than a few small players which provide enterprise 2.0 capabilities, and have provided connectors to them. For e.g Broadchoice, and Quontext, but did not interest me enough to 'actually' test them
That is it for now I am afraid, watch this space to not see anything radical happening to Sugar CRM implementation space (you didn't miss the NOT there, did you?).

07 March 2011

SugarCRM: Reporting

One big thing for any CRM application (or any enterprise application - sooner or later) will be the reporting capabilities of a given application. This is where custom applications often suffer, while packaged applications exhibit a hue of colours denoting their respective capabilities. Siebel (there we go again!) was heavily invested into Actuate reporting capabilities for online transactional (a.k.a OLTP) reporting. More recently we have BI Publisher replacing Actuate, the pain & pleasure to implement that is a story for another day. Siebel Analytics (alias Oracle Business Intelligence - OBI) has been the defacto application for analytical reporting (a.k.a OLAP reporting). Both Actuate (now BIP) and OBI are tightly integrated with the Siebel CRM application, which provides a strategic advantage to get started with reports that make sense quickly.
But, we are here to discuss more about how reporting plays a role in SugarCRM. Sugar does offer a reporting module, but that is limited to professional/enterprise versions, so it doesn't exist as far as I am concerned. When I started looking out for what can be done about the problem, I realized once more the open-source advantage. Almost nothing (barring my technical competence or lack thereof) will bar me from getting any BI suite with decent enough APIs to integrate with the Sugar CRM application. The whole problem can now be percolated to two major steps:
  1. First, an application that can enhance/provide good reporting capabilities, and hooks/libraries to integrate. Since it makes obvious sense to first check out free (freer as in you get the code) software, the list is not bad at all.
    1. Jasper reports - transactional/analytical
    2. Eclipse BIRT - carried forward in association with Actuate, transactiona/analytical reporting
    3. Spago BI - if not anything, the website is quite well done. Again, provides transactional and analytical reporting capabilities
    4. Rapid Miner
    5. Pentaho
  2. Next, apply the criteria of integration with SugarCRM, which is a PHP based application.
Now, for the actual decisions to address these two problems. As far as I am concerned, any BI suite will do if it lets me do things easily and produces beautiful reports. Due to my limited background in BI, it is a no-brainer - I have to give a bigger weightage to the next point.
The second problem about integration was supposedly big now. Almost all reporting applications are java-based, and integration can pose a problem due to the steep learning curve required. But, again here comes to rescue another most big aspect nowadays - 'third-party app development'. There are more than few components on SugarExchange that provide utilities/connectors to some of the BI suites mentioned above. After some searching around I selected one of the third party components  called Zucker Reports, for the obvious reason that it was available for development. This module deals with SugarCRM and Jasper reporting tool, so Jasper it is.
As simple as that, and without a line of code actually written, a bridge was established between SugarCRM and Jasper. Now, for some initial exploration:
  1. ZuckerReports provides the ability to generate On Demand reports or schedule them at your own convenience
  2. Reports designed and directly implemented in Jasper server can also be made available in the CRM application
  3. Parameterized reports can be generated as well (though I might add, the functionality is largely limited)
  4. Generated reports can be stored against a account/opportunity or some such record, and emailed to anyone interested
Below are two screen shots that demonstrate what it actually translates to in the application.





Yes, I understand this is no reporting nirvana. But there were one too many times I stifled 'a wow' when things fall into place almost automatically. Capabilities listed in other tools, and integration challenges certainly look promising to me and that is something I have to address sometime in the near future.

    27 February 2011

    SugarCRM: Seamless Mail Sync

    The disclaimer first - my knowledge with SugarCRM has been limited and I only try to dig into things when I find something interesting enough. I have been playing around the latest version (6.12) of SugarCRM lately, and was fairly delighted to see a good email integration feature.

    How it works is pretty straight-forward.
    1. The user can setup his own account to connect to an email account - gmail, yahoo, MS Exchange enabled by default


    2. Connect to email box and check things in Sugar



    3. Import the received/sent email within Sugar, and build other entities like account, opportunity etc. around it


    I was also impressed by the level of integration a calendar entry has. For example, a divisional manager sends a meeting request to his boss and the rep working on a proposal. This is what the rep gets in the email.


    Ofcourse, the point to note is that this was sent from the SugarCRM calendar. There is greater flexibility if it was google calendar (yes, there is a mod to connect with Google calendar).

    The reason I was so delighted should probably be attributed to the way PIM Sync works. Until that is re-written, we probably would not miss out on 'complex' projects to implement email integration.

    05 February 2011

    Siebel: Prototype in eScript - Part 3

    In earlier posts, we have seen using prototypes to extend OOB objects. In other posts we have also dealt with user defined objects and scripts libraries. Time for seeing all three in action you say? And I hear you, we shall see how user defined object can be prototyped, and used across the application.
    Problem: I need a function to lookup the description of a LOV provided its type and value
    Solution: We address the problem in two steps:
    1. Define a user object and make sure it is available for the session. One of the common ways of doing this is in Application object
    2. Use the custom object to define a prototype for useful function(s) - in our case 'LookupDesc'
     Now, the how..
    • Define a variable in the application script, for example: Siebel Life Sciences
    [Application: Siebel Life Sciences, (declarations)]
    var MyApp;
    And, call a business service where MyApp is initialized. This is just to keep the application object, it works just fine within the application itself.
    [Application: Siebel Life Sciences, Method: Application_Start]
    function Application_Start (CommandLine)
    {
     var bsStarter = TheApplication().GetService("COG Test Proto");
     bsStarter.Init();
    }

    • Write the custom business service 'COG Test Proto'
    [Service: COG Test Proto, Method: Init]
     function Init ()
     {
        TheApplication().MyApp = new MyAppFun;
        MyAppFun.prototype.LookupDesc = LookupDescFun;
     }

    [Service: COG Test Proto, Method: MyAppFun]

           function MyAppFun()
           {
     // this is a dummy, but funny function.
           }


      [Service: COG Test Proto, Method: MyAppFun]
    function LookupDescFun (Type, Value)
     {
     try {
      var sDesc = "";
      var boLOV = TheApplication().GetBusObject("List Of Values");
      var bcLOV = boLOV.GetBusComp("List Of Values");
      with (bcLOV) {
         ClearToQuery();
         SetViewMode(AllView);
         ActivateField("Description");
         SetSearchExpr("[Type]='" + Type + "' AND [Value] = '" + Value + "'");
         ExecuteQuery(ForwardOnly);
         if (FirstRecord()) sDesc = GetFieldValue("Description");
      } //with
      return(sDesc);
     }
     catch(e) {
      throw(e);
     }
     finally {
      bcLOV = null;
      boLOV = null;
     }
     }


     That's about it, now MyApp is ready to have some fun. Again, a quick service to test how things work.

    [Service: COG Test Proto Call, Method: Service_PreInvokeMethod]
     function Service_PreInvokeMethod (MethodName, Inputs, Outputs)
     {
        Outputs.SetProperty("out", TheApplication().MyApp.LookupDesc("blah", "blah"));
     }

    A bit of theory on how it works:
    1. MyApp is defined as a variable in Application, the same is initialized in a business service. It does not matter what the function [MyAppFun] contains, we will not be using that anyway
    2. The prototype LookupDesc is defined as an extension of MyAppFun. Any object based on MyAppFun will have access to the LookupDesc functionality
    3. We invoke LookupDesc as an extension of the variable in the application object. There are other blogs out there who just use TheApplication = MyApp, but that practice is not encouraged as I understand
    4. When TheApplication().MyApp.LookupDesc is invoked, Siebel will look for the LookupDesc function for MyApp object. Since the functionality does not exist OOB, the prototype is consulted and in turn LookupDescFun function is executed.

    If you are thinking this is an overkill, you may be right if this is all you want to do. Keep in mind that this coding practice will be more scalable, and ensures reusability.

    02 February 2011

    Siebel: Prototype in eScript - Part 2

    The last example in prototypes dealt with extending a OOB data type, but that extension was done within the business service itself. Although the prototype can be defined only once and used multiple times, it is not really demonstrated well since the entire thing is handled within the same code. Here, let me take an opportunity to show how the prototype definition itself can be handled elsewhere.

    Problem
    Check whether the given string is a valid email address

    Solution
    Define the prototype to extend the OOB string object, and use it as many times as needed. To achieve this we define the prototype in the Application object.

    Go to "Server Scripts" of 'Siebel Life Sciences' or similar, and define prototype.

    (declarations)

    String.prototype.IsEmail = CheckValidEmail;

    Add a function 'CheckValidEmail' to the same application object.

    function CheckValidEmail()

    {

    var rEmailPat = /^\w+[\w-\.]*\@\w+((-\w+)(\w*))\.[a-z]{2,3}$/;

    return rEmailPat.test(this);

    }

    That's about it! Any string can now be tested for a valid email. We will quickly build a test function to demonstrate how this is used:

    Service: COG Test Email

    Method: Service_PreInvokeMethod

    function Service_PreInvokeMethod (MethodName, Inputs, Outputs)

    {

    var sEmail = Inputs.GetProperty("Email");

    Outputs.SetProperty("Valid", sEmail.IsEmail());

    return (CancelOperation);

    }

    When you run this in the simulator, this should either return a 'true' or 'false' value depending on whether the supplied string is a valid email address. Now, a bit about how it works.

    1. First we define the prototype for the data type string with the statement String.prototype.IsEmail = CheckValidEmail'. This statement is executed when the application starts up.
    2. The above prototype points to a custom function 'CheckValidEmail'. This function uses a simple regular expression to test the validity of the entered string. It returns a 'true' when the string has the specified regex pattern, false otherwise
    3. None of the above has any effect until we actually invoke the 'IsEmail' function. When this function is used against the string object, Siebel checks the prototype since no such function exists OOB
    4. Return value from the function denotes whether the string 'sEmail' is a valid email address

    Watch this space for one more example!

    31 January 2011

    Siebel: Script Libraries

    Siebel 8 (or ST engine to be more specific) has a elegant way of calling business service methods. Script libraries provide the ability to call functions on a business service directly, no more is the need for building property sets and setting the parameters!

    If you have not already used script libraries, do take a look. The reduced coding implies lesser mistakes, debugging time and easier maintenance! The simple demo below illustrates the usage.

    Step 1:
    Create the target business service 'COG Test Script Lib'. A custom function 'Echo' is defined here.

    Service_PreInvokeMethod:

    function Service_PreInvokeMethod (MethodName, Inputs, Outputs)

    {

    return (CancelOperation);

    }

    Echo:
    function Echo (MyString)

    {

    return "Echoed: " + MyString;

    }



    Step 2:
    Create the caller service 'COG Test Script Lib Call'. There is only one method here - 'Service_PreInvokeMethod', and the following code has to be input:

    function Service_PreInvokeMethod (MethodName, Inputs, Outputs) {

    var bsTest = TheApplication().GetService("COG Test Script Lib");

    Outputs.SetProperty("Output", bsTest.Echo("abc"));

    bsTest = null;

    return (CancelOperation);

    }



    Compare this to the approach in earlier versions. In most probability you will be coding something like:

    function Service_PreInvokeMethod (MethodName, Inputs, Outputs)

    {

    var bsTest = TheApplication().GetService("COG Test Script Lib");

    var psIn = TheApplication().NewPropertySet();

    var psOut = TheApplication().NewPropertySet();

    psIn.SetProperty("MyString", "abc");

    bsTest.InvokeMethod(psIn, psOut);

    Outputs.SetProperty("Output", psOut.GetProperty("ReturnString"));

    psOut = null;

    psIn = null;

    bsTest = null;

    return (CancelOperation);

    }


    And, don't forget to add a line or two in the target service 'COG Test Script Lib' to set required properties in the output propertyset. Now, a simple 'bsTest.Echo("abc")' does the job. Isn't life simpler?

    24 January 2011

    Siebel: Prototype in eScript

    I had mentioned about using prototypes in one of the previous posts, here's a drilldown into how things work.
    Tucked away in a remote corner in the eScript reference of the Siebel Bookshelf is a single paragraph referring to prototypes. Common to javascript developers, prototype is not something that we bother about too often. Prototypes provide a highly reusable way of extending out of the box objects, with an optimal memory usage as a bonus.

    How do we use Prototypes?
    The best way to understand will be through an example. Let us consider a problem where we need to add x days to the given date and get the next working day (!= Saturday or Sunday).
    We go about this problem by extending the Date object to support a new functionality - add x days and retrieve the next working day. For simplicity sake we keep the definition of prototype and the actual call together, however they may be located in different objects as well.
    To demo the prototype define custom business service 'COG Get Working Day' in Siebel Tools or Client. Paste the following code in relevant sections:
    (declarations)


    Date.prototype.AddDaysToGetWrkDay = AddDaysToGetWrkDay;

    AddDaysToGetWrkDay


    function AddDaysToGetWrkDay(iDays, Outputs)

    {

    var iDateNew; var iOneDay = 24 * 60 * 60 * 1000; // day in milliseconds -
    (hrs/day * min * sec * ms)
    this.setMilliseconds(iDays * iOneDay);
    if
    (this.getDay() == 0 this.getDay() == 6) { // if sunday or saturday

    this.AddDaysToGetWrkDay(1); // add one more day and check whether that falls
    on working day

    }

    return this;

    }

    Service_PreInvokeMethod
    function Service_PreInvokeMethod (MethodName, Inputs, Outputs)
    {
    try {
    var dSomeDate = new Date("1/28/2011");
    dSomeDate.AddDaysToGetWrkDay(1);
    Outputs.SetProperty("New Date", dSomeDate);
    return (CancelOperation);
    }
    catch(e){
    throw(e);
    }
    finally {
    dSomeDate = null;
    }
    }


    When executed through simulator (or a call from placed from another service), the service returns the next working day - in the above example 31-Jan-2011. Read on to find out how.


    Code Explanation

    1. 'Date.prototype.AddDaysToGetWrkDay = AddDaysToGetWrkDay' is the statement that tells the execution engine that there is a new prototype for Date object, and the extended functionality is provided by the function (or object) called 'AddDaysToGetWrkDay'. This is not synonymous with calling a function since there is no actual execution at this point. It is equivalent to a declaration.
    2. Next, define the function 'AddDaysToGetWrkDay'. This will act on the provided date object, which is referenced using 'this'. All it does is to add the given number of days to the date, check whether the new date falls on a Saturday or Sunday, continue adding more days if that is the case, and return the final date. Recursion is used to keep on adding days until it is not required.
    3. 'Service_PreInvokeMethod' just calls the extended function 'AddDaysToGetWrkDay' against the date object. When the actual call is made, the scripting engine looks at the Date object itself to check whether such a method is present, and then consults the prototype. Since such a prototype exists and points to a function, the function is executed to return the result

    Note that the prototype itself may be defined only once, and the functionality is available thereon. Though this example is simple at its best, it does demonstrate how prototypes can be used to extend the objects.

    Conclusion

    Keep in mind the following:

    • Prototypes share the same memory space. Multiple invocations do not mean multiple copies
    • Prototypes can also be added later. Dynamic invocation can mean that you don't need to do everything in one place and at once
    • A prototype can also be extended further. For example, I can very well define another which says 'AddDaysToGetWrkDay.prototype.ExcludeDay' to selectively exclude certain days. For example, myDate.AddDaysToGetWrkDay(21).ExcludeDay("Tuesday") can return the working day 21 days from the given date, but which is not a Tuesday
    • From the above point you can observe that the methods can be executed in a 'chained' manner, which gives us a scalable solution that is easy to maintain (remember my OO reference in an earlier post?)
    • Use prototypes for reusable functions, that is when they yield better results

    So, how do you want to use prototypes in your application?