Dolibarr / dolibarr

Dolibarr ERP CRM is a modern software package to manage your company or foundation's activity (contacts, suppliers, invoices, orders, stocks, agenda, accounting, ...). it's an open source Web application (written in PHP) designed for businesses of any sizes, foundations and freelancers.
https://www.dolibarr.org
GNU General Public License v3.0
5.24k stars 2.72k forks source link

__DATE_DUE_YMD__ always give date format %d/%m/%Y no matter what main.lang defines it as #20209

Closed bos4711 closed 6 months ago

bos4711 commented 2 years ago

Bug

v15.0.0

The code in htdocs/core/lib/functions.lib.php somehow always returns in DMY-format even when our main.lang formats are defined as this:

FormatDateShort=%Y-%m-%d FormatDateShortInput=%Y-%m-%d FormatDateShortJava=yyyy-MM-dd FormatDateShortJavaInput=yyyy-MM-dd FormatDateShortJQuery=yy-mm-dd FormatDateShortJQueryInput=yy-mm-dd FormatHourShortJQuery=tt:mm FormatHourShort=%H:%M FormatHourShortDuration=%H:%M FormatDateTextShort=%Y-%m-%d FormatDateText=%Y-%m-%d FormatDateHourShort=%Y-%m-%d %H:%M FormatDateHourSecShort=%Y-%m-%d %I:%M:%S %p FormatDateHourTextShort=%d %b %Y, %H:%M FormatDateHourText=%d %B %Y, %H:%M

We use DATE_DUE_YMD in email templates for invoices, and for today's email it contains "10/02/2022" when it should be "2022-02-10".

Reproducable every time.

The email template looks like this:

Vi saknar betalning för faktura __REF__ med förfallodatum __DATE_DUE_YMD__. Kopia på fakturan finns bifogad.

Environment Version

15.0.0

Environment OS

No response

Environment Web server

No response

Environment PHP

No response

Environment Database

No response

Environment URL(s)

No response

Expected and actual behavior

It should respect the date-format specified in main.lang

Steps to reproduce the behavior

No response

Attached files

No response

eldy commented 2 years ago

The format used to output the date with DATE_DUE_YMD param should be the one defined into the language of the output PDF or ODT (so if you generated the PDF for a french customer, it will use the language of the customer so french format). For which document template do you have this problem ?

bos4711 commented 2 years ago

The error is not in a document template, but in email template. All our customers are set to use sv_SE language. PDF output is fine (YYYY-MM-DD) but the email template when sending the PDF is wrong.

Sidenote: we have deleted all languages except for sv_SE and en_US, and we have edited both these to use YYYY-MM-DD everywhere, so where DATE_DUE_YMD gets its format from is unbeknownst to me.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 1 year with no activity. If this is a bug, please comment to confirm it is still present on latest stable version. if this is a feature request, please comment to notify the request is still relevant and not yet covered by latest stable version. This issue may be closed automatically by stale bot in 10 days (you should still be able to re-open it if required).

bos4711 commented 6 months ago

Bug still exists in v19.

hregis commented 6 months ago

@bos4711 try with this fix : https://github.com/Dolibarr/dolibarr/pull/28595

bos4711 commented 6 months ago

@hregis That's the exact same definitions we use today, and they don't work.

I have tried to trace the code to see where the error actually occurs but I haven't found it yet. The only occurence to __DATE_DUEYMD is in functions.lib.php:

./core/lib/functions.lib.php: $substitutionarray['__DATE_DUE_YMD__'] = is_object($object) ? (isset($object->date_lim_reglement) ? dol_print_date($object->date_lim_reglement, 'day', 0, $outputlangs) : null) : '';

So maybe the source of the error is in dol_print_date(), or wrong parameters passed to it?

bos4711 commented 6 months ago

Update: in the quoted line above, if we change 'day' to 'dayrfc' then the result is correct. So something in dol_print_date() messes up the format when using this variable substitution.

hregis commented 6 months ago

@eldy an idea?

bos4711 commented 6 months ago

I have played around in our sandbox-installation and I think I have found a clue. In functions.lib.php, where the DATE_DUE_YMD is substituted, I added three lines of test code:

    $substitutionarray['__DATE_YMD__']        = is_object($object) ? (isset($object->date) ? dol_print_date($object->date, 'day', 0, $outputlangs) : null) : '';
    $substitutionarray['__DATE_DUE_YMD__']    = is_object($object) ? (isset($object->date_lim_reglement) ? dol_print_date($object->date_lim_reglement, 'day', 0, $outputlangs) : null) : '';
    $substitutionarray['__TEST__'] = "We are here";
    print_r($substitutionarray);
    print "<br><br><br>";

When applying the email template, which triggers the error, the substitution is somehow run twice and this can be seen on the screen:

Untitled

This means the first run of substitution the date format is correct, but since it runs a second time (why?) the date format is replaced to the incorrect one.

dol_print_date() always returns the correct date at all times.

eldy commented 6 months ago

The substitution is using the language file of the $outputlang that should be the language of user and not necesserly yours. So the format for lang used is not always the ine in main.lang but can be the one in main.lang of the other language file.

bos4711 commented 6 months ago

Since the template used is made with sv_SE set, shouldn't the main.lang for sv_SE be used no matter what language the user or anything else has set?

bos4711 commented 6 months ago

Screenshot_20240303_160735_org.mozilla.firefox_edit_4178636185834430.jpg

bos4711 commented 6 months ago

I've dived into this issue some more. On my computer, I use en_US as locale. In dolibarr admin interface, we use en_US. In Dolibarr invoices, sales orders, etc we use sv_SE. I had a hunch that because my computer locale is en_US, Dolibarr/PHP might have been confused so I switched locale to sv_SE just to test but the error remains.

Then I went to functions.lib.php again and right under the DATE_DUE_YMD-substitution I added this line just to see what happens:

print $outputlangs->defaultlang . " --- " . dol_print_date($object->date_lim_reglement, 'day', 0, $outputlangs) . "<br>";

Now, when I apply the email template I see two lines:

en_US --- 2023-09-28 sv_SE --- 28/09/2023

Which is very weird, because I have altered the Format-strings in main.lang in both en_US and sv_SE to be exactly the same (%Y-%m-%d). I have also deleted every other lang directory so only en_US/sv_SE remains, and as you can see above the first line is correct (Y-m-d) but the second run (why does it run twice when applying email template?) it changes back to d/m/Y, and there is no trace of this format in main.lang or anywhere else.

Yet Dolibarr somehow picks that format from somewhere, but I cannot find from where. Is that a PHP-default or something?

(I'm aware all my problems can be solved by changing to "dayrfc" in dol_print_date() but there obviously exists a bug here somewhere and I really want to hunt it down)

bos4711 commented 6 months ago

In dol_print_date() I added a stacktrace and print $ret; just before the return of the function, and this happens when clicking "Apply template":

2023-11-16

0 dol_print_date() called at [/var/www/dolibarr.17/core/lib/functions.lib.php:8058]

1 getCommonSubstitutionArray() called at [/var/www/dolibarr.17/core/class/html.formmail.class.php:1531]

2 FormMail->setSubstitFromObject() called at [/var/www/dolibarr.17/core/tpl/card_presend.tpl.php:233]

3 include(/var/www/dolibarr.17/core/tpl/card_presend.tpl.php) called at [/var/www/dolibarr.17/compta/facture/card.php:5819]

16/11/2023

0 dol_print_date() called at [/var/www/dolibarr.17/core/lib/functions.lib.php:8058]

1 getCommonSubstitutionArray() called at [/var/www/dolibarr.17/core/tpl/card_presend.tpl.php:236]

2 include(/var/www/dolibarr.17/core/tpl/card_presend.tpl.php) called at [/var/www/dolibarr.17/compta/facture/card.php:5819]

That is, when FormMail->setSubstitFromObject() is run, the returned substitution date is correct. In the second run, this function is not called and the returned date format gets wrong.

I tried to manually force the code in card_presend.tpl.php to run FormMail->setSubstitFromObject() every time just before getCommonSubstitutionArray() is called, but somehow this does not work. Currently it resides in an if-case just before getCommonSubstitutionArray(). Even when removing the if-clause, the function is not called during the second run.

I think this is the root cause for the bug, but right now I cannot get any further.

bos4711 commented 6 months ago

Now I added print "We're in card_presend.tpl.php<br>"; just before the call to FormMail->setSubstitFromObject() and clicked "apply template again". This is the output:

We're in card_presend.tpl.php

2023-11-16

0 dol_print_date() called at [/var/www/dolibarr.17/core/lib/functions.lib.php:8058]

1 getCommonSubstitutionArray() called at [/var/www/dolibarr.17/core/class/html.formmail.class.php:1531]

2 FormMail->setSubstitFromObject() called at [/var/www/dolibarr.17/core/tpl/card_presend.tpl.php:234]

3 include(/var/www/dolibarr.17/core/tpl/card_presend.tpl.php) called at [/var/www/dolibarr.17/compta/facture/card.php:5819]

16/11/2023

0 dol_print_date() called at [/var/www/dolibarr.17/core/lib/functions.lib.php:8058]

1 getCommonSubstitutionArray() called at [/var/www/dolibarr.17/core/tpl/card_presend.tpl.php:237]

2 include(/var/www/dolibarr.17/core/tpl/card_presend.tpl.php) called at [/var/www/dolibarr.17/compta/facture/card.php:5819]

This means the first run is because of "Apply template". The second run comes from somewhere else, like the call is cached or similiar. This does not make sense to me but I hope it does for someone else.

bos4711 commented 6 months ago

This was an incredibly hard-to-find bug, but I have finally found the root cause.

The bug occurs because the "main.lang" is not loaded properly when Dolibarr switches to sv_SE during the substitution process. Adding a load("main") solves everything.

I will create a fix / PR shortly.