博客 Engineering

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

英文文章. 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.

简短回答

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.

常见问题解答

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.

目标

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.

运行闭环

把生产信号转化为已审查的修复。

开始免费试用,了解 Prilog 如何把真实事故映射到代码级 Pull Request。