No description
Find a file
Jam Balaya b8dc0d34ec
FIX #33065 page hangs when displaying a very long html content (#39260)
* FIX #39190 wrong unit price when invoicing time spent with one line per declaration (#39215)

* FIX #39190 wrong unit price when invoicing time spent with one line per declaration

In projet/tasks/time.php, the 'onelineperperiod' mode (invoice generation option
"One line for each time spent declaration") computed the unit price as

    $pu_ht = price2num($value['totalvaluetodivideby3600'] / 3600, 'MU');

but totalvaluetodivideby3600 is timespent_duration (seconds) * timespent_thm
(hourly rate), so dividing by 3600 yields "hours * hourly rate", which is the line
total and not a unit price. The quantity passed to addline() is the number of hours,
so the line was billed hours * (hours * rate) instead of hours * rate: the time is
over-billed by a factor equal to the number of hours.

The sibling modes are already correct: 'onelineperuser' and 'onelinepertask' divide
by the recorded number of seconds. Up to 16.0 'onelineperuser' had the same /3600
expression; it was fixed there and 'onelineperperiod' was left behind. Align it with
that reference implementation, including the same guard against a zero duration.

Also reset $pu_ht for each generated line. $pu_ht is initialized once before the loops
(with the price of the selected product/service, or 0) and this mode only had an
"if (empty($pu_ht))" test, so once a price was computed for the first line every
following line reused it, and lines of users with a different hourly rate got the rate
of the first line. The base price is saved before the loop and restored on each
iteration, so the product/service price path is preserved.

* Rename variable for clarity in time.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>

* FIX isInt() does not detect sized integer types (tinyint, bigint) (#39236)

CommonObject::isInt() decides whether a list-page column gets numeric
search mode and is also used when resolving $this->id. The regex
/(^int|int$)/ missed sized integer types such as tinyint(4) and
bigint(20): they neither start nor end with "int".

These types are not exotic: tinyint(4) is used in several core $fields
definitions (societe, contact, entrepot, companypaymentmode, ...) and
ModuleBuilder-generated tables use bigint(20) for rowid, so isInt()
should recognise them rather than requiring callers to change the
column type.

The new regex /^(?:tiny|small|medium|big)?int|int$/ also handles
smallint/mediumint with a size. Anchoring is preserved on purpose so
that strings which merely contain "int" (e.g. sellist:Table:...) are
still NOT matched, while the Dolibarr foreign-key syntax
"integer:Class:path" keeps being detected.

Signed-off-by: Jam Balaya <jambalaya.pyoncafe@outlook.jp>

* FIX #34667 checkUserAccessToObject: skip entity check for non-multientity objects (multicompany) (#39246)

When the multicompany module is enabled, checkUserAccessToObject() (used
by restrictedArea(), e.g. from an ajax tooltip) ran the entity check
unconditionally in its default/custom-object branch, building
"AND dbt.entity IN (...)". For a custom object whose table has no entity
column (ismultientitymanaged = 0), that SQL fails, nb comes back 0 and
access is wrongly denied.

Guard the branch so the entity test only runs when the object is actually
multi-entity managed. Keep the test for legacy classes that never define
ismultientitymanaged (null/unset) and for a non-object $object, and skip
it only when a class explicitly sets ismultientitymanaged = 0.

Supersedes the stale #34667 (by @jyhere) and applies the condition
requested by @eldy in its review.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* FIX mo_production: show very-short unit label instead of untranslated 'UnitPShort' (#39253)

The "Unit" column of the consume/produce tables used
measuringUnitString(..., 2), which translates a <Label>Short key. Those
keys do not exist for most units (e.g. a Piece -> 'UnitPShort', kg ->
'WeightUnitkgShort'), so the raw untranslated key was displayed. Use
param 1 (the very-short DB short_label: 'p', 'kg', ...) like every other
unit column in this file and across the codebase.

Supersedes #31706.

Signed-off-by: Jam Balaya <jambalaya.pyoncafe@outlook.jp>

* FIX #32217 Fire BILL_CREATE with create-form extrafields on next situation invoice (#39254)

When creating the next situation invoice, the create-form extrafields were
saved AFTER createFromCurrent() had already fired BILL_CREATE, so triggers
listening to BILL_CREATE never saw them. Passing 'BILL_CREATE' to
insertExtraFields() (as first proposed) would fire the trigger a second time.

Instead, set the extrafields on $object before createFromCurrent() and let
create() insert them and fire BILL_CREATE once with the values present.
createFromCurrent() now skips its fetch_optionals() when array_options is
already set by the caller, so the form values are no longer overwritten by
the source invoice values. The two other createFromCurrent() callers do not
pre-set array_options, so their behaviour is unchanged.

Supersedes #32217.

Signed-off-by: Jam Balaya <jambalaya.pyoncafe@outlook.jp>

* FIX #33065 page hangs when displaying a very long html content

dol_escape_htmltag() protects the tags listed in $noescapetags before calling
htmlentities(). For the tags carrying attributes it used a do/while loop that,
on each round, searched the first '<tag ...>' with preg_match, replaced every
occurrence of that exact string with str_replace, then compared the whole
content with strcmp to decide whether to loop again.

That loop only consumes one distinct attribute string per round, and each round
scans, rebuilds and compares the whole content. With the 'common' tag list (48
tags) the cost is O(48 * number of distinct attributed tags * length), so it
degrades quadratically with the size of the content while the memory usage stays
flat. A long note or ticket message therefore burns CPU until
max_execution_time is reached instead of raising a memory error.

Replace that loop with a single preg_replace_callback() pass per tag. The
replacement string contains no '<', so it can never build a new tag to protect
and one pass is enough. The attribute string is transformed by exactly the same
operations, in the same order, so the output is unchanged.

Measured on the same content (48 tags, distinct attributes per tag), before and
after, with identical output:

  spans   length    before      after    speedup
    500    29 KB    0.044s     0.006s       7.9x
   1000    59 KB    0.140s     0.010s      13.4x
   2000   121 KB    0.822s     0.028s      29.1x
   4000   245 KB    2.361s     0.042s      56.2x
   8000   493 KB   11.813s     0.171s      69.0x

Equivalence was checked on 26 hand written cases (attributes with brackets,
quotes, forbidden characters, unclosed tags, '<' inside an attribute, reserved
keywords, upper case tags, tabs and newlines) and on 3000 randomly generated
inputs: the old and the new code return the same string for all of them.

---------

Signed-off-by: Jam Balaya <jambalaya.pyoncafe@outlook.jp>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 17:38:42 +02:00
.agents Fix: Use AI provider agnostic .agents, update commit exclusion: develop and version branches (#39189) 2026-07-15 20:40:45 +02:00
.github Qual: Fix PHPStan for 23.0 + pre-commit backports (#39192) 2026-07-16 11:29:42 +02:00
.phan
.tx Update config for tx transifex (#37897) 2026-04-16 13:18:37 +02:00
dev Qual: Fix 'SqlInjection' notices (#39228) 2026-07-20 15:26:30 +02:00
doc Clean files 2026-01-07 19:01:54 +01:00
htdocs FIX #33065 page hangs when displaying a very long html content (#39260) 2026-07-23 17:38:42 +02:00
scripts Qual: Fix SqlInjection notices in scripts (#39214) 2026-07-19 17:32:57 +02:00
test Automated merge from 23.0 to develop 2026-07-23 17:06:43 +02:00
.codeclimate.yml
.editorconfig Qual: Update pre-commit for shell script formatting (#37221) 2026-02-17 22:05:03 +01:00
.gitattributes
.gitignore do not index Mistral Vibe (#38824) 2026-06-15 14:57:29 +02:00
.mailmap Fix mailmap file 2026-07-15 00:56:44 +02:00
.pre-commit-config.yaml Qual: Fix PHPStan for 23.0 + pre-commit backports (#39192) 2026-07-16 11:29:42 +02:00
.travis.yml ci 2026-06-27 14:38:38 +02:00
ChangeLog FIX: Require delete permission for email templates API (#39134) 2026-07-13 14:59:15 +02:00
composer.json.disabled
COPYING
COPYRIGHT Merge branch 'fix_dev_remove_unused_jeditable' of 2026-05-11 01:49:01 +02:00
DCO
phpstan.neon.dist CI 2026-05-22 12:17:17 +02:00
pyproject.toml Qual: Fix PHPStan for 23.0 + pre-commit backports (#39192) 2026-07-16 11:29:42 +02:00
README.md Update link for European directives in README (#38115) 2026-05-07 10:05:17 +02:00
robots.txt Clean files 2026-01-07 19:01:54 +01:00
SECURITY.md Merge branch '23.0' of git@github.com:Dolibarr/dolibarr.git into develop 2026-06-15 01:21:31 +02:00

DOLIBARR ERP & CRM

Downloads per day Docker hub pulls Minimum PHP Version GitHub release CII Best Practices

Dolibarr ERP & CRM is a modern software package that helps manage your organization's activities (contacts, quotes, invoices, orders, stocks, agenda, human resources, ecm, manufacturing…).

It's an Open-Source Software suite (written in PHP with JavaScript enhancements) designed for small, medium or large companies, foundations and freelancers.

You can freely use, study, modify or distribute it according to its license.

You can use it as a standalone application or as a web application to access it from the Internet or from a LAN.

Dolibarr has a large community ready to help you, free forums and preferred partners ready to offer commercial support should you need it

ScreenShot

LICENSE

Dolibarr is released under the terms of the GNU General Public License as published by the Free Software Foundation; either Version 3 of the License, or (at your option) any later version (GPL-3+).

See the COPYING file for a full copy of the license.

Other licenses apply for some included dependencies. See COPYRIGHT for a full list.

INSTALLING

There is a lot of different solutions to install Dolibarr.

Using packages

If you have low technical skills and you're looking to install Dolibarr ERP/CRM with just few clicks, you can use one of the packaged versions (see next chapter if you have IT knowledge) :

Releases can be downloaded from official website.

You can use any web server supporting PHP (Apache, Nginx, ...) and a supported database (MariaDB, MySQL or PostgreSQL) to install the standard version:

  • Verify that your installed PHP version is supported see PHP support.

  • Uncompress the downloaded .zip archive to copy the dolibarr/htdocs directory and all its files inside your web server root or get the files directly from GitHub (recommended if you know git as it makes it easier if you want to upgrade later):

    git clone https://github.com/dolibarr/dolibarr -b x.y (where x.y is the main version like 9.0, 19.0, ...)

  • Set up your web server to use dolibarr/htdocs as root if your web server does not already define a directory to point to.

  • Create an empty htdocs/conf/conf.php file and set write permissions for your web server user (write permission will be removed once install is finished)

  • From your browser, go to the dolibarr "install/" page

    The URL will depend on how your web configuration directs to your dolibarr installation. It may look like:

    http://localhost/dolibarr/htdocs/install/

    or

    http://localhost/dolibarr/install/

    or

    http://yourdolibarrvirtualhost/install/

  • Follow the installer instructions

Using Docker images

Dolibarr is also available as a Docker image. Installation instructions are available here.

Using ready to use SaaS/Cloud offers

If you lack the time to install it yourself, consider exploring commercial 'ready-to-use' Cloud offerings (refer to https://saas.dolibarr.org). Keep in mind that this third option comes with associated costs.

UPGRADING

Dolibarr supports upgrading, usually without the need for any (commercial) support (depending on if you use any commercial extensions). It supports upgrading all the way from any version after 2.8 without breakage. This is unique in the ERP ecosystem and a benefit our users highly appreciate!

Follow these step-by-step instructions to seamlessly upgrade Dolibarr to the latest version:

  • At first make a backup of your Dolibarr files & then see
  • Verify that your installed PHP version is supported by the new version see PHP support.
  • Overwrite all old files from the 'dolibarr' directory with files provided in the new version's package.
  • At your next access, Dolibarr will redirect you to the "install/" page to follow the upgrade process.  If an install.lock file exists to lock any other upgrade process, the application will ask you to remove the file manually (you should find the install.lock file in the directory used to store generated and uploaded documents, in most cases, it is the directory called "documents").

WHAT'S NEW

See the ChangeLog file.

FEATURES

Main application/modules (all optional)

  • Third-Parties Management: Customers, Prospects (Leads) and/or Suppliers + Contacts
  • Members/Membership/Foundation management

Product Management

  • Products and/or Services catalogue
  • Stock / Warehouse management + Inventory
  • Barcodes
  • Batches / Lots / Serials
  • Product Variants
  • Bill of Materials (BOM)
  • Manufacturing Orders (MO)
  • Workstations / Workplaces

Customer/Sales Management

  • Customers/Prospects + Contacts management
  • Opportunities or Leads management
  • Commercial proposals management (online signing)
  • Customer Orders management
  • Contracts/Subscription management
  • Interventions management
  • Ticket System (+ Knowledge management)
  • Partnership management
  • Shipping management
  • Customer Invoices/Credit notes and payment management
  • Point of Sale (POS)

Supplier/Purchase Management

  • Suppliers/Vendors + Contacts
  • Supplier (pricing) requests
  • Purchase Orders management
  • Delivery/Reception
  • Supplier Invoices/Credit notes and payment management
  • INCOTERMS

Finance/Accounting

  • Invoices/Payments
  • Bank accounts management
  • Direct debit and Credit transfer management (European SEPA)
  • Accounting management
  • Donations management
  • Loan management
  • Margins
  • Reports

Collaboration

  • Shared calendar/agenda (with ical and vcal import/export for third-party tools integration)
  • Projects & Tasks management
  • Event organization
  • Ticket System
  • Surveys

HR - Human Resources Management

  • Employee leave management
  • Expense reports
  • Recruitment management
  • Employee/staff management
  • Timesheets

Other application/modules

  • Electronic Document Management (EDM)
  • Bookmarks
  • Reporting
  • Data export/import
  • Barcodes
  • LDAP connectivity
  • Click-To-Dial integration
  • Mass emailing
  • RSS integration
  • Social platforms linking
  • Payment platforms integration (PayPal, Stripe, Paybox...)
  • Email-Collector
  • AI support via API

(around 100 modules available by default, 1000+ addons at the official marketplace Dolistore.com)

Other general features

  • Multi-Language Support (Localization in most major languages)
  • Multi-users and groups with finely-grained rights
  • Multi-Currency
  • Multi-Company (by adding an external module)
  • Very user-friendly and easy to use
  • Customizable dashboards
  • Highly customizable: enable only the modules you need, add user personalized fields, choose your skin, several menu managers (can be used by internal users as a back-office with a particular menu, or by external users as a front-office with another one)
  • APIs (REST, SOAP)
  • Code that is easy to understand, maintain and develop (PHP with no heavy framework; trigger and hook architecture)
  • Support a lot of country-specific features:
    • Spanish Tax RE and IRPF
    • French NPR VAT rate (VAT called "Non Perçue Récupérable" for DOM-TOM)
    • Canadian double taxes (federal/province) and other countries using cumulative VAT
    • Tunisian tax stamp
    • Argentina invoice numbering using A,B,C...
    • Greece fetch customer vat details from AADE, all invoice types, MyData(external free module)
    • ZATCA e-invoicing QR-Code
    • Compatible with European directives (2006/112/CE ... 2010/45/UE)
    • Compatible with data privacy rules (Europe's GDPR, ...)
    • ...
  • Flexible PDF & ODT generation for invoices, proposals, orders...
  • ...

System Environment / Requirements

  • PHP
  • MariaDB, MySQL or PostgreSQL
  • Compatible with all Cloud solutions that match PHP & MySQL or PostgreSQL prerequisites.

See exact requirements on the Wiki

Extending

Dolibarr can be extended with a lot of other external applications or modules from third-party developers available at the DoliStore.

WHAT DOLIBARR CAN'T DO YET

These are features that Dolibarr does not yet fully support:

  • Tasks dependencies in projects
  • Payroll module
  • Native embedded Webmail, but you can send email to contacts in Dolibarr with e.g. offers, invoices, etc.
  • Dolibarr can't do coffee (yet)

DOCUMENTATION

Administrator, user, developer and translator's documentation are available along with other community resources in the Wiki.

CONTRIBUTING AND RELEASE PROCESS

This project exists thanks to all the people who contribute. Please read the instructions on how to contribute (report a bug/error, a feature request, send code, ...) [Contributing]

A View on Contributors:

Dolibarr

The release process is described into the file dev/build/makepack-howto.md

CREDITS

Dolibarr is the work of many contributors over the years and uses some fine PHP libraries.

See COPYRIGHT file.

NEWS AND SOCIAL NETWORKS

Follow Dolibarr project on:

Sponsors

Support this project by becoming a sponsor. Your logo will show up here. 🙏 [Become a sponsor/backer]