You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Quantity not rendered in locale formatting when editing propal line #39933
Steps to reproduce the behavior and expected behavior
Dolibarr in French locale, enter fractional quantity on Propal line, validate, then edit again: quantity shown with "." while prices shown with spaces and ','.
Shown correctly when not editing.
The side effect can be that the edited quantity is mis interpreted depending on the locale.
Surely another issue: when I enter '10.0.5' as the quantity, this is accepted as "10", no error reported to at least warn the user. When I enter "10,0.5" the value becomes 100.5 while my locale suggests the decimal point is ','.
Confirmed the inconsistency, but I stopped short of a patch because the safe fix is not obvious and I would rather say why.
In core/tpl/objectline_edit.tpl.php, the money fields are formatted and the quantity is not:
line 256 price_ht ... price($line->pu_ht, 0, '', 0)
line 264 multicurrency_subprice ... price($line->multicurrency_subprice)
line 287 qty ... $line->qty <- raw
line 322 remise_percent ... $line->remise_percent <- raw too
So the field shows the raw column value, 2.50000000 rather than the locale form, which is what your screenshot shows.
The obvious fix is to wrap qty in price() like its neighbours. What made me stop is the round trip: this value is resubmitted and parsed back with price2num() (comm/propal/card.php:2011). I tested price2num() directly and it is locale dependent, it reads the decimal and thousand separators from $langs:
price2num("2,50", 'MS') = 250 <- with the separators of my test context
price2num("2.50000000", 'MS') = 2.5
That is not proof that the fix breaks anything, since in a real request $langs is loaded and the separators match what price() produced. But it does mean the change can only be validated on a configured instance in a locale using a decimal comma, and I cannot do that reliably from here. Getting it wrong would turn a display annoyance into wrong quantities, which is much worse than the current behaviour.
Two things would let this move:
Your locale, so the fix can be checked in the right configuration.
Whether the quantity is saved correctly today when you edit a line, even though it displays unformatted. If it is, the bug is purely cosmetic and the fix is worth doing carefully rather than quickly.
@mdeweerd also worth noting remise_percent has exactly the same treatment on line 322, so whatever is decided should probably cover both.
Localize the internal data before adding it to the UI;
Delocalize submitted data to internal data.
If all entry and exit points are ok and internal functions use the data based on the internal format, it should be all ok.
The challenge here is that the change in 'core/tpl/objectline_edit.tpl.php' fixes the presentation but does not control how the pages relying on it interpret 'qty'.
However 'qty' is already historically user input, so it should already be handled accordingly whereever it is used. If not that would not be a new bug, but an existing one.
remise_percent should IMHO indeed follow the same logic.
That principle is the right frame, and it resolves what had stopped me. Patch: #40012 against 22.0.
You are right that qty has always been user input: every consumer parses it with price2num() already, in propal, commande and facture alike. So the entry point was the only place out of line, and localizing it does not change how anything downstream interprets the value.
I verified the round trip in fr_FR before sending, since a wrong parse would turn a display annoyance into wrong quantities:
db 2.50000000 shown "2,5" parsed 2.5 ok
db 10.00000000 shown "10" parsed 10 ok
db 1234.56000000 shown "1 234,56" parsed 1234.56 ok
db 0.25000000 shown "0,25" parsed 0.25 ok
including the thousand separator case, which was my main worry. My earlier doubt came from testing price2num() without $langs loaded, where the separators default differently, so that was my mistake rather than a real risk.
I used price($line->qty, 0, '', 0, 0), which is exactly what objectline_view.tpl.php:432 already does, comment included, so the edit form now matches the view.
remise_percent is in the same patch as you suggested.
On your point that a pre-existing mishandling elsewhere would not be a new bug: agreed, and I did not find one. All the call sites I checked go through price2num, so nothing downstream relies on receiving the raw format.
Update: #39945 landed on 22.0 while I was preparing mine and fixes the quantity, with the same price($line->qty, 0, '', 0, 0) call. So that half is done.
I rebased #40012 on top of it, and it is now reduced to the single remaining line, remise_percent, which @mdeweerd asked for on the same grounds. The money fields of that form already go through price(), the quantity now does too, and the discount was the last one printed raw.
Same safety argument as for the quantity, and I checked it rather than assumed: every consumer parses the submitted value with price2num() already (comm/propal/card.php:1244 and :1888, commande/card.php:998 and :1645), and the fr_FR round trip is clean including the thousand separator case.
Activity
FIX #39933 localize edited line quantity (#39945)
pixodeo commentedon Sep 2, 2026
Confirmed the inconsistency, but I stopped short of a patch because the safe fix is not obvious and I would rather say why.
In core/tpl/objectline_edit.tpl.php, the money fields are formatted and the quantity is not:
So the field shows the raw column value, 2.50000000 rather than the locale form, which is what your screenshot shows.
The obvious fix is to wrap qty in price() like its neighbours. What made me stop is the round trip: this value is resubmitted and parsed back with price2num() (comm/propal/card.php:2011). I tested price2num() directly and it is locale dependent, it reads the decimal and thousand separators from $langs:
That is not proof that the fix breaks anything, since in a real request $langs is loaded and the separators match what price() produced. But it does mean the change can only be validated on a configured instance in a locale using a decimal comma, and I cannot do that reliably from here. Getting it wrong would turn a display annoyance into wrong quantities, which is much worse than the current behaviour.
Two things would let this move:
@mdeweerd also worth noting remise_percent has exactly the same treatment on line 322, so whatever is decided should probably cover both.
mdeweerd commentedon Sep 2, 2026
My principle is the following:
If all entry and exit points are ok and internal functions use the data based on the internal format, it should be all ok.
The challenge here is that the change in 'core/tpl/objectline_edit.tpl.php' fixes the presentation but does not control how the pages relying on it interpret 'qty'.
However 'qty' is already historically user input, so it should already be handled accordingly whereever it is used. If not that would not be a new bug, but an existing one.
remise_percentshould IMHO indeed follow the same logic.pixodeo commentedon Sep 2, 2026
That principle is the right frame, and it resolves what had stopped me. Patch: #40012 against 22.0.
You are right that qty has always been user input: every consumer parses it with price2num() already, in propal, commande and facture alike. So the entry point was the only place out of line, and localizing it does not change how anything downstream interprets the value.
I verified the round trip in fr_FR before sending, since a wrong parse would turn a display annoyance into wrong quantities:
including the thousand separator case, which was my main worry. My earlier doubt came from testing price2num() without $langs loaded, where the separators default differently, so that was my mistake rather than a real risk.
I used price($line->qty, 0, '', 0, 0), which is exactly what objectline_view.tpl.php:432 already does, comment included, so the edit form now matches the view.
remise_percent is in the same patch as you suggested.
On your point that a pre-existing mishandling elsewhere would not be a new bug: agreed, and I did not find one. All the call sites I checked go through price2num, so nothing downstream relies on receiving the raw format.
Fix Dolibarr#39933 render remise_percent in the locale format when ed…
pixodeo commentedon Sep 2, 2026
Update: #39945 landed on 22.0 while I was preparing mine and fixes the quantity, with the same price($line->qty, 0, '', 0, 0) call. So that half is done.
I rebased #40012 on top of it, and it is now reduced to the single remaining line, remise_percent, which @mdeweerd asked for on the same grounds. The money fields of that form already go through price(), the quantity now does too, and the discount was the last one printed raw.
Same safety argument as for the quantity, and I checked it rather than assumed: every consumer parses the submitted value with price2num() already (comm/propal/card.php:1244 and :1888, commande/card.php:998 and :1645), and the fr_FR round trip is clean including the thousand separator case.
Fix #39933 render remise_percent in the locale format when editing a …
Fix deposit receipt download link (#39952)