Teal Partners is developing an application in collaboration with SD Worx to support HR departments in small to medium-sized enterprises. This software package allows SMEs to manage the entirety of the HR-related information for their employees. The new payroll engine performs background calculations of the wages, social security contributions and tax.
The payroll engine treats wage calculation and wage payment as separate processes. This offers scope for prognoses and simulations, from the employer and employee perspectives. It allows a better idea of how certain wage scenarios impact the wage costs (for the employer) and the net results (for the employee).
Payroll calculations are regulated by law. These legal regulations are complex, subject to frequent change and specific to country, region and sector. For that reason, managing and updating the regulations is central to the development of a new payroll engine.
It is crucial to adapt quickly and correctly to changes in the law. Take the coronavirus pandemic, for example. In rapid succession new support measures were introduced to create breathing space for businesses. Payroll software must be capable of incorporating these changing regulations seamlessly.
Flexible management of the parameterisation is therefore a key feature for SD Worx. For that reason, we kept the software development separate from the management and publication of the parameterisation. That separation lets us apply the new regulations sooner. In other words, this type of parametrisation allows the regulations to be defined by non-software developers. Typically, they would be business experts or functional analysts, who are more adept at transitioning to the new regulations.
The separation takes the payroll-engine software to a more abstract level. In the application we only use program code to set the payroll engine options. By this we mean things like the different entities, the calculation levels and their dependencies and the user interface supporting the process for end users.
In the parameterisation we establish three things. Firstly, the behaviour of the payroll engine, such as relevant calculation levels. Secondly, the interpretation of certain payroll input, such as hours worked or absences. And thirdly, the wage calculation itself, such as a gross and net pay comparison, employer contributions or the quarterly settlement.
The payroll engine is modular and uses a microservices architecture. In that architecture we have placed parametrisation management in a separate module, the config module. This module publishes the payroll engine's parametrisation.
We opted from the outset to store the definition dataset, i.e. the relevant set of parametrisation data, in each of the operational module databases. In this way, referential integrity can be guaranteed.
While each module stores just a part of the parametrisation, the config module manages the entirety of the parametrisation data. Consistency is guaranteed by means of specific validation rules.
The illustration below clarifies the configuration module's position relative to the operational modules.
Converting legislation into parametrisation looks, in some respects, like software development. It throws up similar challenges.
The above challenges gave us the idea of not storing our parametrisation in a classic SQL environment or document database, but rather a GIT repository. GIT repository technology meets the needs we have just described.
In the GIT repo the parametrisation is stored in JSON documents. It is a file structure that is easy to read and process. There is yet another advantage to storing the parametrisation in documents rather than denormalized SQL tables. Even without a user interface these files are suitable for the content experts, due to their structure and content.
Here is an example of a JSON configuration file:
{ "Code": "CompanyCar", "ConfigSource": "General", "ValidFrom": "1900-01-01", "ValidUntil": null, "AssetType": "LeaseCar", "BenefitCalculationClass": "GrossUpContract", "Icon": "car", "Labels": [{ "Language": "Dutch", "Hash": null, "Lb1": "Leasewagen" }, { "Language": "English", "Hash": null, "Lb1": "Lease car" }, { "Language": "French", "Hash": null, "Lb1": "Vulture de leasing" }, { "Language": "German", "Hash": "29f5932", "Lb1": "Leasing-Fahrzeug" }] }
Every change in parametrisation goes through the same release cycle as a feature release in the software. A change in parametrisation is isolated in a feature branch. There, it is approved by a pull request before merging with our DEV branch. Eventually, after all the tests have been run, it ends up in the MASTER branch. Once there, the change is validated in the business-acceptance environment before proceeding to the production environment.
There are six steps in the process of bringing a legislation change to production.
The next challenge was to integrate GIT in the configuration module. We need to be able to query information from the config module about branches, commits and data, and to execute data changes and merges.
This integration is an important way to prevent functional profiles from having to deal directly with GIT commands like squash, rebase or merge.
We looked at a range of possibilities. In the end, we went for GitHub. It guarantees the best API support for the software integration. Besides a traditional REST API, GitHub publishes a GraphQL API.
This technology offers greater query precision and flexibility than the classic REST API. As it turned out, this was an important element in guaranteeing performance under a more intensive use of parametrisation.
In conclusion, we have (1) separated software configuration from software development, (2) stored the configuration as JSON files in a GIT repository, (3) used a pipeline for the configuration release matching that for a software release, and (4) built a GitHub integration that lets us develop a support process for the parametrisation.
Next week, in part 2, we will go deeper into the use of microservices architecture within this structure. Be sure to join us if you want to know more about our approach.