Human Capital Management Blogs by SAP
Get insider info on SAP SuccessFactors HCM suite for core HR and payroll, time and attendance, talent management, employee experience management, and more in this SAP blog.
cancel
Showing results for 
Search instead for 
Did you mean: 
xavierlegarrec
Product and Topic Expert
Product and Topic Expert
15,293

Overview

Formulas using dates can be difficult to implement in SuccessFactors Compensation templates due to the complexity of the formula parameter.

Additionally some Employee Central fields such as Age (but also Compa-Ratio or Range Penetration and a significant number of other fields) cannot be retrieved directly from EC into a column of a compensation worksheet because they are Transient fields, which means they are calculated on the fly in EC and their data isn't stored.

Finally, roundings in standard recommendation columns or in custom formulas are also complicated to set up either because they require XML edits or because the formulas are not obvious to configure (nested conditions).

 

 

CALCULATING A NUMBER OF DAYS BETWEEN DATES

In this 3 minutes recording we go through the steps required to build a formula that recalculates the age of an employee in a compensation worksheet using the dateDiff function. Please find more Q&A on dateDiff formulas on the SAP blog question thread here.

https://youtu.be/pwWkOHcCCGI


Formula:

round('down',(dateDiff(toDate(customDateOfBirth,"MM/dd/yyyy"),toDate("09/29/2020","MM/dd/yyyy"))/365))


Note : if we need to recalculate the seniority of an employee (Time in Position is a transient field in EC and its data cannot be retrieved in comp planning worksheets) please know that we cannot bring in Today's date dynamically. We would have to either hardcode a date in the formula as per my example above on calculating the Age (our date would need to be aligned with the Comp Cycle start date) or get the date from a lookup table (preferred solution which is easier to maintain for customers).

 

 

Recalculating proration in a custom field with dateDiff formula :

How to use dateDiff to recalculate employee proration in a custom field based on the Hire Date in EC mapped to the standard column "startDate" in the compensation template (this is useful if we would like to display the proration % for each employee but not have it impact standard money columns as per the standard proration feature) :

 


 

Formula : 

if((dateDiff(toDate("01/01/2021","MM/dd/yyyy"),startDate)/365) <= 0,1,(dateDiff(toDate("01/01/2021","MM/dd/yyyy"),startDate)/365))


 

 

 

 

USING A DATE FROM A LOOKUP TABLE FOR PUBLISH BACK TO EC OR MDF

Formula :

toDate(lookup('2021_Publish_back_settings',EE_Country,payroll_area_code,2),'MM/dd/yyyy')

 

 


 

 

 

 

BUILDING IF-THEN RULES WITH DATES

If we want to build an if-then rule where the output will always be a date (for example to handle exceptions for the effective date of the publish back to EC), then we can build our rule the following way (all input fields and the one output field are column type = Date).

 

Reminder: why there is no way to do day/month/year for a single column in a worksheet when the language selected by the planner is US English. (credit Phil MacGovern).

Date fields are shown in the format specified by the language. If planners want to see the dates as day/month/year they need to switch to a different language pack than US (settings > language in top right corner), like UK English (but that effects all dates for all employees including employees in the US).

The toDate function cannot help us here. Even though it can help convert a string column to a Date column, the second parameter (MM/dd/yyyy or dd/MM/yyyy) is a descriptor of what format the string is in, not the expected outcome. If source field is a string, then with the toDate function we are saying "I have a date string in this format: dd/MM/yyyy; convert it to a Date type. So if we have 3/26/2022 in the source field it takes the 3 as the day and 26 as the month which leads to an error and a blank in the target column.

It is also currently not possible to force the format of dates on standard Compensation Statements to only show in one format (for example DD/MM/YYYY). To achieve this we would need to make sure that Dates are in the right format already in the source Compensation worksheets column which in some cases (including when the date pulled onto the statement comes from an editable date column on the worksheet - for example if manager edits the publish back date use it otherwise use default 03/01/2024 date) isn't possible at this time. The only option to meet this requirement would be to download the standard statement and turn it into a "custom" statement by editing its xsl code with a sample like below ($startDate format is defined at the top of the xsl as DD/MM/YYYY).

xavierlegarrec_0-1706594174469.png

 



 

 

Example 1 :


Example 2 : same than example 1 but with 2 override dates (for example one for merit and one for lumpsum)

https://youtu.be/pdXmFo1ezWA

 

If we want to build complex if-then rules using dates and decide whether our output is a date or any other text then we must turn all input columns as well as the output column into String type. Please see examples below.

 

Example 3 :


 

Example 4 :


 

Example 5 :


 

Example 6 :


 

 

Example 7 : If there is no date, then...


 

 

ADDING ROUNDINGS IN COMPENSATION WORKSHEETS

In both cases below (standard or custom fields), SuccessFactors always applies roundings on the local currency value of the recommendation. Which means that in the case of larger currencies (Yen, Rupies...) a lot of inaccuracy can be introduced when toggling back and forth between functional and local currency currency (the percentage may keep increasing because the system will first convert the local currency into functional currency, then round).

We recommend whenever possible to round final payout values instead of recommendation columns. And to remember to always test rounding configuration changes in Local Currency view which is the only view valid for testing due to the above explanations.



 

    • Rounding in standard recommendation fields



To add rounding on all standard recommendation fields such as merit, lumpsum, extra or promotion, we need to download the template xml and add the following line to the MONEY format :


To round 1001.2 to 1100, use <comp-number-format-ext-multiple roundingMode="up">100</comp-number-format-ext-multiple>

To round 1001.2 to 1010, use <comp-number-format-ext-multiple roundingMode="up">10</comp-number-format-ext-multiple>

To round 1001.2 to 1002, use <comp-number-format-ext-multiple roundingMode="up">1</comp-number-format-ext-multiple>

The xml tag "roundingMode" can have the values "up" or "down" or "halfUp" (halfUp is the default prebuilt roundingMode for each format when the tag isn't defined).

 

Please note the following :

    1. this tag ONLY applies to the following fields : merit / promo / extra / extra2 / lumpsum / lumpsum2 / stockunit / stock / option / stockother1 / stockother2 / stockother3 / and custom editable fields of type Money on the worksheet.

 

    1. this tag doesn't round the Current Salary and Final Salary fields or any other standard read-only field of type Money. To round these fields we will need to replace them with a custom field (see below) and adjust the configuration of the publish back to Employee Central.

 

    1. Specific Money formats can also be configured based on the paycomponent frequency of an employee (ANNUAL, MONTHLY, ANNUAL) or the currency code.



 

The recording below shows examples of roundings in standard recommendation fields :

https://youtu.be/-PYpgP8fymU

 

 

 

 

 

    • Rounding on custom fields (credit Phil MacGovern)

 

To round to the nearest 1/n (i.e. round to the nearest 1/4th (0.25) or the nearest 1/20th (0.05) or 1/2 (0.5), the formula is: round('halfUp',x*n)/n


Rounding up to nearest 0.05: round('halfUp',lumpSum*20)/20

Rounding up to nearest 0.5: round('halfUp',lumpSum*2)/2

 

Other frequent rounding requirements: 

Rouding to nearest 5: round('halfUp',round('halfUp',lumpSum)/5)*5
Rounding to nearest 10: round('halfUp',round('halfUp',lumpSum)/10)*10
Rounding to nearest 100: round('halfUp',round('halfUp',lumpSum)/100)*100

Rounding up always: round('up',round('up',lumpSum))
Rounding down always: round('down',round('down',lumpSum))

 

Example 1 (rounding to nearest 5 or 10 or 100) :
 

 

 


 Example 2: (rounding to nearest 0.5 or 0.05)

 

Result of calculationResult should be rounded to:
9.28 %9.50 %
9.70%10.00 %
10.30% 10.50 %

2024-10-10_12-50-22.jpg

 

 

2024-10-10_13-00-54.jpg

 

 

xavierlegarrec_0-1728590513140.png

2024-10-10_13-02-51.jpg

 

 

2024-10-10_13-03-51.jpg

 

For additional content see conversation here.

 

    • Rounding on the last decimal in custom fields


Please note : we can only control rounding within the Number Format already defined and there is no number format for STRING so the formulas below are only relevant for Amount, Money and Percentage type of columns.


Rounding down on the last decimal defined in the column Format (for example #,##0.00 or #,##0.##) : round("Down",finSalary*100/unitPerYear)/100

Rounding halfUp on the last decimal defined in the column Format (for example #,##0.00 or #,##0.##) : round("halfUp",finSalary*100/unitPerYear)/100

Rounding up on the last decimal while keeping the number of decimals defined in the column Format (for example #,##0.00 or #,##0.##) : round("Up",finSalary*100/unitsPerYear)/100

 

Business case : make sure when converting from annual to monthly that the employee doesn't lose out. Let's take an example : If we divide a salary of 70,000 by 12 we get 5,833.33333 which rounds to 5,833.33. But if we multiply that 5,833.33 by 12 then in Employee Central Pay Component Group we get 69999.96 which is lower than what was on the compensation worksheet. By doing  round("up",(finSalary/12)*100)/100 then we get 70,000.08 in the Pay Component Group in EC and hence make sure the employee doesn't lose out. See this blog for more information on this topic with configuration options for permanent consistency.

 

 

 


 

https://youtu.be/JPKzzvKMRkU

 

 

 

 

--

All the best,

Xavier

(If you found this blog useful please consider giving it a Like)

29 Comments
i354253
Product and Topic Expert
Product and Topic Expert
Hello Xavier, Thanks for this blog. In most of the implementations we come across this requirement to create a column for the date difference.

 
0 Kudos
Hello Xavier,

Thanks for this blog, i am calculating tenure in years formula for my client ,can you help me out with a solution with correction on the below formula using date function. Cust_LastPromotion & Cust_DOJ  are columns ids.

 

round("down",if(cust_LastPromotion="NA",(dateDiff(toDate(cust_DOJ,"dd/mm/yyyy"),toDate("06/06/2021","dd/mm/yyyy"))/365),
(dateDiff(toDate(cust_LastPromotion,"dd/mm/yyyy"),toDate("06/06/2021","dd/mm/yyyy"))/365)))

 

 
xavierlegarrec
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi gkkumar

I wouldn't be able to help just by looking at it, working with formulas with dates takes a lot of time and testing.

Here is my tip : try to break down the different parts of your formula into different columns of your worksheet so you can easily spot which nested condition is the problematic one, fix it, then merge it back together in one formula.

Thanks !
former_member23662
Participant
0 Kudos
HI Xavier,

 

I was referring to DOB calculation done in the initial video. would like to know if you store current date somewhere.

dateDiff(toDate(Customdob,”MM/dd/yyyy”),toDate(“12/14/2021″,”MM/dd/yyyy”))/365

 

Pl let me know . Thanks for your help

 

Thanks

Ritanshi

 
rocer
Newcomer
0 Kudos
Hi Xavier,

 

Good day!

 

Would like to check if we can have a formula for Date like for example. HireDate is 05-05-2022 then add +365 days so on the worksheet it will show as 05-04-2023. Will this be possible?

 

Regards,
xavierlegarrec
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi,

As far as I know it would only be possible with a lookup table.

All the best,

Xavier
kavijain
Explorer
0 Kudos
Hi Xavier

I am in a situation where i need to round only the decimals not the number in compensation template

Example

Value to be converted from 19.724101 to 19.73 (always round up) as per requirement from customer

Currently when i round up 19.724101 it gives me 20

Any help will be appreciated...is this possible?

Thanks

Kavita

 
xavierlegarrec
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi kavijain

it's in the blog higher...


Xavier

 

 
kavijain
Explorer
0 Kudos
Thanks that worked. Appreciate your support.
RavindraKumar
Explorer
0 Kudos
Hi

Thanks for this blogs. this is very use full

Is any formula for Hire date - current system date (by default) convert in total month.

example

Hire Date 1/1/2020

Current System Date 29/08/2023

so value should show 43 month

Regards

Ravindra
xavierlegarrec
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi ravindrasharma87

You can divide the number of days (explained in the blog) by 30 and it will give you an estimate of the number of months.

There is no way I know of to make it always 100% exact however. If you want that you would need to build it through a custom MDF object where there is a business rule that allows for 100% months calculation based on the number of days of each month within the period.

All the best

Xavier
susanam1
Explorer
0 Kudos
Good day,

May I please ask a question on numbers formatting, slightly but not directly related to the above?

Hello,


I have asked this question on formatting numbers in ‘Set Numbers Format Rules’ in the Compensation tool in the Learning room Compensation forum in the past and I got the explanation provided in the Implementation Guide as an answer. Unfortunately, this didn’t help much, as my problem is precisely that; that I don’t understand the explanation provided in the Implementation Guide. I also got referred to this article, which does not talk about these format rules.


They have then advised by one of the advisers at the Learning room forum I post my questions to this existing blog and the Implementation SMEs could take a look

So, I would appreciate it if you could advise on my two questions below:


 

  1. QUESTION NUMBER 1: MY QUESTIONS IN ITALICS ON THE RULES:



1)      To format numbers rounded to the left of the decimal point, type in "#,###" in the "Format" field.



2)      To display a comma as a thousands separator, include a comma in the number format



3)      To format numbers with decimal point, include the following digit placeholders in a section.





  • If a number has more digits to the right of the decimal point than there are placeholders in the format, the number rounds to as many decimal places as there are placeholders.



MY QUESTION: what happens if a number has less digits to the right of the decimal point than there are placeholders in the format?


 


MY QUESTION: what happens if a number has the same digits to the right of the decimal point as there are placeholders in the format?





  • If there are more digits to the left of the decimal point than there are placeholders, the extra digits are displayed.


 


MY QUESTION: what happens if there are less digits to the left of the decimal point than there are placeholders?


 


MY QUESTION: what happens if there the same digits to the left of the decimal point than as are placeholders?


 

  • If the format contains only number signs (#) to the left of the decimal point, numbers less than one begin with a decimal point.


# (number sign) displays only significant digits and does not display insignificant zeros.

0 (zero) displays insignificant zeros if a number has fewer digits than there are zeros in the format.


2. QUESTION NUMBER TWO: PLEASE KINDLY VERIFY if the codes I have given to the following examples (in red) are correct. I would like to test if I am beginning to understand the rules.

And if they are not correct, please explain why and provide the correct ones. I am trying to find the consistent logic to all examples, and until now, I am failing to find it.









































NUMBER FORMAT CODE
1.23 1.230 #.##0
1.23 1.23 #.##
1.23 1.2 #.#
1 1.00 #.00
1 01.00 0#.00
12 12.0 #.0


Very many thanks for your continued support

Former Member
Hello, your table is correct; it looks like you understand how the formatting works.

When creating a format, I think of it like this. A '#' symbol displays the digit if it exists. A '0' displays a digit regardless. If one doesn't exist, it adds a 0.

If the number is 3.47 and the format is:




























#.## 3.47 There is a number for each placeholder
#.### 3.47 There is no digit for the last #, so it doesn't display
#.# 3.5 It displays two digits as the format describes and rounds the result
#.##00 3.4700 No digits exist beyond the 7, so the system adds zeroes
#,###.00 3.47 No digits exist before the 3, so they aren't displayed. There are two numbers after the decimal so they are displayed. If there weren't, zeroes would be displayed instead.

I hope this helps.
susanam1
Explorer
Excellent, thanks very much for verifying and for providing a clear, straight forward explanation
swagatikapanda
Participant
0 Kudos

Hi @xavierlegarrec ,

In the variable pay worksheet, I want to make a percent field round to nearest decimal, example:

If I use formula: round('halfUp',(customTeamBonus/customTarget)) output is 100.00%

If I use formula: customTeamBonus/customTarget, output is 89.99%

Team Bonus = 4,793, Custom target = 5,326, I am expecting the output to display as 90.00%.

Please can you help.

 

Thanks,

Swagatika

swagatikapanda
Participant
0 Kudos

Hello @xavierlegarrec @Former Member 

Any thoughts on my query above.

Former Member
0 Kudos

4793/5326 = 0.8999248967. If you round that, you get 1, so that is why you get 100%. You need to multiply by 100, round, then divide by 100.

0.8999248967 * 100 = 89.99248967, rounded becomes 90.0 and divide by 100 to get 0.9, which is 90%.

Use

round('halfUp',(customTeamBonus/customTarget)*100)/100

 

MicheleCordano
Explorer

Hi @xavierlegarrec @Former Member and thanks for this extremely informative thread

 

we are facing an issue:

SuccessFactors Employee Central utilizes half-even rounding for the calculation of pay components (as explained in this document). What this means is that it will round "up" or "down" in order to get the closest even number (e.g. 1.036 -> 1.04, 1.029 -> 1.02)

 

But SuccessFactors Compensation cannot utilize half-even rounding, only roundingMode= "up" / "down" / "halfUp"

 

what this means is that when the compensation manager approves the new salary, they will see a value in the Compensation Module that is not the same of the value that will actually be calculated in Employee Central Compensation Information

 

e.g.: an employee has the Yearly Salary = €35.000,00

  • In the Compensation module the Monthly Salary displayed will be €2,916.67 (Yearly Salary / 12)
    • 35.000,00 / 12 = 2,916.666666666667 and it will be rounded up to €2,916.67

  • when the new Yearly Salary is published to EC and the rule is calculating other pay components, Monthly Salary will be calculated to be €2,916.6
    • 35.000,00 / 12 = 2,916.666666666667 and it will be rounded to the closest even number which is 6

 

my question is: is there a standard procedure to handle this? Or do we have to assume that Monthly Salary calculated in EC will be slightly different than Monthly Salary calculated in the Comp Module?

Is there a best practice to handle this misalignment?

thanks in advance for your time and your help

Arpita_01
Discoverer
0 Kudos

Hi @xavierlegarrec @Former Member any thoughts on the above query ?

Regards,

Arpita Ganguwar

SonjaK
Explorer
0 Kudos

Hi everybody and  @xavierlegarrec @pmacgovern

I wanted to ask for an idea for a challenge regarding rounding. 

Here are examples for the requirement:

Result of calculationResult should be rounded to:
9.28 %9.50 %
9.70%10.00 %
10.30% 10.50 %

It should always be rounded to the nearest 0.5%.

I tried the advices from this blog post but unfortunately it didn't work. The results were never the wanted one. 

It would be great, if someone have an idea or could tell me that it is not possible. 

Thank you in advance.

Sonja

xavierlegarrec
Product and Topic Expert
Product and Topic Expert
0 Kudos

@MicheleCordano @Arpita_01 

Apologies for the delay, I was on parental leave when you posted your question and only catching up with this now.

I believe your EC design may be a bit different from our leading practices and you have a rounding issue that most customers don't have (but they do sometimes have another similar one which I will explain below). Can you share a screenshot of your Yearly and Monthly values in EC ?

The issue I know of only happens with the publish back design and only when planning is done based on annualized values while Pay Components are in various frequencies. I just documented it here: 

https://community.sap.com/t5/human-capital-management-blogs-by-sap/annualized-compensation-planning-...

All the best

Xavier

xavierlegarrec
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @SonjaK 

Sorry for the late reply, I updated the blog above after reaching to Phil, here is the answer:

xavierlegarrec_0-1728590777842.png

 

Arpita_01
Discoverer
0 Kudos

hi @xavierlegarrec  Thank you for your response.

Please find the screenshots below:

On compensation side: As you can see the "Fulltime final salary" is 265887.18 

Arpita_01_0-1729178162826.png

This amount when gets published in EC is same..265887.18. But when period base salary is calculated then it is 22157.26 whereas if we see in the comp worksheet, monthly salary is 22157.27

Arpita_01_1-1729178358159.png

The setup information is given by @MicheleCordano in the above post.

Kindly guide.

Thanks in advance.

Regards,

Arpita

 

 

BalajiNudurupat
Contributor
0 Kudos

Hi @xavierlegarrec :

I saw your below video on the rounding of standard columns. I am wondering if we can round the values based on the employee pay frequency.
https://youtu.be/-PYpgP8fymU

Our requirement is: For some countries like Switzerland, Japan etc., the pay frequency is monthly or 13 payments for 12 months etc. Once the managers enter the recommendations on the planning worksheet, they should automatically round to nearest frequency so that the monthly payments or the adjusted payments should be a round figure without any decimals.

For ex: Employee X has an annual salary as 12000 CHF and pay frequency is 12 months. So his monthly payment is 1000 CHF.

On the planning worksheet, if we give him a raise of 100 CHF, the total salary will be 12000 + 100 = 12100. But when it calculates monthly while sending to ADP, it calculates as 1008.33333. But the final salary should be updated to 12108.

Please let me know if we can achieve this with some updates on the template. Appreciate your guidance on this.

abigaillapuz
Explorer
0 Kudos

Very good article. But I cannot view the images anymore and have tried different web browsers. It returns the following error when trying to open an image in another page.

Forbidden

You don't have permission to access url

xavierlegarrec
Product and Topic Expert
Product and Topic Expert

Hi @abigaillapuz 

it's a known issue that they are working on fixing: 

 

xavierlegarrec_1-1729794792468.png

 

xavierlegarrec
Product and Topic Expert
Product and Topic Expert
0 Kudos

@BalajiNudurupat We can have different number formats with Up, halfUp, or Down roundings based on the currency. I documented it in this blog post.

However I am not sure it would work here for you and you would probably need to use custom roundings in custom columns just for the final numbers.

I don't understand the very last sentence.

"But when it calculates monthly while sending to ADP, it calculates as 1008.33333. But the final salary should be updated to 12108"

To publish back to EC we indeed need to redivide the final annual salary (after recommendation) by the frequency which gives us 1008.33 (beware of this known limitation however). I'm aligned with that.

I just don't understand the math behind the 12108, can you provide the math ? I do see the 8 in 1008.33, but don't understand in the context of the final annual salary number.

xavierlegarrec
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @Arpita_01 @MicheleCordano 

Here are my thoughts after looking at your most recent screenshots.

What we send back from Comp to EC is the value highlighted in your comp worksheet screenshot : 22,157.27.

As far as I know there is no rounding applied by EC on the value published to the paycomponent itself from Comp. What is in the source comp column is what get published. What could happen here is that the publish is made using a different value from the comp worksheet than the one you are showing here in the screenshot (I would need to check the config of the comp template for that).

Once the 22,157.27 is in EC then we can multiply it by 12 which would give us 265,887.24 in the paycomponent group.

xavierlegarrec_0-1729796195799.png

 

I think that the value with .26 you are showing either comes from a custom calculation within the comp portlet (post publish re-calculation) OR as mentioned above it is an issue where what is published from Comp is different from what you think is being used and the .26 value is in a different column.

Maybe it would be best to connect. Feel free to send me a meeting invitation for next week between 9 and 2 pm PST at xavier (dot) le (dot) garrec (at) sap (dot) com

 

BalajiNudurupat
Contributor
0 Kudos

Hello @xavierlegarrec :

Here is my explanation and thought process:

Current Salary: CHF 12000

Merit Increase: CHF 100

So Final Salary = CHF 12100

If the employee pay frequency is 12 Months, then we publish this amount to EC as monthly. So, CHR 12100/12 = CHF 1008.3333. But we want the salary to be rounded based on the frequency. So we need to publish the amount as CHF 1009 for monthly and so the annual or the final salary should be CHF 12108 instead of CHF 12100.

So, we want money format which can help us to round based on the employee's pay frequency.

Please let me know for any additional clarifications.

Thank you.