Skip to content

Quantity not rendered in locale formatting when editing propal line #39933

Closed

Description

@mdeweerd

Bug

comm/propal/card.php?id=333&action=editline

Image

I suppose this may be similar for other cards.

Dolibarr Version

22.0.5

Environment PHP

No response

Environment Database

No response

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 ','.

Attached files

No response

Activity

  1. added
    BugThis is a bug (something does not work as expected)
    on Aug 31, 2026
  2. added a commit that references this issue on Aug 31, 2026
    57c4e13
  3. pixodeo commented on Sep 2, 2026

    @pixodeo
    Contributor

    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:

    1. Your locale, so the fix can be checked in the right configuration.
    2. 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.

  4. mdeweerd commented on Sep 2, 2026

    @mdeweerd
    ContributorAuthor

    My principle is the following:

    • 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.

  5. pixodeo commented on Sep 2, 2026

    @pixodeo
    Contributor

    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.

  6. added a commit that references this issue on Sep 2, 2026
    068792e
  7. pixodeo commented on Sep 2, 2026

    @pixodeo
    Contributor

    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.

  8. added a commit that references this issue on Sep 4, 2026
    d42ff5f
  9. added a commit that references this issue on Sep 11, 2026
    30eea82
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugThis is a bug (something does not work as expected)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions