The fun (and pain) of Kronos Integration

One of our clients undertook a massive IT transformation program which involved switching to a new financial management system, upgrading and rebuilding a plethora of interfaces among several systems, both internal and external to the business. Kronos was chosen to replace an old timesheet software and there was the need to integrate it with other systems such as Maximo and TechnologyOne. WebMethods was used as the integration tool for this IT ecosystem. This is my first experience with Kronos. The project took almost two years to finish. As always, when dealing with something new, I had quite a bit of fun (and pain) during this project. As it is approaching the final stage now, I think I should write down what I’ve learnt. Hopefully, it will be useful for people out there who’re doing a similar task.

REST API: Kronos provides a pretty good reference source for the REST API at this Link. REST API theoretically offers the advantage of supporting real-time integration and enables seamless workflow. However, we don’t have such a requirement in this project. On the other hand, this has two major limitations.

One is the API throttling limit, which essentially restricts the number of calls you can make based on the license purchased. The other limitation is, it is obvious to me that the API was built for internal use of the application. It is not meant to be used for external integration. No one told us about this when we first started. As a result, we hit several major obstacles along the way. For example, most API calls will need to be method-specific. Cost Center requests need to be either Create New, Update, or Move; there is no Sync or Merge operation. The Update and Move requests will accept Kronos’ internal ID only. When sending an update or move request, we need to send another request first to retrieve the internal ID of a record. Cost Center is a simple master data structure with a few fields, however, to get it to work, we had to build some complex logic to query Kronos to determine whether the record exists (and whether the parent exists) to send in the appropriate create new/update/move calls. The complexity is taken to another level as we needed to build caching mechanism to pre-load and refresh the data at a suitable time so that the number of requests sent to Kronos is kept at minimal. For a more complex data structure such as the Employee master data, if we use the REST API, it is impossible to build an interface that is robust enough for a large scale, high volume environment. I felt like we had to build the whole application layer in WebMethods to handle all sort logic, scenarios, and possible exceptions that could occur. The process to create a new employee record can result in more than a dozen different requests to check existing data and lookup internal Id of different profiles (security, schedule, timesheet, holiday, pay calculation profiles etc.), then send in the Create New/Update requests in the correct order, ensure proper handling of exception and roll back if one request fails due to various reasons.


REST API reference guide (This page shows the API Throttling limits)

Report API: Kronos has a REST API to execute reports (both out-of-the-box and customized). This is useful to alleviate some of the problems with the API throttling limit. For example, we have an interface to send organisation hierarchy (departments and job positions) to Kronos as Cost Centers. The source system would periodically export its whole data set to a CSV file, and we’ll need to query Kronos to determine if the record exists to either send a Create or an Update request, and if the record has new changes to send in update/move requests. We used the Report API to retrieve the whole set of Cost Center data in one single call rather than having to make thousands of individual cost centre detail requests.

Import API: This turned out to the best way to send data to Kronos. We learnt it the hard way. The import API still has a few minor limitations such as some APIs uses description to identify a record instead of an ID, or documentation sometimes is not accurate. Overall, this provides the capability to bulk upload, auto translating ID, and runs on “merge” operation (i.e. automatically decide to create new or update depends on whether a record already exists or not). Since this is an asynchronous operation, and the time it takes to process inbound data depends on the volume, there is a need to build a custom response handler to request (and retry) Kronos later to retrieve the status of the import job and handle success/failure. This custom response handling takes some extra effort to build, but it can be reused for different import endpoints. With the Employee interface mentioned earlier, at a point, it became way too complex and a maintenance nightmare. We had to rebuild it from scratch using the Import API and we’re glad that we did. It was greatly simplified, and we are now very confident of its robustness.

 

List of Import APIs which can be seen after logged in to Kronos


To conclude, if I have to build a new Kronos interface now, for retrieving data from Kronos and sending it to an external system, I will start with using reports to identify new changes, then use the REST API to retrieve details of individual records if necessary. To send data to Kronos, I would look at the Import API first, and will only go for the REST API if the Import API cannot do what I want to do and only if the request is very simple and low volume.     


No comments:

Post a Comment