From 30ecf8073217dd2b1a747e68c1047b630329b1e6 Mon Sep 17 00:00:00 2001 From: lvessiller-opendsi Date: Fri, 14 Nov 2025 15:53:31 +0100 Subject: [PATCH 1/9] FIX keep user who validate proposal on update (#36257) --- htdocs/comm/propal/class/propal.class.php | 13 +++++-------- htdocs/core/class/commonobject.class.php | 5 +++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index edd443c1b58..e09fb5f5e6e 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -183,7 +183,6 @@ class Propal extends CommonObject public $fin_validite; public $user_author_id; - public $user_valid_id; public $user_close_id; /** @@ -1369,7 +1368,7 @@ class Propal extends CommonObject // Clear fields $object->user_author = $user->id; - $object->user_valid = ''; + $object->user_validation_id = 0; $object->date = $now; $object->datep = $now; // deprecated $object->fin_validite = $object->date + ($object->duree_validite * 24 * 3600); @@ -1554,7 +1553,7 @@ class Propal extends CommonObject $this->extraparams = (array) json_decode($obj->extraparams, true); $this->user_author_id = $obj->fk_user_author; - $this->user_valid_id = $obj->fk_user_valid; + $this->user_validation_id = $obj->fk_user_valid; $this->user_close_id = $obj->fk_user_cloture; //Incoterms @@ -1656,7 +1655,7 @@ class Propal extends CommonObject $sql .= " total_ttc=".(isset($this->total_ttc) ? $this->total_ttc : "null").","; $sql .= " fk_statut=".(isset($this->statut) ? $this->statut : "null").","; $sql .= " fk_user_author=".(isset($this->user_author_id) ? $this->user_author_id : "null").","; - $sql .= " fk_user_valid=".(isset($this->user_valid) ? $this->user_valid : "null").","; + $sql .= " fk_user_valid = ".(!empty($this->user_validation_id) ? (int) $this->user_validation_id : "null").","; $sql .= " fk_projet=".(isset($this->fk_project) ? $this->fk_project : "null").","; $sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->cond_reglement_id : "null").","; $sql .= " fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->mode_reglement_id : "null").","; @@ -1942,7 +1941,7 @@ class Propal extends CommonObject $this->ref = $num; $this->brouillon = 0; $this->statut = self::STATUS_VALIDATED; - $this->user_valid_id = $user->id; + $this->user_validation_id = $user->id; $this->datev = $now; $this->db->commit(); @@ -3199,9 +3198,7 @@ class Propal extends CommonObject $this->user_creation = $cuser; if ($obj->fk_user_valid) { - $vuser = new User($this->db); - $vuser->fetch($obj->fk_user_valid); - $this->user_validation = $vuser; + $this->user_validation_id = $obj->fk_user_valid; } if ($obj->fk_user_signature) { diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index dc5b3f72aad..59b5ec6c658 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -481,6 +481,11 @@ abstract class CommonObject */ public $date_modification; // Date last change (tms field) + /** + * @var int|null User id of validation + */ + public $user_validation_id; + public $next_prev_filter; /** From 1adf4ce67fecb89428496efa380257e6a4b2d3d6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 20 Nov 2025 15:13:52 +0100 Subject: [PATCH 2/9] Fix CI --- htdocs/emailcollector/lib/emailcollector.lib.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/emailcollector/lib/emailcollector.lib.php b/htdocs/emailcollector/lib/emailcollector.lib.php index eef737cfc86..5211bc811df 100644 --- a/htdocs/emailcollector/lib/emailcollector.lib.php +++ b/htdocs/emailcollector/lib/emailcollector.lib.php @@ -115,7 +115,6 @@ function getDParameters($part) * @param object $mbox object connection imaap * @return array type, filename, pos */ - function getAttachments($jk, $mbox) { $structure = imap_fetchstructure($mbox, $jk, FT_UID); // @phan-suppress-current-line PhanTypeMismatchArgumentInternal $parts = getParts($structure); From f32386208d9f7a74753557006ca079f486d44a30 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 20 Nov 2025 15:14:09 +0100 Subject: [PATCH 3/9] Fix CI --- htdocs/emailcollector/lib/emailcollector.lib.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/emailcollector/lib/emailcollector.lib.php b/htdocs/emailcollector/lib/emailcollector.lib.php index 5211bc811df..598d6611975 100644 --- a/htdocs/emailcollector/lib/emailcollector.lib.php +++ b/htdocs/emailcollector/lib/emailcollector.lib.php @@ -115,7 +115,8 @@ function getDParameters($part) * @param object $mbox object connection imaap * @return array type, filename, pos */ -function getAttachments($jk, $mbox) { +function getAttachments($jk, $mbox) +{ $structure = imap_fetchstructure($mbox, $jk, FT_UID); // @phan-suppress-current-line PhanTypeMismatchArgumentInternal $parts = getParts($structure); $fpos = 2; From 70f5e20572cb002c72f04f2bc9426b52df918b37 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Thu, 20 Nov 2025 15:16:04 +0100 Subject: [PATCH 4/9] Fix CI --- .../core/triggers/interface_50_modTicket_TicketEmail.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php index 00672fe7fd4..1709955673d 100644 --- a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php +++ b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php @@ -379,7 +379,7 @@ class InterfaceTicketEmail extends DolibarrTriggers $message = dol_nl2br($message); } $message_customer .= '

'.$langs->trans('Message').' :

'.$message.'


'; - if (getDolGlobalInt('TICKET_ENABLE_PUBLIC_INTERFACE')){ + if (getDolGlobalInt('TICKET_ENABLE_PUBLIC_INTERFACE')) { $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id; $message_customer .= '

'.$langs->trans($see_ticket).' : '.$url_public_ticket.'

'; $message_customer .= '

'.$langs->trans('TicketEmailPleaseDoNotReplyToThisEmail').'

'; From 9e8460c3dc4aacc2c76f348fe673f372c8366dc0 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Thu, 20 Nov 2025 15:16:04 +0100 Subject: [PATCH 5/9] Fix CI --- .../core/triggers/interface_50_modTicket_TicketEmail.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php index 95600161561..096b2b8279a 100644 --- a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php +++ b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php @@ -379,7 +379,7 @@ class InterfaceTicketEmail extends DolibarrTriggers $message = dol_nl2br($message); } $message_customer .= '

'.$langs->trans('Message').' :

'.$message.'


'; - if (getDolGlobalInt('TICKET_ENABLE_PUBLIC_INTERFACE')){ + if (getDolGlobalInt('TICKET_ENABLE_PUBLIC_INTERFACE')) { $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id; $message_customer .= '

'.$langs->trans($see_ticket).' : '.$url_public_ticket.'

'; $message_customer .= '

'.$langs->trans('TicketEmailPleaseDoNotReplyToThisEmail').'

'; From c8acd48e34044bdf4d90ecb73250702207e22b8a Mon Sep 17 00:00:00 2001 From: Eric - CAP-REL <1468823+rycks@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:58:15 +0100 Subject: [PATCH 6/9] setErrors does not exists, same solution as dolibarr v19.0 (#36107) * setErrors does not exists, same solution as dolibarr v19.0 * reload ci * reload ci 2 --------- Co-authored-by: Laurent Destailleur Co-authored-by: lvessiller-opendsi --- htdocs/core/class/html.formsetup.class.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 03b9695b18f..cbd0111e099 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -80,6 +80,10 @@ class FormSetup */ public $formHiddenInputs = array(); + /** + * @var string[] $errors + */ + public $errors = array(); /** * Constructor @@ -253,10 +257,9 @@ class FormSetup $parameters = array(); $reshook = $hookmanager->executeHooks('formSetupBeforeSaveConfFromPost', $parameters, $this); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->setErrors($hookmanager->errors); + $this->errors = $hookmanager->errors; return -1; } - if ($reshook > 0) { return $reshook; } From 0e1ac03fb0de9062f47eb29a0bf46e8be27ed819 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Fri, 21 Nov 2025 11:15:34 +0100 Subject: [PATCH 7/9] FIX #36347 (#36358) --- htdocs/compta/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index c372ab72026..675f82c1179 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2526,7 +2526,7 @@ if (empty($reshook)) { } // Insert line - $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $date_start, $date_end, 0, $info_bits, 0, $price_base_type, $pu_ttc, $type, min($rank, count($object->lines) + 1), $special_code, '', 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, GETPOSTINT('progress'), 0, $fk_unit, $pu_ht_devise); + $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $date_start, $date_end, 0, $info_bits, 0, $price_base_type, $pu_ttc, $type, min($rank, count($object->lines) + 1), $special_code, '', 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, GETPOST('progress'), 0, $fk_unit, $pu_ht_devise); if ($result > 0) { // Define output language and generate document From 0e8d4461c4fafe5dba2646963f3440cc1ae09eba Mon Sep 17 00:00:00 2001 From: iLLixM <162678117+iLLixM@users.noreply.github.com> Date: Fri, 21 Nov 2025 18:34:24 +0100 Subject: [PATCH 8/9] Fix: Prevent negative payment amount in EPC-QR Code (#36364) --- htdocs/core/class/commoninvoice.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index d1adb0d9fce..50c56f07f99 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -1669,6 +1669,9 @@ abstract class CommonInvoice extends CommonObject $amount_to_pay = $this->total_ttc; } + // Prevent negative values (e.g. overpayments) + $amount_to_pay = max(0, $amount_to_pay); + // Ensure numeric formatting for EPC QR code $amount_to_pay = price2num($amount_to_pay, 'MT'); From 5a61cc9393234ced3632dbf7341eda8844162fd9 Mon Sep 17 00:00:00 2001 From: Florian Mortgat <50440633+atm-florianm@users.noreply.github.com> Date: Mon, 24 Nov 2025 14:57:20 +0100 Subject: [PATCH 9/9] FIX DA027383: permissions not checked on HRM evaluation card (#36328) (#36399) Permissions involved: - hrm->evaluation->readall: the user can view anyone's evaluations - hrm->evaluation->read: the user can only view their or their subordinates' evaluations --- htdocs/core/lib/security.lib.php | 20 +++++++++++++++++++- htdocs/hrm/evaluation_card.php | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index c29c0df7126..19768625ec1 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -401,6 +401,10 @@ function restrictedArea(User $user, $features, $object = 0, $tableandshare = '', $tableandshare = 'paiementcharge'; $parentfortableentity = 'fk_charge@chargesociales'; } + if ($features == 'evaluation') { + $features = 'hrm'; + $feature2 = 'evaluation'; + } // Get more permissions checks from hooks $parameters = array('features'=>$features, 'originalfeatures'=>$originalfeatures, 'objectid'=>$objectid, 'dbt_select'=>$dbt_select, 'idtype'=>$dbt_select, 'isdraft'=>$isdraft); @@ -834,7 +838,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl $checkother = array('contact', 'agenda', 'contrat'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...). $checkproject = array('projet', 'project'); // Test for project object $checktask = array('projet_task'); // Test for task object - $checkhierarchy = array('expensereport', 'holiday'); // check permission among the hierarchy of user + $checkhierarchy = array('expensereport', 'holiday', 'hrm'); // check permission among the hierarchy of user $checkuser = array('bookmark'); // check permission among the fk_user (must be myself or null) $nocheck = array('barcode', 'stock'); // No test @@ -1055,6 +1059,20 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl } } } + if ($feature == 'hrm' && in_array('evaluation', $feature2)) { + $useridtocheck = $object->fk_user; + + if ($user->hasRight('hrm', 'evaluation', 'readall')) { + // the user can view evaluations for anyone + return true; + } + if (!$user->hasRight('hrm', 'evaluation', 'read')) { + // the user can't view any evaluations + return false; + } + // the user can only their own evaluations or their subordinates' + return in_array($useridtocheck, $childids); + } } // For some object, we also have to check it is public or owned by user diff --git a/htdocs/hrm/evaluation_card.php b/htdocs/hrm/evaluation_card.php index e59ba7db462..97c77cbd76c 100644 --- a/htdocs/hrm/evaluation_card.php +++ b/htdocs/hrm/evaluation_card.php @@ -92,8 +92,8 @@ $upload_dir = $conf->hrm->multidir_output[isset($object->entity) ? $object->enti // Security check (enable the most restrictive one) //if ($user->socid > 0) accessforbidden(); //if ($user->socid > 0) $socid = $user->socid; -//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); -//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +$isdraft = ($object->status == Evaluation::STATUS_DRAFT) ? 1 : 0; +restrictedArea($user, $object->element, $object, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); if (!isModEnabled("hrm")) { accessforbidden(); }