Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into

develop
This commit is contained in:
Laurent Destailleur 2025-11-12 22:02:50 +01:00
commit 34bd3f5755
16 changed files with 100 additions and 83 deletions

View file

@ -998,66 +998,67 @@ class Categorie extends CommonObject
$objs = array();
$classnameforobj = $this->MAP_OBJ_CLASS[$type];
$obj = new $classnameforobj($this->db);
if (!empty($classnameforobj) && class_exists($classnameforobj)) {
$obj = new $classnameforobj($this->db);
$sql = "SELECT c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." as fk_object";
$sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as c";
$sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." as o";
if (!empty($filterlang)) {
$sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])."_lang as ol";
}
$sql .= " WHERE o.entity IN (".getEntity($obj->element).")";
$sql .= " AND c.fk_categorie = ".((int) $this->id);
// Compatibility with actioncomm table which has id instead of rowid
if ((array_key_exists($type, $this->MAP_OBJ_TABLE) && $this->MAP_OBJ_TABLE[$type] == "actioncomm") || $type == "actioncomm") {
$sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.id";
} else {
$sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.rowid";
}
if (!empty($filterlang)) {
$sql .= " AND ol.fk_".(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." = o.rowid";
$sql .= " AND ol.lang = '".$this->db->escape($filterlang)."'";
}
// Protection for external users
if (($type == 'customer' || $type == 'supplier') && $user->socid > 0) {
$sql .= " AND o.rowid = ".((int) $user->socid);
}
$sql = "SELECT c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." as fk_object";
$sql .= " FROM ".MAIN_DB_PREFIX."categorie_".(empty($this->MAP_CAT_TABLE[$type]) ? $type : $this->MAP_CAT_TABLE[$type])." as c";
$sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." as o";
if (!empty($filterlang)) {
$sql .= ", ".MAIN_DB_PREFIX.(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])."_lang as ol";
}
$sql .= " WHERE o.entity IN (".getEntity($obj->element).")";
$sql .= " AND c.fk_categorie = ".((int) $this->id);
// Compatibility with actioncomm table which has id instead of rowid
if ((array_key_exists($type, $this->MAP_OBJ_TABLE) && $this->MAP_OBJ_TABLE[$type] == "actioncomm") || $type == "actioncomm") {
$sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.id";
} else {
$sql .= " AND c.fk_".(empty($this->MAP_CAT_FK[$type]) ? $type : $this->MAP_CAT_FK[$type])." = o.rowid";
}
if (!empty($filterlang)) {
$sql .= " AND ol.fk_".(empty($this->MAP_OBJ_TABLE[$type]) ? $type : $this->MAP_OBJ_TABLE[$type])." = o.rowid";
$sql .= " AND ol.lang = '".$this->db->escape($filterlang)."'";
}
// Protection for external users
if (($type == 'customer' || $type == 'supplier') && $user->socid > 0) {
$sql .= " AND o.rowid = ".((int) $user->socid);
}
$errormessage = '';
$sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
if ($errormessage) {
$this->errors[] = $errormessage;
dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
return -1;
}
$errormessage = '';
$sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
if ($errormessage) {
$this->errors[] = $errormessage;
dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
return -1;
}
$sql .= $this->db->order($sortfield, $sortorder);
if ($limit > 0 || $offset > 0) {
$sql .= $this->db->plimit($limit + 1, $offset);
}
$sql .= $this->db->order($sortfield, $sortorder);
if ($limit > 0 || $offset > 0) {
$sql .= $this->db->plimit($limit + 1, $offset);
}
dol_syslog(get_class($this)."::getObjectsInCateg", LOG_DEBUG);
dol_syslog(get_class($this)."::getObjectsInCateg", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
while ($rec = $this->db->fetch_array($resql)) {
if ($onlyids) {
$objs[] = $rec['fk_object'];
} else {
$classnameforobj = $this->MAP_OBJ_CLASS[$type];
$obj = new $classnameforobj($this->db);
$obj->fetch($rec['fk_object']);
if ($obj->id > 0) { // Failing fetch may happen for example when a category supplier was set and third party was moved as customer only. The object supplier can't be loaded.
$objs[] = $obj;
$resql = $this->db->query($sql);
if ($resql) {
while ($rec = $this->db->fetch_array($resql)) {
if ($onlyids) {
$objs[] = $rec['fk_object'];
} else {
$obj->id = 0;
$obj->fetch($rec['fk_object']);
if ($obj->id > 0) { // Failing fetch may happen for example when a category supplier was set and third party was moved as customer only. The object supplier can't be loaded.
$objs[] = $obj;
}
}
}
} else {
$this->error = $this->db->error().' sql='.$sql;
return -1;
}
return $objs;
} else {
$this->error = $this->db->error().' sql='.$sql;
return -1;
}
return $objs;
}
/**

View file

@ -3694,8 +3694,7 @@ class Commande extends CommonOrder
$response->nbtodo++;
$response->total += $obj->total_ht;
$generic_commande->statut = $obj->fk_statut;
$generic_commande->date_commande = $this->db->jdate($obj->date_commande);
$generic_commande->status = $obj->fk_statut;
$generic_commande->date = $this->db->jdate($obj->date_commande);
$generic_commande->delivery_date = $this->db->jdate($obj->delivery_date);

View file

@ -2624,9 +2624,12 @@ while ($i < $imaxinloop) {
if (!is_array($typenArray) || count($typenArray) == 0) {
$typenArray = $formcompany->typent_array(1);
}
print '<td class="center tdoverflowmax100" title="'.dolPrintHTMLForAttribute($typenArray[$obj->typent_code]).'">';
if (!empty($obj->typent_code)) {
print '<td class="center tdoverflowmax100" title="'.dolPrintHTMLForAttribute($typenArray[$obj->typent_code]).'">';
print $typenArray[$obj->typent_code];
} else {
print '<td class="center tdoverflowmax100">';
print '';
}
print '</td>';
if (!$i) {

View file

@ -9203,6 +9203,8 @@ class Form
if ($tmpfieldstoshow) {
$fieldstoshow = $tmpfieldstoshow;
}
} elseif ($objecttmp->element === 'category') {
$fieldstoshow = 't.label';
} else {
// For backward compatibility
$objecttmp->fields['ref'] = array('type' => 'varchar(30)', 'label' => 'Ref', 'enabled' => 1, 'position' => 10, 'visible' => 4, 'showoncombobox' => 1);
@ -9236,7 +9238,11 @@ class Form
// Search data
$sql = "SELECT t.rowid, " . $fieldstoshow . " FROM " . $this->db->prefix() . $this->db->sanitize($objecttmp->table_element) . " as t";
if (!empty($objecttmp->isextrafieldmanaged)) {
$sql .= " LEFT JOIN " . $this->db->prefix() . $this->db->sanitize($objecttmp->table_element) . "_extrafields as e ON t.rowid = e.fk_object";
$extrafieldTable = $objecttmp->table_element;
if ($extrafieldTable == 'categorie') {
$extrafieldTable = 'categories'; // For compatibility
}
$sql .= " LEFT JOIN " . $this->db->prefix() . $this->db->sanitize($extrafieldTable) . "_extrafields as e ON t.rowid = e.fk_object";
}
if (!empty($objecttmp->parent_element)) { // If parent_element is defined
'@phan-var-force CommonObjectLine $objecttmp';

View file

@ -293,7 +293,7 @@ if (empty($reshook) && !empty($object->table_element) && isset($extrafields->att
$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;
}
//TODO Improve element and rights detection
// TODO Improve element and rights detection
if ($action == 'edit_extras' && $permtoeditextrafield && GETPOST('attribute', 'restricthtml') == $tmpkeyextra) {
// Show the extrafield in create or edit mode
$fieldid = 'id';
@ -308,7 +308,7 @@ if (empty($reshook) && !empty($object->table_element) && isset($extrafields->att
print '<input type="hidden" name="page_y" value="">';
print $extrafields->showInputField($tmpkeyextra, $value, '', '', '', '', $object, $object->table_element);
print '<input type="submit" class="button reposition" value="'.dol_escape_htmltag($langs->trans('Modify')).'">';
print '<input type="submit" class="button reposition" value="'.dolPrintHTMLForAttribute($langs->trans('Modify')).'">';
print '</form>';
@ -320,10 +320,11 @@ if (empty($reshook) && !empty($object->table_element) && isset($extrafields->att
print $formai->getAjaxAICallFunction();
} else {
// Show the extrafield in view mode
//var_dump($tmpkeyextra.'-'.$value.'-'.$object->table_element);
print $extrafields->showOutputField($tmpkeyextra, $value, '', $object->table_element, null, $object);
print '<input type="hidden" value="' . $value . '" name="options_' . $tmpkeyextra . '" id="options_' . $tmpkeyextra . '"/>'; // it's needed when to get parent value when extra-field list depend on parent extra-field list
print '<input type="hidden" value="' . dolPrintHTMLForAttribute($value) . '" name="options_' . dol_escape_htmltag($tmpkeyextra) . '" id="options_' . dol_escape_htmltag($tmpkeyextra) . '"/>'; // it's needed when to get parent value when extra-field list depend on parent extra-field list
}
print '</td>';

View file

@ -468,7 +468,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers
$diff_array = array_diff_assoc($qtyordred, $qtyshipped);
if (count($diff_array) == 0) {
//No diff => mean everything is shipped
$ret = $order->setStatut(Commande::STATUS_CLOSED, $object->origin_id, $object->origin, 'ORDER_CLOSE');
$ret = $order->cloture($user);
if ($ret < 0) {
$this->setErrorsFromObject($order);
return $ret;

View file

@ -101,6 +101,7 @@ $search_array_options = $extrafields->getOptionalsFromPost($object->table_elemen
// Load object
include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'.
$upload_dir = $conf->eventorganization->multidir_output[isset($object->entity) ? $object->entity : 1];
if ($id > 0 || !empty($ref)) {
$upload_dir = $conf->eventorganization->multidir_output[$object->entity ? $object->entity : $conf->entity]."/conferenceorbooth/".get_exdir(0, 0, 0, 1, $object);
}
@ -111,7 +112,6 @@ $permissiontoadd = $user->hasRight('project', 'write'); // Used by the include o
$permissiontodelete = $user->hasRight('project', 'delete') || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT);
$permissionnote = $user->hasRight('project', 'write'); // Used by the include of actions_setnotes.inc.php
$permissiondellink = $user->hasRight('project', 'write'); // Used by the include of actions_dellink.inc.php
$upload_dir = $conf->eventorganization->multidir_output[isset($object->entity) ? $object->entity : 1];
// Security check
if ($user->socid > 0) {

View file

@ -159,7 +159,7 @@ $step = GETPOSTINT("step") ? GETPOSTINT("step") : 1;
$export_name = GETPOST("export_name", "alphanohtml");
$hexa = GETPOST("hexa", "alpha");
$exportmodelid = GETPOSTINT("exportmodelid");
$field = GETPOST("field", "alpha");
$field = (string) GETPOST("field", "alpha");
$objexport = new Export($db);
$objexport->load_arrays($user, $datatoexport);

View file

@ -1227,9 +1227,15 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') {
if (empty($include_users)) {
print img_warning().' '.$langs->trans("NobodyHasPermissionToValidateHolidays");
} else {
// Defined default approver (the forced approved of user or the supervisor if no forced value defined)
// Note: This use will be set only if the deinfed approvr has permission to approve so is inside include_users
// Defined default approver (the forced approver of edited user or the supervisor of user if no forced value defined)
// Note: This user will be set only if the defined approver has permission to approve so is inside include_users
$defaultselectuser = (empty($user->fk_user_holiday_validator) ? $user->fk_user : $user->fk_user_holiday_validator);
if ($fuserid != $user->id) {
$fuser = new User($db);
$fuser->fetch($fuserid);
$defaultselectuser = (empty($fuser->fk_user_holiday_validator) ? $fuser->fk_user : $fuser->fk_user_holiday_validator);
}
if (getDolGlobalString('HOLIDAY_DEFAULT_VALIDATOR')) {
$defaultselectuser = getDolGlobalString('HOLIDAY_DEFAULT_VALIDATOR'); // Can force default approver
}

View file

@ -94,9 +94,8 @@ ALTER TABLE llx_product DROP FOREIGN KEY fk_product_default_warehouse;
DROP TABLE llx_contratdet_log;
ALTER TABLE llx_societe_rib MODIFY COLUMN iban_prefix varchar(80);
ALTER TABLE llx_bank_account MODIFY COLUMN iban_prefix varchar(80);
ALTER TABLE llx_user_rib MODIFY COLUMN iban_prefix varchar(80);
ALTER TABLE llx_bank_account MODIFY COLUMN iban_prefix varchar(100);
ALTER TABLE llx_user_rib MODIFY COLUMN iban_prefix varchar(100);
ALTER TABLE llx_bom_bom ADD COLUMN last_main_doc varchar(255) AFTER model_pdf;

View file

@ -39,7 +39,7 @@ create table llx_bank_account
cle_rib varchar(5),
bic varchar(11), -- 11 according to ISO 9362
bic_intermediate varchar(11), -- 11 according to ISO 9362. Same as bic but for intermediate bank
iban_prefix varchar(80), -- full iban. 34 according to ISO 13616 but we set 80 to allow to store it with encryption information
iban_prefix varchar(100), -- full iban. 34 according to ISO 13616 but we set 100 to allow to store it with encryption information
country_iban varchar(2), -- deprecated
cle_iban varchar(2),
domiciliation varchar(255),

View file

@ -31,7 +31,7 @@ create table llx_user_rib
cle_rib varchar(5), -- key of bank account
bic varchar(11), -- 11 according to ISO 9362
bic_intermediate varchar(11), -- 11 according to ISO 9362. Same as bic but for intermediate bank
iban_prefix varchar(80), -- full iban. 34 according to ISO 13616 but we set 80 to allow to store it with encryption information
iban_prefix varchar(100), -- full iban. 34 according to ISO 13616 but we set 100 to allow to store it with encryption information
domiciliation varchar(255),
proprio varchar(60),
owner_address varchar(255),

View file

@ -3280,7 +3280,8 @@ class Product extends CommonObject
if (!$resql) {
$this->error = $this->db->lasterror;
return -1;
} elseif ($result = $this->db->fetch_array($resql)) {
} else {
$result = $this->db->fetch_array($resql);
$this->multiprices[$i] = (!empty($result["price"]) ? $result["price"] : 0);
$this->multiprices_ttc[$i] = (!empty($result["price_ttc"]) ? $result["price_ttc"] : 0);
$this->multiprices_min[$i] = (!empty($result["price_min"]) ? $result["price_min"] : 0);

View file

@ -257,6 +257,7 @@ if (getDolGlobalInt('WEBPORTAL_LOGIN_BY_MODULE') && !empty($conf->modules_parts[
$logged_thirdparty = $websiteaccount->thirdparty;
if (!$logged_thirdparty || !($logged_thirdparty->id > 0)) {
$result = $websiteaccount->fetch_thirdparty();
if ($result < 0) {
$error_msg = $langs->transnoentitiesnoconv('WebPortalErrorFetchLoggedThirdParty', (string) $websiteaccount->fk_soc);
//dol_syslog("Can't load third-party (ID: ".$websiteaccount->fk_soc.") even if session logged.", LOG_ERR);
@ -279,7 +280,7 @@ if (getDolGlobalInt('WEBPORTAL_LOGIN_BY_MODULE') && !empty($conf->modules_parts[
$context->setEventMessage($error_msg, 'errors');
}
if (!$error && $logged_member->id > 0) {
if (isModEnabled('partnership') && !$error && $logged_member->id > 0) {
// get partnership
$logged_partnership = new WebPortalPartnership($db);
// @phan-suppress-next-line PhanPluginSuspiciousParamPosition

View file

@ -1492,13 +1492,13 @@ if ($reshook == 0) { //add buttons
$menus[$r++] = $butmenu;
}
}
} elseif ($reshook == 1) {
$r = 0; //replace buttons
if (is_array($hookmanager->resArray)) {
foreach ($hookmanager->resArray as $resArray) {
foreach ($resArray as $butmenu) {
$menus[$r++] = $butmenu;
}
}
} elseif ($reshook == 1) {
$r = 0; //replace buttons
if (is_array($hookmanager->resArray) ) {
foreach ($hookmanager->resArray as $resArray) {
foreach ($resArray as $butmenu) {
$menus[$r++] = $butmenu;
}
}
}

View file

@ -166,7 +166,7 @@ $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->tra
dol_banner_tab($object, 'id', $linkback, $user->hasRight('user', 'user', 'lire') || $user->admin, 'rowid', 'ref', $morehtmlref);
$object->info($id);
$object->info($object->id);
print '<div class="fichecenter">';
@ -188,10 +188,10 @@ $out = '';
$permok = $user->hasRight('agenda', 'myactions', 'create');
if ((!empty($objUser->id) || !empty($objcon->id)) && $permok) {
if (is_object($objUser) && get_class($objUser) == 'User') {
$out .= '&amp;originid='.$objUser->id.($objUser->id > 0 ? '&amp;userid='.$objUser->id : '').'&amp;backtopage='.urlencode($_SERVER['PHP_SELF'].($objUser->id > 0 ? '?userid='.$objUser->id : ''));
$out .= '&originid='.$objUser->id.($objUser->id > 0 ? '&userid='.$objUser->id : '').'&backtopage='.urlencode($_SERVER['PHP_SELF'].($objUser->id > 0 ? '?userid='.$objUser->id : ''));
}
$out .= (!empty($objcon->id) ? '&amp;contactid='.$objcon->id : '');
$out .= '&amp;datep='.dol_print_date(dol_now(), 'dayhourlog', 'tzuserrel');
$out .= (!empty($objcon->id) ? '&contactid='.$objcon->id : '');
$out .= '&datep='.dol_print_date(dol_now(), 'dayhourlog', 'tzuserrel');
}
$morehtmlright = '';
@ -209,7 +209,7 @@ if (isModEnabled('agenda')) {
if (isModEnabled('agenda') && ($user->hasRight('agenda', 'myactions', 'read') || $user->hasRight('agenda', 'allaactions', 'read'))) {
print '<br>';
$param = '&userid='.urlencode((string) ($id));
$param = '&userid='.urlencode((string) ($object->id));
if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
$param .= '&contextpage='.urlencode($contextpage);
}