From c8ebd5ce530d97dca4623a21d465c99bd0854c12 Mon Sep 17 00:00:00 2001 From: Zakaria Boushaba <48571684+Boushabazakaria@users.noreply.github.com> Date: Wed, 24 Jun 2026 15:51:23 +0100 Subject: [PATCH 01/11] Fix date/datetime extrafield shown empty after update_extras due to stale POST data (#38984) Co-authored-by: Zakaria Boushaba --- htdocs/core/tpl/extrafields_view.tpl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/extrafields_view.tpl.php b/htdocs/core/tpl/extrafields_view.tpl.php index 8dc99923682..98629728a28 100644 --- a/htdocs/core/tpl/extrafields_view.tpl.php +++ b/htdocs/core/tpl/extrafields_view.tpl.php @@ -281,7 +281,7 @@ if (empty($reshook) && !empty($object->table_element) && isset($extrafields->att $datenotinstring = $db->jdate($datenotinstring); } //print 'x'.$object->array_options['options_' . $tmpkeyextra].'-'.$datenotinstring.' - '.dol_print_date($datenotinstring, 'dayhour'); - $value = GETPOSTISSET("options_".$tmpkeyextra) ? dol_mktime(12, 0, 0, GETPOSTINT("options_".$tmpkeyextra."month"), GETPOSTINT("options_".$tmpkeyextra."day"), GETPOSTINT("options_".$tmpkeyextra."year")) : $datenotinstring; + $value = ($action == 'edit_extras' && GETPOSTISSET("options_".$tmpkeyextra)) ? dol_mktime(12, 0, 0, GETPOSTINT("options_".$tmpkeyextra."month"), GETPOSTINT("options_".$tmpkeyextra."day"), GETPOSTINT("options_".$tmpkeyextra."year")) : $datenotinstring; } if (in_array($extrafields->attributes[$object->table_element]['type'][$tmpkeyextra], array('datetime'))) { $datenotinstring = empty($object->array_options['options_'.$tmpkeyextra]) ? '' : $object->array_options['options_'.$tmpkeyextra]; @@ -290,7 +290,7 @@ if (empty($reshook) && !empty($object->table_element) && isset($extrafields->att $datenotinstring = $db->jdate($datenotinstring); } //print 'x'.$object->array_options['options_' . $tmpkeyextra].'-'.$datenotinstring.' - '.dol_print_date($datenotinstring, 'dayhour'); - $value = GETPOSTISSET("options_".$tmpkeyextra) ? dol_mktime(GETPOSTINT("options_".$tmpkeyextra."hour"), GETPOSTINT("options_".$tmpkeyextra."min"), GETPOSTINT("options_".$tmpkeyextra."sec"), GETPOSTINT("options_".$tmpkeyextra."month"), GETPOSTINT("options_".$tmpkeyextra."day"), GETPOSTINT("options_".$tmpkeyextra."year"), 'tzuserrel') : $datenotinstring; + $value = ($action == 'edit_extras' && GETPOSTISSET("options_".$tmpkeyextra)) ? dol_mktime(GETPOSTINT("options_".$tmpkeyextra."hour"), GETPOSTINT("options_".$tmpkeyextra."min"), GETPOSTINT("options_".$tmpkeyextra."sec"), GETPOSTINT("options_".$tmpkeyextra."month"), GETPOSTINT("options_".$tmpkeyextra."day"), GETPOSTINT("options_".$tmpkeyextra."year"), 'tzuserrel') : $datenotinstring; } // TODO Improve element and rights detection From 9570b49024021909b1baabd34c36409815db872d Mon Sep 17 00:00:00 2001 From: kkhelifa-opendsi Date: Thu, 25 Jun 2026 21:28:08 +0200 Subject: [PATCH 02/11] FIX: Fix rang of added lines when create a contract from another element (#38856) --- htdocs/contrat/card.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 524722f10ad..036efff36f5 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -360,6 +360,7 @@ if (empty($reshook)) { $fk_parent_line = 0; $num = count($lines); + $rang = 0; for ($i = 0; $i < $num; $i++) { $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0); @@ -429,7 +430,7 @@ if (empty($reshook)) { $lines[$i]->pa_ht, $array_options, (int) $lines[$i]->fk_unit, - $num + 1 + $rang++ ); if ($result < 0) { From 93602a7246a63007a9a9a5949d89afc427fda338 Mon Sep 17 00:00:00 2001 From: Zakaria Boushaba Date: Fri, 26 Jun 2026 09:23:25 +0100 Subject: [PATCH 03/11] Fix: reset fk_code_ventilation on cloned customer invoice lines --- htdocs/compta/facture/class/facture.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 78c454fed8e..cd146bc69b4 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1354,6 +1354,7 @@ class Facture extends CommonInvoice } $object->lines[$i]->ref_ext = ''; // Do not clone ref_ext + $object->lines[$i]->fk_code_ventilation = 0; // Do not clone accounting binding } // Create clone From 0a810507bb5852c1fd0a2cd715795b1fa7306e29 Mon Sep 17 00:00:00 2001 From: ThomasNgr-OpenDSI Date: Fri, 26 Jun 2026 13:26:11 +0200 Subject: [PATCH 04/11] FIX : when cloning a supplier order, the date would be set to 01/01/1970 (#38270) --- htdocs/fourn/class/fournisseur.commande.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 086897566fc..e011371eacc 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -163,7 +163,7 @@ class CommandeFournisseur extends CommonOrder public $date_approve2; /** - * @var int Date of the purchase order ordering + * @var null|int Date of the purchase order ordering */ public $date_commande; @@ -1944,7 +1944,7 @@ class CommandeFournisseur extends CommonOrder $this->date = dol_now(); $this->date_creation = 0; $this->date_validation = 0; - $this->date_commande = 0; + $this->date_commande = null; $this->ref_supplier = ''; $this->user_approve_id = 0; $this->user_approve_id2 = 0; From d9102959fda7e9b57d18fedc931525096be32c84 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Jun 2026 16:49:45 +0200 Subject: [PATCH 05/11] Fix showunused option in sanity_check_trans_missing_unused.sh --- dev/translation/sanity_check_trans_missing_unused.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dev/translation/sanity_check_trans_missing_unused.sh b/dev/translation/sanity_check_trans_missing_unused.sh index a04a11208fe..d671d1dd164 100755 --- a/dev/translation/sanity_check_trans_missing_unused.sh +++ b/dev/translation/sanity_check_trans_missing_unused.sh @@ -130,9 +130,11 @@ diff "${AVAILABLE_FILE}" "${EXPECTED_FILE}" \ > "${MISSING_AND_UNUSED_FILE}" rm -f "${UNUSED_FILE}.grep" >/dev/null 2>&1 -sed -n 's@< \(.*\)@^\1\\s*=@p' \ - < "${MISSING_AND_UNUSED_FILE}" \ - > "${UNUSED_FILE}.grep" +if [ "$1" == "--showunused" ]; then + sed -n 's@< \(.*\)@^\1\\s*=@p' \ + < "${MISSING_AND_UNUSED_FILE}" \ + > "${UNUSED_FILE}.grep" +fi # Prepare file with exact matches for use with `git grep`, supposing " quotes From 6e101143e02aeada6c760f1cdb5f68ceaece15bc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Jun 2026 16:49:45 +0200 Subject: [PATCH 06/11] Fix showunused option in sanity_check_trans_missing_unused.sh --- dev/translation/sanity_check_trans_missing_unused.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dev/translation/sanity_check_trans_missing_unused.sh b/dev/translation/sanity_check_trans_missing_unused.sh index a04a11208fe..d671d1dd164 100755 --- a/dev/translation/sanity_check_trans_missing_unused.sh +++ b/dev/translation/sanity_check_trans_missing_unused.sh @@ -130,9 +130,11 @@ diff "${AVAILABLE_FILE}" "${EXPECTED_FILE}" \ > "${MISSING_AND_UNUSED_FILE}" rm -f "${UNUSED_FILE}.grep" >/dev/null 2>&1 -sed -n 's@< \(.*\)@^\1\\s*=@p' \ - < "${MISSING_AND_UNUSED_FILE}" \ - > "${UNUSED_FILE}.grep" +if [ "$1" == "--showunused" ]; then + sed -n 's@< \(.*\)@^\1\\s*=@p' \ + < "${MISSING_AND_UNUSED_FILE}" \ + > "${UNUSED_FILE}.grep" +fi # Prepare file with exact matches for use with `git grep`, supposing " quotes From 5ade4d0567765ae8fbc008d7638f256f9771f24e Mon Sep 17 00:00:00 2001 From: nicolasVr <46503289+nicolasVr@users.noreply.github.com> Date: Sat, 27 Jun 2026 17:57:03 +0200 Subject: [PATCH 07/11] FIX Syntax error (#38976) This prevented display of reminder fields --- htdocs/comm/action/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index a59bbda3588..ea2ec7498db 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1925,7 +1925,7 @@ if ($action == 'create') { $("#select_offsetunittype_duration").select2("destroy"); $("#select_offsetunittype_duration").select2(); selectremindertype(); - }); + } toggle_reminder_part(); $("#addreminder").click(toggle_reminder_part); From f8d674f324077551c7ff17a469db869f558ec15d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Jun 2026 17:09:22 +0200 Subject: [PATCH 08/11] Test disable consumming task --- .pre-commit-config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 01fd70ff8cc..9f3b54f34ae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -254,7 +254,8 @@ repos: rev: 3.3.1 hooks: - id: sqlfluff-lint - stages: [pre-commit, manual] # manual needed for ci + #stages: [pre-commit, manual] # manual needed for ci + stages: [manual] # manual needed for ci exclude: (?x)^ (dev/initdemo/mysqldump_.*\.sql |htdocs/core/menus/init_menu_auguria\.sql From 4d313cfd6acc45509f96dd67c01589a8c94b3345 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 1 Jul 2026 17:10:37 +0200 Subject: [PATCH 09/11] Fix warning --- htdocs/install/index.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/htdocs/install/index.php b/htdocs/install/index.php index c089a90fdf4..41dd768a0e1 100644 --- a/htdocs/install/index.php +++ b/htdocs/install/index.php @@ -27,6 +27,11 @@ define('ALLOWED_IF_UPGRADE_UNLOCK_FOUND', 1); include_once 'inc.php'; +/** + * @var string $conffile + * @var ?string $dolibarr_main_url_root + */ +'@phan-var-force string $conffile'; // From inc.php include_once '../core/class/html.form.class.php'; include_once '../core/class/html.formadmin.class.php'; @@ -36,6 +41,7 @@ $err = 0; // If the config file exists and is filled, we're not on first install so we skip the language selection page if (file_exists($conffile) && isset($dolibarr_main_url_root)) { + //header("Location: '.$dolibarr_main_url_root.'/install/check.php?testget=ok"); header("Location: check.php?testget=ok"); exit; } From dc2a01ff28900288816a97dc12c36bfa1973f595 Mon Sep 17 00:00:00 2001 From: reachsanjivbhagat-gif Date: Thu, 2 Jul 2026 03:25:04 -0700 Subject: [PATCH 10/11] FIX #32909 Restrict salary/HR field edit to authorized users (#39033) * FIX #32909 Restrict salary/HR field edit to authorized users On the user card, a user with only "modify own info" (user->self->write) could edit thm, tjm, salary, salaryextra and weeklyhours, even though the display of these fields is gated on salaries->readall / hrm->employee->read. Guard the write of these fields with the same permission used for display, so self-service users can no longer change compensation data they are not allowed to see. Signed-off-by: Sanjiv Kumar Bhagat * Update card.php * Update salary edit permissions logic --------- Signed-off-by: Sanjiv Kumar Bhagat Co-authored-by: Laurent Destailleur --- htdocs/user/card.php | 45 ++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 9c4f85580ad..da29cd14f57 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -161,6 +161,9 @@ if ($id > 0) { $permissiontoeditpasswordandsend = ((($user->id == $id) && $user->hasRight("user", "self", "password")) || (($user->id != $id) && $user->hasRight("user", "user", "password")))&& (empty($user->socid) || $user->socid == $object->socid); } +// Salary and other HR fields must only be editable by users allowed to see them (same rights as the display, see issue #32909) +$permissiontoeditsalary = ((isModEnabled('salaries') && $user->hasRight("salaries", "read") && in_array($id, $childids)) || (isModEnabled('salaries') && $user->hasRight("salaries", "readall")) || (isModEnabled('hrm') && $user->hasRight("hrm", "employee", "read"))); + $passwordismodified = false; $ldap = null; @@ -333,14 +336,17 @@ if (empty($reshook)) { $object->fk_user_holiday_validator = GETPOSTINT("fk_user_holiday_validator") > 0 ? GETPOSTINT("fk_user_holiday_validator") : 0; $object->employee = GETPOSTINT('employee'); - $object->thm = GETPOST("thm", 'alphanohtml') != '' ? GETPOST("thm", 'alphanohtml') : ''; - $object->thm = price2num($object->thm); - $object->tjm = GETPOST("tjm", 'alphanohtml') != '' ? GETPOST("tjm", 'alphanohtml') : ''; - $object->tjm = price2num($object->tjm); - $object->salary = GETPOST("salary", 'alphanohtml') != '' ? GETPOST("salary", 'alphanohtml') : ''; - $object->salary = price2num($object->salary); - $object->salaryextra = GETPOST("salaryextra", 'alphanohtml') != '' ? GETPOST("salaryextra", 'alphanohtml') : ''; - $object->weeklyhours = GETPOST("weeklyhours", 'alphanohtml') != '' ? GETPOST("weeklyhours", 'alphanohtml') : ''; + // Only users allowed to see salary/HR fields can modify them (issue #32909) + if ($permissiontoeditsalary) { + $object->thm = GETPOST("thm", 'alphanohtml') != '' ? GETPOST("thm", 'alphanohtml') : ''; + $object->thm = price2num($object->thm); + $object->tjm = GETPOST("tjm", 'alphanohtml') != '' ? GETPOST("tjm", 'alphanohtml') : ''; + $object->tjm = price2num($object->tjm); + $object->salary = GETPOST("salary", 'alphanohtml') != '' ? GETPOST("salary", 'alphanohtml') : ''; + $object->salary = price2num($object->salary); + $object->salaryextra = GETPOST("salaryextra", 'alphanohtml') != '' ? GETPOST("salaryextra", 'alphanohtml') : ''; + $object->weeklyhours = GETPOST("weeklyhours", 'alphanohtml') != '' ? GETPOST("weeklyhours", 'alphanohtml') : ''; + } $object->color = GETPOST("color", 'alphanohtml') != '' ? GETPOST("color", 'alphanohtml') : ''; @@ -524,16 +530,19 @@ if (empty($reshook)) { $object->fk_user_holiday_validator = GETPOSTINT("fk_user_holiday_validator") > 0 ? GETPOSTINT("fk_user_holiday_validator") : 0; $object->employee = GETPOSTINT('employee'); - $object->thm = GETPOST("thm", 'alphanohtml') != '' ? GETPOST("thm", 'alphanohtml') : ''; - $object->thm = price2num($object->thm); - $object->tjm = GETPOST("tjm", 'alphanohtml') != '' ? GETPOST("tjm", 'alphanohtml') : ''; - $object->tjm = price2num($object->tjm); - $object->salary = GETPOST("salary", 'alphanohtml') != '' ? GETPOST("salary", 'alphanohtml') : ''; - $object->salary = price2num($object->salary); - $object->salaryextra = GETPOST("salaryextra", 'alphanohtml') != '' ? GETPOST("salaryextra", 'alphanohtml') : ''; - $object->salaryextra = price2num($object->salaryextra); - $object->weeklyhours = GETPOST("weeklyhours", 'alphanohtml') != '' ? GETPOST("weeklyhours", 'alphanohtml') : ''; - $object->weeklyhours = price2num($object->weeklyhours); + // Only users allowed to see salary/HR fields can modify them (issue #32909) + if ($permissiontoeditsalary) { + $object->thm = GETPOST("thm", 'alphanohtml') != '' ? GETPOST("thm", 'alphanohtml') : ''; + $object->thm = price2num($object->thm); + $object->tjm = GETPOST("tjm", 'alphanohtml') != '' ? GETPOST("tjm", 'alphanohtml') : ''; + $object->tjm = price2num($object->tjm); + $object->salary = GETPOST("salary", 'alphanohtml') != '' ? GETPOST("salary", 'alphanohtml') : ''; + $object->salary = price2num($object->salary); + $object->salaryextra = GETPOST("salaryextra", 'alphanohtml') != '' ? GETPOST("salaryextra", 'alphanohtml') : ''; + $object->salaryextra = price2num($object->salaryextra); + $object->weeklyhours = GETPOST("weeklyhours", 'alphanohtml') != '' ? GETPOST("weeklyhours", 'alphanohtml') : ''; + $object->weeklyhours = price2num($object->weeklyhours); + } $object->color = GETPOST("color", 'alphanohtml') != '' ? GETPOST("color", 'alphanohtml') : ''; $object->dateemployment = $dateemployment; From 5bb3714ef718f740373c4e8a352e7df70ea129ee Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 Jul 2026 12:39:23 +0200 Subject: [PATCH 11/11] Fix: use the same condition everywhere --- htdocs/user/card.php | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index da29cd14f57..a23f6286d32 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -161,8 +161,12 @@ if ($id > 0) { $permissiontoeditpasswordandsend = ((($user->id == $id) && $user->hasRight("user", "self", "password")) || (($user->id != $id) && $user->hasRight("user", "user", "password")))&& (empty($user->socid) || $user->socid == $object->socid); } -// Salary and other HR fields must only be editable by users allowed to see them (same rights as the display, see issue #32909) -$permissiontoeditsalary = ((isModEnabled('salaries') && $user->hasRight("salaries", "read") && in_array($id, $childids)) || (isModEnabled('salaries') && $user->hasRight("salaries", "readall")) || (isModEnabled('hrm') && $user->hasRight("hrm", "employee", "read"))); +// Permission to read salary and hourly rate +$permissiontoseesalary = (empty($user->socid) && ( + (isModEnabled('salaries') && $user->hasRight("salaries", "read") && ($id == 0 || in_array($id, $childids))) // If user is a manager of employee + || (isModEnabled('salaries') && $user->hasRight("salaries", "readall")) + || (isModEnabled('hrm') && $user->hasRight("hrm", "employee", "read"))) + || (!isModEnabled('salaries') && !isModEnabled('hrm') && ($id == 0 || in_array($id, $childids)))); $passwordismodified = false; $ldap = null; @@ -337,7 +341,7 @@ if (empty($reshook)) { $object->employee = GETPOSTINT('employee'); // Only users allowed to see salary/HR fields can modify them (issue #32909) - if ($permissiontoeditsalary) { + if ($permissiontoseesalary) { $object->thm = GETPOST("thm", 'alphanohtml') != '' ? GETPOST("thm", 'alphanohtml') : ''; $object->thm = price2num($object->thm); $object->tjm = GETPOST("tjm", 'alphanohtml') != '' ? GETPOST("tjm", 'alphanohtml') : ''; @@ -531,7 +535,7 @@ if (empty($reshook)) { $object->employee = GETPOSTINT('employee'); // Only users allowed to see salary/HR fields can modify them (issue #32909) - if ($permissiontoeditsalary) { + if ($permissiontoseesalary) { $object->thm = GETPOST("thm", 'alphanohtml') != '' ? GETPOST("thm", 'alphanohtml') : ''; $object->thm = price2num($object->thm); $object->tjm = GETPOST("tjm", 'alphanohtml') != '' ? GETPOST("tjm", 'alphanohtml') : ''; @@ -1484,9 +1488,7 @@ if ($action == 'create' || $action == 'adduserldap') { print ''; print ''; - if ((isModEnabled('salaries') && $user->hasRight("salaries", "read") && in_array($id, $childids)) - || (isModEnabled('salaries') && $user->hasRight("salaries", "readall")) - || (isModEnabled('hrm') && $user->hasRight("hrm", "employee", "read"))) { + if ($permissiontoseesalary) { $langs->load("salaries"); // THM @@ -1810,9 +1812,7 @@ if ($action == 'create' || $action == 'adduserldap') { print "\n"; // Sensitive salary/value information - if ((empty($user->socid) && in_array($id, $childids)) // A user can always see salary/value information for its subordinates - || (isModEnabled('salaries') && $user->hasRight("salaries", "readall")) - || (isModEnabled('hrm') && $user->hasRight("hrm", "employee", "read"))) { + if ($permissiontoseesalary) { $langs->load("salaries"); // Salary @@ -3027,9 +3027,7 @@ if ($action == 'create' || $action == 'adduserldap') { print "\n"; // Sensitive salary/value information - if ((empty($user->socid) && in_array($id, $childids)) // A user can always see salary/value information for its subordinates - || (isModEnabled('salaries') && $user->hasRight("salaries", "readall")) - || (isModEnabled('hrm') && $user->hasRight("hrm", "employee", "read"))) { + if ($permissiontoseesalary) { $langs->load("salaries"); // Salary