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

Conflicts:
	ChangeLog
	htdocs/compta/facture/list.php
	htdocs/product/stock/movement_list.php
This commit is contained in:
Laurent Destailleur 2022-01-06 11:15:28 +01:00
commit 1e467c60f3
7 changed files with 107 additions and 29 deletions

View File

@ -135,7 +135,7 @@ NEW: we need to be able to put more filters on deleteByParentField() function
NEW: make it easier to set the `keyword`, `keywords` and `description` attributes of an ecm file object NEW: make it easier to set the `keyword`, `keywords` and `description` attributes of an ecm file object
NEW: Experimental feature to manage user sessions in database NEW: Experimental feature to manage user sessions in database
NEW: Hidden option API_DISABLE_COMPRESSION is now visible in API setup page. NEW: Hidden option API_DISABLE_COMPRESSION is now visible in API setup page.
NEW: Add hook printUnderHeaderPDFline on invoice PDF templates (can be used for example to add a barcode or more information on header of invoices).
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
* Update hook 'printOriginObjectLine', removed check on product type and special code. Need now reshook. * Update hook 'printOriginObjectLine', removed check on product type and special code. Need now reshook.
@ -152,6 +152,41 @@ Following changes may create regressions for some external modules, but were nec
you can use hook 'setLinkedObjectSourceTargetType' to set your usual targettype you can use hook 'setLinkedObjectSourceTargetType' to set your usual targettype
***** ChangeLog for 14.0.5 compared to 14.0.4 *****
FIX: 13.0: printFieldListWhere called twice on same query
FIX: 14.0.4 fatal error on cron list.
FIX: #19476
FIX: #19564
FIX: #19651
FIX: Accountancy - SQL error on subledger account search in journal
FIX: apply eldy's suggestion to not overwrite existing extrafields of $line
FIX: Can't close a down payment if paid with credit notes.
FIX: better compatibility with multicompany
FIX: contact card: bad colspan value for separator extrafield in creation/modification form
FIX: discounts are applied both when fetching the best supplier price and when displaying it
FIX: double display for contact categorie on societe create card
FIX: fatal error on cron list.
FIX: holiday list: only mass delete if leave request is not in draft, canceled or refused, like in card
FIX: holiday mass deletion: correct return of record deleted
FIX: Holiday month report
FIX: info tab on customer invoice record not found
FIX: line extrafields are inoperative in dispatch cards even when they exist
FIX: list of categories in stats of supplier invoices
FIX: missing default value for more comprehensive
FIX: multicurrency: fields in discount unitialized when creating deposit
FIX: Navigation on bank transaction list
FIX: Can't edit a bank transaction due to bad permission check.
FIX: Option MAIN_DIRECT_STATUS_UPDATE broken. Ajax on/off not saving value in DB after updating to version >=12
FIX: postgresql compatibility, "" as is not authorized
FIX: printFieldListWhere called twice (at different locations) for the same SQL query, can result in syntax errors
FIX: select too large into addrights (pb of missing parenthesis)
FIX: set optional from post, we can't untick boolean field on product card
FIX: Take into consideration work leave over serveral months
FIX: test if method exist on wrong object
FIX: title for nature of third party in company list
FIX: Urgent onglet contact inaccessible depuis une facture
FIX: wrong syntax of sql request
***** ChangeLog for 14.0.4 compared to 14.0.3 ***** ***** ChangeLog for 14.0.4 compared to 14.0.3 *****

View File

@ -119,9 +119,9 @@ if (dol_is_file($xmlfile)) {
print '<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).'">'; print '<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).'">';
print '<br>'; print '<br>';
} else { } else {
print '<input type="radio" name="target" value="local"> '.$langs->trans("LocalSignature").' = '; print '<input type="radio" name="target" id="checkboxlocal" value="local"> <label for="checkboxlocal">'.$langs->trans("LocalSignature").' = ';
print '<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).'">'; print '<input name="xmlshortfile" class="flat minwidth400" value="'.dol_escape_htmltag($xmlshortfile).'">';
print ' <span class="warning">('.$langs->trans("AvailableOnlyOnPackagedVersions").')</span>'; print ' <span class="warning">('.$langs->trans("AvailableOnlyOnPackagedVersions").')</span></label>';
print '<br>'; print '<br>';
} }
print '<!-- for a remote target=remote&xmlremote=... -->'."\n"; print '<!-- for a remote target=remote&xmlremote=... -->'."\n";
@ -129,7 +129,7 @@ if ($enableremotecheck) {
print '<input type="radio" name="target" id="checkboxremote" value="remote"'.(GETPOST('target') == 'remote' ? 'checked="checked"' : '').'> <label for="checkboxremote">'.$langs->trans("RemoteSignature").'</label> = '; print '<input type="radio" name="target" id="checkboxremote" value="remote"'.(GETPOST('target') == 'remote' ? 'checked="checked"' : '').'> <label for="checkboxremote">'.$langs->trans("RemoteSignature").'</label> = ';
print '<input name="xmlremote" class="flat minwidth500" value="'.dol_escape_htmltag($xmlremote).'"><br>'; print '<input name="xmlremote" class="flat minwidth500" value="'.dol_escape_htmltag($xmlremote).'"><br>';
} else { } else {
print '<input type="radio" name="target" value="remote" disabled="disabled"> '.$langs->trans("RemoteSignature").' = '.dol_escape_htmltag($xmlremote); print '<input type="radio" name="target" id="checkboxremote" value="remote" disabled="disabled"> '.$langs->trans("RemoteSignature").' = '.dol_escape_htmltag($xmlremote);
if (!GETPOST('xmlremote')) { if (!GETPOST('xmlremote')) {
print ' <span class="warning">('.$langs->trans("FeatureAvailableOnlyOnStable").')</span>'; print ' <span class="warning">('.$langs->trans("FeatureAvailableOnlyOnStable").')</span>';
} }

View File

@ -1736,7 +1736,7 @@ if ($resql) {
print '<td class="nobordernopadding nowraponall">'; print '<td class="nobordernopadding nowraponall">';
if ($contextpage == 'poslist') { if ($contextpage == 'poslist') {
print $obj->ref; print dol_escape_htmltag($obj->ref);
} else { } else {
print $facturestatic->getNomUrl(1, '', 200, 0, '', 0, 1); print $facturestatic->getNomUrl(1, '', 200, 0, '', 0, 1);
} }
@ -1758,7 +1758,7 @@ if ($resql) {
// Customer ref // Customer ref
if (!empty($arrayfields['f.ref_client']['checked'])) { if (!empty($arrayfields['f.ref_client']['checked'])) {
print '<td class="nowrap tdoverflowmax200">'; print '<td class="nowrap tdoverflowmax200">';
print $obj->ref_client; print dol_escape_htmltag($obj->ref_client);
print '</td>'; print '</td>';
if (!$i) { if (!$i) {
$totalarray['nbfield']++; $totalarray['nbfield']++;
@ -1823,7 +1823,7 @@ if ($resql) {
if (!empty($arrayfields['p.title']['checked'])) { if (!empty($arrayfields['p.title']['checked'])) {
print '<td class="nowraponall">'; print '<td class="nowraponall">';
if ($obj->project_id > 0) { if ($obj->project_id > 0) {
print $projectstatic->title; print dol_escape_htmltag($projectstatic->title);
} }
print '</td>'; print '</td>';
if (!$i) { if (!$i) {
@ -1835,9 +1835,9 @@ if ($resql) {
if (!empty($arrayfields['s.nom']['checked'])) { if (!empty($arrayfields['s.nom']['checked'])) {
print '<td class="tdoverflowmax200">'; print '<td class="tdoverflowmax200">';
if ($contextpage == 'poslist') { if ($contextpage == 'poslist') {
print $companystatic->name; print dol_escape_htmltag($companystatic->name);
} else { } else {
print $companystatic->getNomUrl(1, 'customer'); print $companystatic->getNomUrl(1, 'customer', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1);
} }
print '</td>'; print '</td>';
if (!$i) { if (!$i) {
@ -1846,8 +1846,8 @@ if ($resql) {
} }
// Alias // Alias
if (!empty($arrayfields['s.name_alias']['checked'])) { if (!empty($arrayfields['s.name_alias']['checked'])) {
print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag((!empty($obj->name_alias)) ? $obj->name_alias : '').'">'; print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($companystatic->name_alias).'">';
print dol_escape_htmltag((!empty($obj->name_alias) ? $obj->name_alias : '')); print dol_escape_htmltag($companystatic->name_alias);
print '</td>'; print '</td>';
if (!$i) { if (!$i) {
$totalarray['nbfield']++; $totalarray['nbfield']++;
@ -1903,10 +1903,10 @@ if ($resql) {
// Staff // Staff
if (!empty($arrayfields['staff.code']['checked'])) { if (!empty($arrayfields['staff.code']['checked'])) {
print '<td class="center">'; print '<td class="center">';
if (!is_array($staffArray) || count($staffArray) == 0) { if (!is_array($conf->cache['staff']) || count($conf->cache['staff']) == 0) {
$staffArray = $formcompany->effectif_array(1); $conf->cache['staff'] = $formcompany->effectif_array(1);
} }
print $staffArray[$obj->staff_code]; print $conf->cache['staff'][$obj->staff_code];
print '</td>'; print '</td>';
if (!$i) { if (!$i) {
$totalarray['nbfield']++; $totalarray['nbfield']++;
@ -1955,7 +1955,7 @@ if ($resql) {
// Amount HT // Amount HT
if (!empty($arrayfields['f.total_ht']['checked'])) { if (!empty($arrayfields['f.total_ht']['checked'])) {
print '<td class="right nowraponall amount">'.price($obj->total_ht)."</td>\n"; print '<td class="right nowraponall">'.price($obj->total_ht)."</td>\n";
if (!$i) { if (!$i) {
$totalarray['nbfield']++; $totalarray['nbfield']++;
} }
@ -2085,7 +2085,7 @@ if ($resql) {
} }
if (!empty($arrayfields['f.retained_warranty']['checked'])) { if (!empty($arrayfields['f.retained_warranty']['checked'])) {
print '<td align="right amount">'.(!empty($obj->retained_warranty) ?price($obj->retained_warranty).'%' : '&nbsp;').'</td>'; print '<td align="right">'.(!empty($obj->retained_warranty) ? price($obj->retained_warranty).'%' : '&nbsp;').'</td>';
} }
if (!empty($arrayfields['dynamount_payed']['checked'])) { if (!empty($arrayfields['dynamount_payed']['checked'])) {
@ -2116,7 +2116,7 @@ if ($resql) {
// Currency // Currency
if (!empty($arrayfields['f.multicurrency_code']['checked'])) { if (!empty($arrayfields['f.multicurrency_code']['checked'])) {
print '<td class="nowraponall">'.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."</td>\n"; print '<td class="nowraponall">'.dol_escape_htmltag($obj->multicurrency_code).' - '.$langs->trans('Currency'.$obj->multicurrency_code)."</td>\n";
if (!$i) { if (!$i) {
$totalarray['nbfield']++; $totalarray['nbfield']++;
} }
@ -2210,7 +2210,7 @@ if ($resql) {
print $hookmanager->resPrint; print $hookmanager->resPrint;
// Date creation // Date creation
if (!empty($arrayfields['f.datec']['checked'])) { if (!empty($arrayfields['f.datec']['checked'])) {
print '<td align="center" class="nowrap">'; print '<td class="nowrap center">';
print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
print '</td>'; print '</td>';
if (!$i) { if (!$i) {
@ -2219,7 +2219,7 @@ if ($resql) {
} }
// Date modification // Date modification
if (!empty($arrayfields['f.tms']['checked'])) { if (!empty($arrayfields['f.tms']['checked'])) {
print '<td align="center" class="nowrap">'; print '<td class="nowrap center">';
print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser');
print '</td>'; print '</td>';
if (!$i) { if (!$i) {
@ -2228,7 +2228,7 @@ if ($resql) {
} }
// Date closing // Date closing
if (!empty($arrayfields['f.date_closing']['checked'])) { if (!empty($arrayfields['f.date_closing']['checked'])) {
print '<td align="center" class="nowrap">'; print '<td class="nowrap center">';
print dol_print_date($db->jdate($obj->date_closing), 'dayhour', 'tzuser'); print dol_print_date($db->jdate($obj->date_closing), 'dayhour', 'tzuser');
print '</td>'; print '</td>';
if (!$i) { if (!$i) {

View File

@ -273,6 +273,7 @@ ErrorWrongFileName=Name of the file cannot have __SOMETHING__ in it
ErrorNotInDictionaryPaymentConditions=Not in Payment Terms Dictionary, please modify. ErrorNotInDictionaryPaymentConditions=Not in Payment Terms Dictionary, please modify.
ErrorIsNotADraft=%s is not a draft ErrorIsNotADraft=%s is not a draft
ErrorExecIdFailed=Can't execute command "id" ErrorExecIdFailed=Can't execute command "id"
ErrorBadCharIntoLoginName=Unauthorized character in the login name
# Warnings # Warnings
WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup.

View File

@ -1,5 +1,6 @@
<?php <?php
/* Copyright (C) 2019 Laurent Destailleur <eldy@users.sourceforge.net> /* Copyright (C) 2019 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2022 Ferran Marcet <fmarcet@2byte.es>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -155,6 +156,9 @@ if ($permissiontoupdatecost) {
$arrayfields['m.price']['enabled'] = 1; $arrayfields['m.price']['enabled'] = 1;
} }
$arrayofselected = array();
/* /*
* Actions * Actions
*/ */
@ -798,10 +802,29 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
} }
$num = $db->num_rows($resql); $num = $db->num_rows($resql);
$totalarray = array();
$i = 0; $i = 0;
while ($i < ($limit ? min($num, $limit) : $num)) { while ($i < ($limit ? min($num, $limit) : $num)) {
$objp = $db->fetch_object($resql); $objp = $db->fetch_object($resql);
// Multilangs
if (!empty($conf->global->MAIN_MULTILANGS)) { // If multilang is enabled
// TODO Use a cache here
$sql = "SELECT label";
$sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
$sql .= " WHERE fk_product=".$objp->rowid;
$sql .= " AND lang='".$db->escape($langs->getDefaultLang())."'";
$sql .= " LIMIT 1";
$result = $db->query($sql);
if ($result) {
$objtp = $db->fetch_object($result);
if (!empty($objtp->label)) {
$objp->produit = $objtp->label;
}
}
}
$userstatic->id = $objp->fk_user_author; $userstatic->id = $objp->fk_user_author;
$userstatic->login = $objp->login; $userstatic->login = $objp->login;
$userstatic->lastname = $objp->lastname; $userstatic->lastname = $objp->lastname;
@ -835,7 +858,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
// Id movement // Id movement
if (!empty($arrayfields['m.rowid']['checked'])) { if (!empty($arrayfields['m.rowid']['checked'])) {
// This is primary not movement id // This is primary not movement id
print '<td>'.$objp->mid.'</td>'; print '<td>'.dol_escape_htmltag($objp->mid).'</td>';
} }
if (!empty($arrayfields['m.datem']['checked'])) { if (!empty($arrayfields['m.datem']['checked'])) {
// Date // Date
@ -858,7 +881,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
if ($productlot->id > 0) { if ($productlot->id > 0) {
print $productlot->getNomUrl(1); print $productlot->getNomUrl(1);
} else { } else {
print $productlot->batch; // the id may not be defined if movement was entered when lot was not saved or if lot was removed after movement. print dol_escape_htmltag($productlot->batch); // the id may not be defined if movement was entered when lot was not saved or if lot was removed after movement.
} }
print '</td>'; print '</td>';
} }
@ -884,13 +907,13 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
// Inventory code // Inventory code
print '<td>'; print '<td>';
//print '<a href="' . DOL_URL_ROOT . '/product/stock/movement_card.php' . '?id=' . $objp->entrepot_id . '&amp;search_inventorycode=' . $objp->inventorycode . '&amp;search_type_mouvement=' . $objp->type_mouvement . '">'; //print '<a href="' . DOL_URL_ROOT . '/product/stock/movement_card.php' . '?id=' . $objp->entrepot_id . '&amp;search_inventorycode=' . $objp->inventorycode . '&amp;search_type_mouvement=' . $objp->type_mouvement . '">';
print $objp->inventorycode; print dol_escape_htmltag($objp->inventorycode);
//print '</a>'; //print '</a>';
print '</td>'; print '</td>';
} }
if (!empty($arrayfields['m.label']['checked'])) { if (!empty($arrayfields['m.label']['checked'])) {
// Label of movement // Label of movement
print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($objp->label).'">'.$objp->label.'</td>'; print '<td class="tdoverflowmax300" title="'.dol_escape_htmltag($objp->label).'">'.dol_escape_htmltag($objp->label).'</td>';
} }
if (!empty($arrayfields['m.type_mouvement']['checked'])) { if (!empty($arrayfields['m.type_mouvement']['checked'])) {
// Type of movement // Type of movement
@ -911,7 +934,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
} }
if (!empty($arrayfields['origin']['checked'])) { if (!empty($arrayfields['origin']['checked'])) {
// Origin of movement // Origin of movement
print '<td class="nowraponall">'.$origin.'</td>'; print '<td class="nowraponall">'.dol_escape_htmltag($origin).'</td>';
} }
if (!empty($arrayfields['m.fk_projet']['checked'])) { if (!empty($arrayfields['m.fk_projet']['checked'])) {
// fk_project // fk_project

View File

@ -3,7 +3,7 @@
* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net> * Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com> * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2015 Juanjo Menent <jmenent@2byte.es> * Copyright (C) 2015 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es> * Copyright (C) 2018-2022 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr> * Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -1155,6 +1155,24 @@ while ($i < min($num, $limit)) {
$userstatic->email = $objp->user_email; $userstatic->email = $objp->user_email;
$userstatic->statut = $objp->user_status; $userstatic->statut = $objp->user_status;
// Multilangs
if (!empty($conf->global->MAIN_MULTILANGS)) { // If multilang is enabled
// TODO Use a cache
$sql = "SELECT label";
$sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
$sql .= " WHERE fk_product=".$objp->rowid;
$sql .= " AND lang='".$db->escape($langs->getDefaultLang())."'";
$sql .= " LIMIT 1";
$result = $db->query($sql);
if ($result) {
$objtp = $db->fetch_object($result);
if (!empty($objtp->label)) {
$objp->produit = $objtp->label;
}
}
}
$productstatic->id = $objp->rowid; $productstatic->id = $objp->rowid;
$productstatic->ref = $objp->product_ref; $productstatic->ref = $objp->product_ref;
$productstatic->label = $objp->produit; $productstatic->label = $objp->produit;

View File

@ -2518,9 +2518,10 @@ class Societe extends CommonObject
* @param int $maxlen Max length of name * @param int $maxlen Max length of name
* @param int $notooltip 1=Disable tooltip * @param int $notooltip 1=Disable tooltip
* @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
* @param int $noaliasinname 1=Do not add alias into the link ref
* @return string String with URL * @return string String with URL
*/ */
public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $save_lastsearch_value = -1) public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $save_lastsearch_value = -1, $noaliasinname = 0)
{ {
global $conf, $langs, $hookmanager; global $conf, $langs, $hookmanager;
@ -2558,7 +2559,7 @@ class Societe extends CommonObject
} }
} }
if (!empty($this->name_alias)) { if (!empty($this->name_alias) && empty($noaliasinname)) {
$name .= ' ('.$this->name_alias.')'; $name .= ' ('.$this->name_alias.')';
} }