diff --git a/ChangeLog b/ChangeLog index a5d8b7c967e..0458780eeab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -254,6 +254,44 @@ The following changes may create regressions for some external modules, but were * A very high number of class properties (with old name in french) are now deprecated in favor of the property name in english. +***** ChangeLog for 18.0.4 compared to 18.0.3 ***** +FIX: $this->newref already exists and could have been modified by trigger but we still use a local variable for the filesystem-based renaming +FIX: 16.0 only, backport fix for SQL error on global search product +FIX: #25399 (#26694) +FIX: #25458 intervention localizations (backport v17) (#26757) +FIX: #26518 +FIX: #26536 Accountancy - Balance - Not divided lines by label & account, only by account (#26547) +FIX: #26553 Supplier invoice - Do not display the delete button for reconciled payment (#26554) +FIX: #26735 +FIX: #26994 +FIX: Accountancy - Possibility to write in bookkeeping expense report operation with some line not bound (#26545) +FIX: add display of an error when attempting to delete a committed transaction (#26573) +FIX: avoid warning : Cannot use a scalar value as an array (#26437) +FIX: backport SQL error on global search product +FIX: # Bug Estimated Stock at date value in V14 (#26479) +FIX: commande context (#26497) +FIX: delivery note disappear after generation +FIX: double hook and paging search param in product list (#26767) +FIX: Email reminder template must not be visible when option is off +FIX: escape HTML tags in return value of getFullName() (#26735) +FIX: Fix set private note (#26610) +FIX: Fix when options FAC_FORCE_DATE_VALIDATION and INVOICE_CHECK_POSTERIOR_DATE enabled. The date is forced after the test and not before +FIX: menu auguria +FIX: pagination parameters on save and cancel buttons (#26605) +FIX: pdf cornas page head multicell width (backport v17) +FIX: php8 fatal on edit supplier order when multicurrency is activated (#26758) +FIX: possible inconsistency between llx_ecm_files and file system when BILL_SUPPLIER_VALIDATES changes ref +FIX: regression on planned bank entries (#26556) +FIX: Social contribution - Payment list - Wrong information in type column (#26561) +FIX: special_code update line keep old value. (#26819) +FIX: substitute project variables in invoice documents (#26445) +FIX: Test on permission for holiday tooltips +FIX: v17: Param $notrigger in $societe->create() causes method to return true regardless of actual result of database functions (#26499) +FIX: v18 SQL error in llx_c_forme_juridique.sql when installing +FIX: Warehouse Global Amounts not displayed (#26478) +FIX: warning param $lineID getSpecialCode is negatif (#26826) +FIX: warning php8.2 undefined_array_key (#26830) + ***** ChangeLog for 18.0.3 compared to 18.0.2 ***** FIX: #25793 Cannot add time spent (#26405) FIX: #26100 Ticket - On edit, list of closed project must be excluded (#26223) diff --git a/dev/initdata/purge-data.php b/dev/initdata/purge-data.php index d75c9fae8b2..442d991a453 100755 --- a/dev/initdata/purge-data.php +++ b/dev/initdata/purge-data.php @@ -148,8 +148,8 @@ $sqls=array( "DELETE FROM ".MAIN_DB_PREFIX."product where datec < '__DATE__'", ), 'project'=>array( - // TODO set fk_project to null on object that refer to project - "DELETE FROM ".MAIN_DB_PREFIX."projet_task_time WHERE fk_task IN (select rowid FROM ".MAIN_DB_PREFIX."projet_task WHERE fk_projet IN (select rowid FROM ".MAIN_DB_PREFIX."projet where datec < '__DATE__'))", + // TODO set fk_project to null on all objects/tables that refer to project + "DELETE FROM ".MAIN_DB_PREFIX."element_time WHERE elementtype = 'task' AND fk_element IN (select rowid FROM ".MAIN_DB_PREFIX."projet_task WHERE fk_projet IN (select rowid FROM ".MAIN_DB_PREFIX."projet where datec < '__DATE__'))", "DELETE FROM ".MAIN_DB_PREFIX."projet_task WHERE fk_projet IN (select rowid FROM ".MAIN_DB_PREFIX."projet where datec < '__DATE__')", "DELETE FROM ".MAIN_DB_PREFIX."projet where datec < '__DATE__'", ), diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index c92d0032176..245e011d6bc 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -84,6 +84,11 @@ if (($action == 'update' && !GETPOST("cancel", 'alpha')) $s = $mysoc->country_id.':'.$mysoc->country_code.':'.$mysoc->country_label; dolibarr_set_const($db, "MAIN_INFO_SOCIETE_COUNTRY", $s, 'chaine', 0, '', $conf->entity); + if($mysoc->country_code == 'FR' && !isset($conf->global->MAIN_PROFID1_IN_ADDRESS)){ + // For FR, default value of option to show profid SIREN is on by default + $res = dolibarr_set_const($db, "MAIN_PROFID1_IN_ADDRESS", 1, 'chaine', 0, '', $conf->entity); + } + activateModulesRequiredByCountry($mysoc->country_code); } diff --git a/htdocs/bom/class/api_boms.class.php b/htdocs/bom/class/api_boms.class.php index 4b9ccda6b09..658543e68c3 100644 --- a/htdocs/bom/class/api_boms.class.php +++ b/htdocs/bom/class/api_boms.class.php @@ -559,7 +559,7 @@ class Boms extends DolibarrApi * * @return void */ - private function checkRefNumbering(): void + private function checkRefNumbering() { $ref = substr($this->bom->ref, 1, 4); if ($this->bom->status > 0 && $ref == 'PROV') { diff --git a/htdocs/bom/tpl/linkedobjectblock.tpl.php b/htdocs/bom/tpl/linkedobjectblock.tpl.php index d00340a1322..082936be50a 100644 --- a/htdocs/bom/tpl/linkedobjectblock.tpl.php +++ b/htdocs/bom/tpl/linkedobjectblock.tpl.php @@ -62,7 +62,7 @@ foreach ($linkedObjectBlock as $key => $objectlink) { $product_static->getNomUrl(1); } print ''; - echo ''.dol_print_date($objectlink->date_creation, 'day').''; + echo ''.dol_print_date($objectlink->date_creation, 'day').''; echo ''; if ($user->hasRight('commande', 'lire')) { $total = $total + $objectlink->total_ht; diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 652f60552ff..5e403dff7a8 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -575,6 +575,7 @@ if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { /* The fast and low memory method to get and count full list converts the sql into a sql count */ $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); if ($resql) { $objforcount = $db->fetch_object($resql); diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 5b10b742d87..4ac22405287 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -701,6 +701,15 @@ class Account extends CommonObject } // Load librairies to check BAN + $balance = $this->balance; + if (empty($balance) && !empty($this->solde)) { + $balance = $this->solde; + } + if (empty($balance)) { + $balance = 0; + } + + // Load the library to validate/check a BAN account require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php'; $now = dol_now(); @@ -779,7 +788,7 @@ class Account extends CommonObject $accline = new AccountLine($this->db); $accline->datec = $now; $accline->label = '('.$langs->trans("InitialBankBalance").')'; - $accline->amount = price2num($this->solde); + $accline->amount = price2num($balance); $accline->fk_user_author = $user->id; $accline->fk_account = $this->id; $accline->datev = $this->date_solde; diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index d58a1cf15d4..055cede7593 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -925,6 +925,7 @@ if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { /* The fast and low memory method to get and count full list converts the sql into a sql count */ $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); if ($resql) { $objforcount = $db->fetch_object($resql); @@ -932,7 +933,7 @@ if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { } else { dol_print_error($db); } - + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 $page = 0; $offset = 0; diff --git a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php index 9e45515a15e..940a4f09a6d 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php @@ -6,6 +6,7 @@ * Copyright (C) 2015 Marcos García * Copyright (C) 2017 Ferran Marcet * Copyright (C) 2018-2022 Frédéric France + * Copyright (C) 2023 William Mead * * 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 @@ -1197,9 +1198,9 @@ class pdf_cornas extends ModelePDFSuppliersOrders $pdf->SetTextColor(0, 0, 60); $pdf->SetFont('', 'B', $default_font_size + 3); - $w = 100; + $w = 110; - $posx = $this->page_largeur - $this->marge_droite - 100; + $posx = $this->page_largeur - $this->marge_droite - $w; $posy = $this->marge_haute; $pdf->SetXY($this->marge_gauche, $posy); diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php index 98f5c15c5ce..87127b34010 100644 --- a/htdocs/fourn/class/api_supplier_invoices.class.php +++ b/htdocs/fourn/class/api_supplier_invoices.class.php @@ -235,7 +235,7 @@ class SupplierInvoices extends DolibarrApi } if ($this->invoice->create(DolibarrApiAccess::$user) < 0) { - throw new RestException(500, "Error creating order", array_merge(array($this->invoice->error), $this->invoice->errors)); + throw new RestException(500, "Error creating invoice ", array_merge(array($this->invoice->error), $this->invoice->errors)); } return $this->invoice->id; } diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 05f91cdb6af..65a00f8affc 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -1916,19 +1916,18 @@ class FactureFournisseur extends CommonInvoice // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments $oldref = dol_sanitizeFileName($this->ref); - $newref = dol_sanitizeFileName($num); $dirsource = $conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id, 2, 0, 0, $this, 'invoice_supplier').$oldref; - $dirdest = $conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id, 2, 0, 0, $this, 'invoice_supplier').$newref; + $dirdest = $conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id, 2, 0, 0, $this, 'invoice_supplier').$this->newref; if (!$error && file_exists($dirsource)) { dol_syslog(get_class($this)."::validate rename dir ".$dirsource." into ".$dirdest); if (@rename($dirsource, $dirdest)) { dol_syslog("Rename ok"); - // Rename docs starting with $oldref with $newref - $listoffiles = dol_dir_list($conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id, 2, 0, 0, $this, 'invoice_supplier').$newref, 'files', 1, '^'.preg_quote($oldref, '/')); + // Rename docs starting with $oldref with $this->newref + $listoffiles = dol_dir_list($conf->fournisseur->facture->dir_output.'/'.get_exdir($this->id, 2, 0, 0, $this, 'invoice_supplier').$this->newref, 'files', 1, '^'.preg_quote($oldref, '/')); foreach ($listoffiles as $fileentry) { $dirsource = $fileentry['name']; - $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); + $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $this->newref, $dirsource); $dirsource = $fileentry['path'].'/'.$dirsource; $dirdest = $fileentry['path'].'/'.$dirdest; @rename($dirsource, $dirdest); diff --git a/htdocs/install/mysql/data/llx_c_forme_juridique.sql b/htdocs/install/mysql/data/llx_c_forme_juridique.sql index f17ba7b1b21..fd094e387ef 100644 --- a/htdocs/install/mysql/data/llx_c_forme_juridique.sql +++ b/htdocs/install/mysql/data/llx_c_forme_juridique.sql @@ -110,7 +110,7 @@ insert into llx_c_forme_juridique (fk_pays, code, libelle) values (2, '229', 'VS -- France: Catégories niveau II - Extrait de https://www.insee.fr/fr/information/2028129 - Dernière mise à jour Septembre 2022 -insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'00','Organisme de placement collectif en valeurs mobilières sans personnalité morale'); +insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'09','Organisme de placement collectif en valeurs mobilières sans personnalité morale'); insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'10','Entrepreneur individuel'); insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'21','Indivision'); insert into llx_c_forme_juridique (fk_pays, code, libelle) values (1,'22','Société créée de fait'); diff --git a/htdocs/langs/en_US/recruitment.lang b/htdocs/langs/en_US/recruitment.lang index d46ddaf389a..50085bd578f 100644 --- a/htdocs/langs/en_US/recruitment.lang +++ b/htdocs/langs/en_US/recruitment.lang @@ -79,3 +79,4 @@ WeAreRecruiting=We are recruiting. This is a list of open positions to be filled NoPositionOpen=No positions open at the moment ConfirmClose=Confirm cancellation ConfirmCloseAsk=Are you sure you want to cancel this recruitment candidature +recruitment=Recruitment diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index 4e19a517e6c..a2e5d7fd27b 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -219,10 +219,6 @@ if (!defined('NOREQUIREDB') && !defined('NOREQUIRESOC')) { // For DE, we need to invert our address with customer address $conf->global->MAIN_INVERT_SENDER_RECIPIENT = 1; } - if ($mysoc->country_code == 'FR' && !isset($conf->global->MAIN_PROFID1_IN_ADDRESS)) { - // For FR, default value of option to show profid SIRET is on by default. Decret n°2099-1299 2022-10-07 - $conf->global->MAIN_PROFID1_IN_ADDRESS = 1; - } if ($mysoc->country_code == 'FR' && !isset($conf->global->INVOICE_CATEGORY_OF_OPERATION)) { // For FR, default value of option to show category of operations is on by default. Decret n°2099-1299 2022-10-07 $conf->global->INVOICE_CATEGORY_OF_OPERATION = 1; @@ -249,6 +245,7 @@ if (!defined('NOREQUIREDB') && !defined('NOREQUIRESOC')) { // Invoice subtype is a requirement for Greece. $conf->global->INVOICE_SUBTYPE_ENABLED = 1; } + if (($mysoc->localtax1_assuj || $mysoc->localtax2_assuj) && !isset($conf->global->MAIN_NO_INPUT_PRICE_WITH_TAX)) { // For countries using the 2nd or 3rd tax, we disable input/edit of lines using the price including tax (because 2nb and 3rd tax not yet taken into account). // Work In Progress to support all taxes into unit price entry when MAIN_UNIT_PRICE_WITH_TAX_IS_FOR_ALL_TAXES is set. diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index c64d042485b..e0b191c195a 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -299,7 +299,6 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; $sql = preg_replace('/,\s*$/', '', $sql); -//$sql .= ", COUNT(rc.rowid) as anotherfield"; $sqlfields = $sql; // $sql fields to remove for count total @@ -388,6 +387,7 @@ if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { /* The fast and low memory method to get and count full list converts the sql into a sql count */ $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); if ($resql) { $objforcount = $db->fetch_object($resql); diff --git a/htdocs/product/stock/productlot_list.php b/htdocs/product/stock/productlot_list.php index ce24972023f..d0e65765b35 100644 --- a/htdocs/product/stock/productlot_list.php +++ b/htdocs/product/stock/productlot_list.php @@ -229,6 +229,9 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; $sql = preg_replace('/,\s*$/', '', $sql); + +$sqlfields = $sql; + $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; @@ -317,7 +320,9 @@ if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { } }*/ /* The fast and low memory method to get and count full list converts the sql into a sql count */ - $sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/Ui', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql); + $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); + $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); if ($resql) { $objforcount = $db->fetch_object($resql); @@ -325,7 +330,7 @@ if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { } else { dol_print_error($db); } - + if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 $page = 0; $offset = 0; diff --git a/htdocs/projet/contact.php b/htdocs/projet/contact.php index f2d3946579a..8e7c81d1200 100644 --- a/htdocs/projet/contact.php +++ b/htdocs/projet/contact.php @@ -158,6 +158,11 @@ if (empty($reshook)) { // Add new contact if ($action == 'addcontact_confirm' && $user->hasRight('projet', 'creer')) { + if (GETPOST('confirm', 'alpha') == 'no') { + header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); + exit; + } + $contactid = (GETPOST('userid') ? GETPOST('userid', 'int') : GETPOST('contactid', 'int')); $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type')); diff --git a/htdocs/public/agenda/agendaexport.php b/htdocs/public/agenda/agendaexport.php index 9f62c6265c5..873f5a80e50 100644 --- a/htdocs/public/agenda/agendaexport.php +++ b/htdocs/public/agenda/agendaexport.php @@ -86,7 +86,7 @@ require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; $object = new ActionComm($db); // Not older than -if (!isset($conf->global->MAIN_AGENDA_EXPORT_PAST_DELAY)) { +if (empty($conf->global->MAIN_AGENDA_EXPORT_PAST_DELAY)) { $conf->global->MAIN_AGENDA_EXPORT_PAST_DELAY = 100; // default limit } diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 2d6e1991846..ae4fe3dd971 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1775,7 +1775,7 @@ class Societe extends CommonObject global $langs; global $conf; - if (empty($rowid) && empty($ref) && empty($ref_ext) && empty($barcode) && empty($idprof1) && empty($idprof2) && empty($idprof3) && empty($idprof4) && empty($idprof5) && empty($idprof6) && empty($email)) { + if (empty($rowid) && empty($ref) && empty($ref_ext) && empty($barcode) && empty($idprof1) && empty($idprof2) && empty($idprof3) && empty($idprof4) && empty($idprof5) && empty($idprof6) && empty($email) && empty($ref_alias)) { return -1; } diff --git a/htdocs/website/index.php b/htdocs/website/index.php index aa7ea1f78e7..e25f1d4b2ab 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -4808,7 +4808,7 @@ if ($mode == 'replacesite' || $massaction == 'replace') { print ''; // Categories - Tags - print ''; + print ''; if (isModEnabled('categorie') && $user->hasRight('categorie', 'lire')) { // Get current categories $existing = $c->containing($answerrecord->id, Categorie::TYPE_WEBSITE_PAGE, 'object');