Blogs Engineering

Making a Leave-Type Setting Actually Work: A Merged Dolibarr Fix

Engelstalig artikel. Dolibarr's 'Blocked when balance is negative' leave setting had no effect. A three-line fix made the per-type option do what it says.

PHPDolibarr/dolibarrERPHRconfiguration

When a checkbox in the admin UI is silently overridden by a hidden global, users lose trust in every other setting.

Kort antwoord

In Dolibarr's Holiday module, enabling "Blocked when balance is negative" on a leave type did nothing unless an undocumented global constant, HOLIDAY_DISALLOW_NEGATIVE_BALANCE, was also set. The fix removes that extra condition from the three balance checks, so the per-type setting governs on its own. It was merged as PR #39654 and closed issue #39605.

The problem

Dolibarr is an open-source ERP and CRM written in PHP. Issue #39605, reported on Dolibarr 23.0.1, described a user with one day of paid-leave balance submitting a two-day request. The request was created without an error, then approved without a warning, leaving the balance negative, even though the leave type was set to block negative balances.

Root cause

Holiday::validate(), Holiday::approve() and Holiday::update() each checked the balance like this:

if (($balance - $daysAsked) < 0 && getDolGlobalString('HOLIDAY_DISALLOW_NEGATIVE_BALANCE')) {

As the PR describes it, the per-type block_if_negative check was neutralized by this undocumented global. Blocking required the constant too, so without it the dictionary setting was ignored.

The fix

if (($balance - $daysAsked) < 0) {
    $this->error = 'LeaveRequestCreationBlockedBecauseBalanceIsNegative';
    return -1;
}

The PR description addresses compatibility. The block_if_negative column defaults to 0 and no shipped leave type enables it, so default behavior stays the same. That preserves the intent of an earlier commit titled "Keep same behaviour by default" while making the setting effective when an admin turns it on.

By the numbers

  • Repository: Dolibarr/dolibarr, 7,826 stars (Nov 3, 2026), PHP, GPL-3.0
  • Files changed: 1
  • Lines: +3 / -3
  • Commits: 1
  • Opened: Aug 21, 2026. Merged: Sep 8, 2026. Time to merge: 17 days, 22 hours
  • Review: merged by a maintainer without review comments

How the review went

There was no discussion on the pull request. A Dolibarr maintainer merged it into develop, and the issue was closed at the same time.

Veelgestelde vragen

Does this block leave for everyone by default?

No. Blocking only applies to leave types where an admin has enabled "Blocked when balance is negative".

Where can I read more?

See the pull request and the original issue.

Het doel

Small fixes like this are easy to skip and costly to leave in place. The diff is three identical lines, and the reasoning about default behavior is in the PR, where a reviewer can check it in a minute.

Voer de loop uit

Zet productiesignalen om in gereviewde fixes.

Start een gratis proefperiode en zie hoe Prilog echte incidenten koppelt aan pull requests op codeniveau.