blogpost

Writing software based on French law : when a non working day is not a non working day, unless there are 5 of them

When you write a software that has to deal with a specific legislation, you end up finding a lot of weirdness in the law. For a programmer, the law may look like a program patched again and again over years without wondering if redesigning it from scratch wouldn't be a better choice.

Nereo is now the leading leave management software in France and it slowly becomes international. But at the beginning it wasn't easy to understand even simple things like the way the French law counts days. This is why :

Weirdness level 1 : saturdays are non working but not really

The French law (probably many other countries laws as well) says something like :

You will count saturday as a working day even if it's not really a working day.

It means that on saturdays, employees do not have to come to the office nor to work, but you will consider that they did. In french, there is even a specific word for it. "Ouvré" means a really worked day, ie Monday to Friday, while "Ouvrable" means a real or fake worked day, ie Monday to Saturday.

Ok it's weird but why do we have to bother? We don't, unless you count days in a very specific manner. Which is the way we do in France.

Weirdness level 2 : counting normally is too mainstream

When an employee wants to book a leave, you have to take this saturday-rule into account. For example when an employee wants to take an entire week off, you have to count it as 6 days, monday to saturday, and not 5.

What about an employee who wants to take only friday off? Answer : you have to count it as 2 days. This sounds really weird to a lot of people in France because it isn't natural to get charged for 2 days while you take only one day off.

The algorithm for counting how many days you are going to "charge" people for taking days off is NOT counting days between the start and the end of the leave. You actually have to count the number of days between the start of the leave and the instant the employee comes back to work. In examples we give here, employees come back to work Monday morning, so you have to count the number of theorically worked days between the beginning of the leave and the Monday morning.

Booking an entire week counts as 6 days off

Booking a Friday counts as 2 days off

For now, it is quite easy to implement those things within an application. When you display Saturdays on a calendar or a schedule, you have to display them as non working but when you want to count days for a leave you have to include Saturdays. So the first thing is to allow users to mark days as "considered as worked".

Saturdays are marked non working as Sundays, but they count when booking a leave (look at the Saturday, February 14th) :

So that's it folks, this is the end of the article, I hope you enjoyed.... Oh wait. There is just "one more thing" that makes everything a lot more complicated (and interesting for a programmer).

Weirdness level 3 : saturdays are non working but not really, unless you used 5 of them

Ok now, this is going crazy.

The law says workers are entitled to 5 weeks of annual leave (I know this is huge compared to many other countries but we work hard!).

I will try to show how the law looks like a patched code.

"Law-patch" 1 : 5 weeks = 30 days (not 25).

Normally, 5 weeks would be equal to 25 working days. But considering the way we count off-days, we will say that 5 weeks means 30 days, because we include Saturdays.

So... an employee who books 5 weeks of annual leave actually uses 25 days of leave (because he was actually supposed to show up only Monday to Friday), but we gave him 5 more days so we can take him 5 days back.

Couldn't it be easier to entitle him to 25 days and just count working days as Monday to Friday? It could. But no. Not complicated enough for the French law. (Actually the law tolarates to operate annual leaves this way but there are other things to deal with which I won't mention in this article)

"Law-patch" 2 : let's count how we deviate from the logical way

What about an employee who wants to book only Fridays off? The way we count, he could only take 15 days off because every Saturday following his Fridays off would be taken into account. To avoid he gets disadvantaged compared to other employees, we are going to count how many non working Saturdays we considered as working. The rule for Saturdays becomes :

You will count saturday as a working day even if it's not really a working day, unless you already did this with 5 other saturdays.

With this rule, if an employee books only Fridays, his first 5 Fridays will count as 10 days because we will include Saturdays following those Fridays, and he will be able to book 20 other Fridays. So he will be able to take 25 days off, exactly like an employee who would have booked 5 entire weeks.

Sounds insane? Again, we give the employee 5 more days so we can take him 5 days back.

On the software side, implementing this rule and being able to display something clear to employees was not an easy task.

We had to be careful with a lot of situations :

  • An employee can cancel a leave request in the future, possibly decrementing his "considered as worked" counter below 5, so another leave's Saturday should be counted.
  • An employee can book a leave before an existing leave in the future, possibly incrementing his "considered as worked" counter above 5, so another leave's Saturday that has been counted shouldn't be counted anymore.
  • An employee can book a long leave including several Saturdays, some one them possibly counted, some not.
  • An employee must be able to see how many days "considered as worked" he already used.

The model we built to deal with this is a very simple state machine with a stack. You can think about it as a directed graph, each node representing an off-day, each edge representing a precedence condition, and a stack. Edges can increment/decrement the stack with some conditions on the stack. To find out which off-days we should actually count, we walk through this state machine.

With a model like this, we can easily deal with any change in an employee's schedule and we can construct a simple UI to display a consistent explanation to the end-user. If the stack size exceeds 5, we don't push anything on it but we keep track of days marked "considered as worked". We can immediately see that February 14th should not be considered as worked anymore, and we can update this state machine easily if the user does any modification to his schedule.

Now we can avoid counting Saturdays when we are above the threshold, and show it clearly to the user: (look at the Saturday, February 14th)

Conclusion

Each programmer made at least once the mistake of doing a lot of workarounds to make a legacy code with bad design work. This is actually interesting to see that it seems to be simply human nature, since even people who make the law can do this kind of mistake.

Solving challenges is what programmers like most, I was actually happy to have to deal with it. However I would prefer simpler laws so that most of employees understand better their holiday entitlement, even though it allowed our software to create a real difference.

Fun fact : Nobody really gets how this Saturday rule actually works. To understand totally the law, I had to order a law book online from the gouvernment's website. I never thought I would be that happy to receive a law book.