Components

Components form the basis of our HRM system. Each component represents compensation and benefits an employee can receive as part of their salary package. This document describes what components are and how they are used throughout the entire system. As you will see components relate closely to policies, the only difference being that components are based on law, sectoral and institutional rules. They are defined by law and therefor informatively enforce those laws. Within the system they are immutable, although they can be influenced by policy. Law provides us with constraints where organizations are free to define their own policies within these constraints. The first order of business is providing a system that can capture these components and their constraints. This is the job of components.

Note

The difference between components and policies is:

  • Components have a legal character, follow institutional law and are therefor immutable. They are controlled on the highest level.
  • Policies is what clients and users can manage to tailor the application to their needs, including the input and results components use and provide.

Why do we need components

Components in our system have a couple of goals. Most essential is that components form the input for salary composition and form the input for payroll engines. The scope of our software is to provide a tool allowing for flexible compensation and benefits for employees. The goal is to make this manageable for the employer by providing in reporting and cost estimations. Additionally, the intent is to create insight for employees into their salary composition by providing a clear overview of all components that make up their salary.

graph TD;
    A[Labour law] --> X(Component)
    B[Sectoral agreements] --> X
    X --> C[Payroll]
    X --> D[Reporting]
    X --> E[Information]

    C ==> F(Benefit in kind)
    C ==> G(Budget impact)
    D ==> H(Total cost of ownership)
    D ==> I(Cost optimization)
    E ==> J(Simulation)
    E ==> K(Visualization)
    E ==> L(Comprehensible)

    classDef green fill:#9f6,stroke:#333,stroke-width:2px,color:black;
    classDef orange fill:#f96,stroke:#333,stroke-width:4px;
    class X green
    class di orange

Example component

To clarify components, we will take the example of an electric bike. Let’s crunch the numbers. In this example an employee has chosen for an electric bike with a consumer price equal to 2799.00.

Result Formula
residualValue 2351.16 consumerPrice - (consumerPrice * residualPercentage)
RSZemployee 307.30 residualValue * RSZemployeePercentage
companyTax 817.55 ((residualValue - RSZemployee) * companyTaxPercentage
cityTax 0.00 ((residualValue - RSZemployee) * companyTaxPercentage * cityTaxPercentage
Netto 1226,32 residualValue - RSZemployee - companyTax - cityTax

Additionally we want to calculate the budget value.

Result Formula
tax 0 consumerPrice * taxRate
residualValue 447.84 (consumerPrice - tax) * residualPercentage
RSZemployerVAA 0 VAAbicyle * componentPeriod * companyContribution
companyTax 817.55 ((residualValue - RSZemployee) * companyTaxPercentage
budgetValue 2351.16 (consumerPrice - tax - residualValue + RSZemployerVAA) / installments

To be able to calculate the values we need, we need some information. These system needs to provide these parameters somehow, or we can’t complete our calculations.

Parameter Value
consumerPrice 2799.00
residualPercentage 0.16
RSZemployeePercentage 0.1307
companyTaxPercentage 0.40
cityTaxPercentage 0
taxRate 0
VAAbicycle 0
componentPeriod 36
companyContribution 0.28
installments 1
Note

A lot of information can be found here. Without specifying where the values come from, we can see that we need about 10 parameters to be able to calculate a single component. Notice that we don’t specify where these parameters are coming from. This is because these parameters differ based on:

  • sector
  • product classification
  • tax rates
  • contract
  • residential address
  • employer contributions

This requirement is where policies come in. We need a way to resolve these values given a set of conditions. Additionally, we need to be able to get these parameters from different corners of the application, we need to be able to set default values, we need to be able to overwrite them to allow for cost optimization and much more. The only mechanism than can cover these use cases is policies. Check out the policies page for more information.

Defining formulas and parameters is all well and good. Although without a way to trigger calculations, or to resolve values, the ability to do calculation has no value. We need to solve a few more problems. Firstly we need to define the input and output of a component.

Component IO

To begin to describe how calculations behave within the system, we need a use case. The first use case we will be considering is that of flexible salary. Flexible salary allows employees to assign a part of their income to their own discretion. Al be it, as always, within the boundaries of the law. To achieve this, we need to link components to employees and/or their contracts. As we determined, components make up an employees salary. Therefor it is the declaration of these components in relation with these employees that starts it all. The question becomes, what are we linking, and how do we identify links? To answer that question, we will be linking multiple concepts through the same system, e.g.:

  • Legal requirements: Monthly/hourly salary
  • Flexible products chosen/ordered by the employee
  • Compensation and benefits as negotioated with the employer

The thing to notice is that the link can take many forms. Therefor basing it on one of these forms would not be practical. Eventually we would need to implement logic that rhymes these corners of the application. The result would be messy, trying to align different use cases together, in a logical, sequential and potentially impact with legal ramifications, could result in: high cost for analysis, slowing progress and complex unmaintainable code.

To mitigate these issues, we will define a standard input/output format for the formulas. One that allows for linking to any and all other concepts both internal and external to the own organization. This would allow for a highly standardized approach that will help to focus on the value components provides. The responsibility of connecting to the component engine will be relayed to the using side. It would be best placed there since it adheres to encapsulation principles.

So we need to define our own object to use as input and output for the component system.

Input

The input for calculations is the actual link. It will contain all values available from the origin. And it will add the configuration for the engine to process the calculations.

Note

The one constant to all links, is the component. It ties it all together.

Important

To keep documentation consistent and readable for non-technical people, I will be defining the objects as yaml. However the system will use json as a format under the hood.

Let’s define an object that can contain the links we need for the calculation engine. Additionally, input is required for calculations to be possible. Therefor when creating the entry, we will add the values as they are available.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
kind: component-values
component: mobilePhone          # component technical name
version: latest                 # indicates to always use the latest version for calculation
date: 20240101100000            # date the entry was created
origin: flexplan-order          # reference to the origin
origin-id: 1234                 # id for the reference
links:
  - employee: aaa-aaa-aaa       # employee linked to the order
  - flexOrder: xxx-xxx-xxx      # order that created this link
  # more links are possible
values:
  - consumerPrice: 2799.00      # product price as chosen by employee in the order
  - residualPercentage: 0.16    # residual percentage as part of a lease/order
  - taxRate: 0.0                # tax rate provided by the product categorization

At this point an entry is made but no calculations have been performed. We need to define how calculations are handled. It is up to the component to tell the system how the calculations should behave. This depends on the context of the component. Let’s add some example calculation definitions to the entry:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
kind: component-values
component: mobilePhone          # component technical name
version: latest                 # indicates to always use the latest version for calculation
date: 20240101100000            # date the entry was created
origin: flexplan-order          # reference to the origin
origin-id: 1234                 # id for the reference
links:
  - employee: aaa-aaa-aaa       # employee linked to the order
  - flexOrder: xxx-xxx-xxx      # order that created this link
  # more links are possible
input:
  - consumerPrice: 2799.00      # product price as chosen by employee in the order
  - residualPercentage: 0.16    # residual percentage as part of a lease/order
  - taxRate: 0.0                # tax rate provided by the product categorization
config:
  start: 20240101               # date calculations should start
  end: 20250101                 # date calculations should end
  interval: * * 1 * *           # cron expression indicating recurring calculations