From 05e09ccc17bd713d5ae2af13c31f79d8c7b00d22 Mon Sep 17 00:00:00 2001 From: altairis-noe Date: Fri, 16 Jul 2021 17:46:21 +0200 Subject: [PATCH 001/417] Filter reassortlot with warehouse tags --- htdocs/product/reassortlot.php | 53 ++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index ea9901a3794..bc93503a3c7 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -6,6 +6,7 @@ * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Ferran Marcet * Copyright (C) 2019 Juanjo Menent + * Copyright (C) 2021 Noé Cendrier * * 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 @@ -72,6 +73,7 @@ $offset = $limit * $page; // Load sale and categ filters $search_sale = GETPOST("search_sale"); $search_categ = GETPOST("search_categ"); +$search_warehouse_categ = GETPOST("search_warehouse_categ"); // Get object canvas (By default, this is not defined, so standard usage of dolibarr) $canvas = GETPOST("canvas"); @@ -101,6 +103,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $tobuy = ""; $search_sale = ""; $search_categ = ""; + $search_warehouse_categ = ""; $type = ""; $catid = ''; $toolowstock = ''; @@ -132,16 +135,17 @@ $sql .= ' SUM(pb.qty) as stock_physique, COUNT(pb.rowid) as nbinbatchtable'; $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps on p.rowid = ps.fk_product'; // Detail for each warehouse $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot as e on ps.fk_entrepot = e.rowid'; // Link on unique key +$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_warehouse as cw on e.rowid = cw.fk_warehouse'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_batch as pb on pb.fk_product_stock = ps.rowid'; // Detail for each lot on each warehouse $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_lot as pl on pl.fk_product = p.rowid AND pl.batch = pb.batch'; // Link on unique key // We'll need this table joined to the select in order to filter by categ if ($search_categ) { - $sql .= ", ".MAIN_DB_PREFIX."categorie_product as cp"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; } $sql .= " WHERE p.entity IN (".getEntity('product').")"; -if ($search_categ) { - $sql .= " AND p.rowid = cp.fk_product"; // Join for the needed table to filter by categ -} +// if ($search_categ) { +// $sql .= " AND "; // Join for the needed table to filter by categ +// } if ($sall) { $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall); } @@ -178,9 +182,13 @@ if ($fourn_id > 0) { $sql .= " AND p.rowid = pf.fk_product AND pf.fk_soc = ".((int) $fourn_id); } // Insert categ filter -if ($search_categ) { +if ($search_categ > 0) { $sql .= " AND cp.fk_categorie = ".((int) $search_categ); } +if ($search_warehouse_categ > 0) { + // $sql .= Categorie::getFilterSelectQuery(Categorie::TYPE_WAREHOUSE, "e.rowid", $search_warehouse_categ); + $sql .= " AND cw.fk_categorie = " . (int) $search_warehouse_categ; +} if ($search_warehouse) { $sql .= natural_search("e.ref", $search_warehouse); } @@ -280,6 +288,9 @@ if ($resql) { if ($search_categ) { $param .= "&search_categ=".urlencode($search_categ); } + if ($search_warehouse_categ) { + $param .= "&search_warehouse_categ=".urlencode($search_warehouse_categ); + } /*if ($eatby) $param.="&eatby=".$eatby; if ($sellby) $param.="&sellby=".$sellby;*/ @@ -303,28 +314,32 @@ if ($resql) { print "
"; } - // Filter on categories + // Filter on product categories $moreforfilter = ''; if (!empty($conf->categorie->enabled)) { - $moreforfilter .= '
'; - $moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); - $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ'); - $moreforfilter .= '
'; + $moreforfilter .= ''; + $moreforfilter .= ''.img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); + $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ').''; + + // Filter on warehouse categories + $moreforfilter .= ''.img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); + $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_WAREHOUSE, $search_warehouse_categ, 'search_warehouse_categ').''; + $moreforfilter .= ''; } //$moreforfilter.=$langs->trans("StockTooLow").' '; - if (!empty($moreforfilter)) { - print '
'; - print $moreforfilter; - $parameters = array(); - $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - print '
'; - } - print '
'; print ''; + if (!empty($moreforfilter)) { + // print '
'; + print $moreforfilter; + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // print '
'; + } + // Fields title search print ''; From d8551da83f77eab4998f9b732d937dcdb953c427 Mon Sep 17 00:00:00 2001 From: altairis-noe Date: Mon, 19 Jul 2021 09:36:58 +0200 Subject: [PATCH 002/417] correction after review --- htdocs/product/reassortlot.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index bc93503a3c7..751c47fd2d2 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -135,17 +135,16 @@ $sql .= ' SUM(pb.qty) as stock_physique, COUNT(pb.rowid) as nbinbatchtable'; $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps on p.rowid = ps.fk_product'; // Detail for each warehouse $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot as e on ps.fk_entrepot = e.rowid'; // Link on unique key -$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_warehouse as cw on e.rowid = cw.fk_warehouse'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_batch as pb on pb.fk_product_stock = ps.rowid'; // Detail for each lot on each warehouse $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_lot as pl on pl.fk_product = p.rowid AND pl.batch = pb.batch'; // Link on unique key // We'll need this table joined to the select in order to filter by categ -if ($search_categ) { +if ($search_categ > 0) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; } +if ($search_warehouse_categ > 0) { + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_warehouse as cw on e.rowid = cw.fk_warehouse'; +} $sql .= " WHERE p.entity IN (".getEntity('product').")"; -// if ($search_categ) { -// $sql .= " AND "; // Join for the needed table to filter by categ -// } if ($sall) { $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall); } @@ -186,7 +185,6 @@ if ($search_categ > 0) { $sql .= " AND cp.fk_categorie = ".((int) $search_categ); } if ($search_warehouse_categ > 0) { - // $sql .= Categorie::getFilterSelectQuery(Categorie::TYPE_WAREHOUSE, "e.rowid", $search_warehouse_categ); $sql .= " AND cw.fk_categorie = " . (int) $search_warehouse_categ; } if ($search_warehouse) { @@ -285,10 +283,10 @@ if ($resql) { if ($search_sale) { $param .= "&search_sale=".urlencode($search_sale); } - if ($search_categ) { + if ($search_categ > 0) { $param .= "&search_categ=".urlencode($search_categ); } - if ($search_warehouse_categ) { + if ($search_warehouse_categ > 0) { $param .= "&search_warehouse_categ=".urlencode($search_warehouse_categ); } /*if ($eatby) $param.="&eatby=".$eatby; @@ -332,12 +330,10 @@ if ($resql) { print '
'; print '
'; if (!empty($moreforfilter)) { - // print '
'; print $moreforfilter; $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; - // print '
'; } From fdbef33d9c24e3127a694d6f43c84b1013a44c15 Mon Sep 17 00:00:00 2001 From: altairis-noe Date: Mon, 19 Jul 2021 11:22:41 +0200 Subject: [PATCH 003/417] indet linter --- htdocs/product/reassortlot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index 751c47fd2d2..7558597057f 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -319,7 +319,7 @@ if ($resql) { $moreforfilter .= ''; - // Filter on warehouse categories + // Filter on warehouse categories $moreforfilter .= ''; $moreforfilter .= ''; From ad878cb12e57eec9daf29d273361d352e070fc4e Mon Sep 17 00:00:00 2001 From: Jeritiana Ravelojaona Date: Thu, 3 Nov 2022 18:43:26 +0300 Subject: [PATCH 004/417] Add OpenID Connect impl --- .../core/login/functions_openid_connect.php | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 htdocs/core/login/functions_openid_connect.php diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php new file mode 100644 index 00000000000..32f7f934117 --- /dev/null +++ b/htdocs/core/login/functions_openid_connect.php @@ -0,0 +1,120 @@ + + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/login/functions_openid_connect.php + * \ingroup core + * \brief OpenID Connect: Authorization Code flow authentication + */ + +include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; + +/** + * Check validity of user/password/entity + * If test is ko, reason must be filled into $_SESSION["dol_loginmesg"] + * + * @param string $usertotest Login + * @param string $passwordtotest Password + * @param int $entitytotest Number of instance (always 1 if module multicompany not enabled) + * @return string Login if OK, '' if KO + */ +function check_user_password_openid_connect($usertotest, $passwordtotest, $entitytotest) +{ + global $conf; + + dol_syslog("functions_openid_connect::check_user_password_openid_connect"); + + $login = ''; + + // Step 1 is done by user: request an authorization code + + if (GETPOSTISSET('username')) { + + // OIDC does not require credentials here: pass on to next auth handler + $_SESSION["dol_loginmesg"] = "Not an OpenID Connect flow"; + dol_syslog("functions_openid_connect::check_user_password_openid_connect not an OIDC flow"); + + } elseif (GETPOSTISSET['code']) { + $auth_code = GETPOST('code', 'aZ09'); + dol_syslog("functions_openid_connect::check_user_password_openid_connect code=".$auth_code); + + // Step 2: turn the authorization code into an access token, using client_secret + $auth_param = [ + 'grant_type' => 'authorization_code', + 'client_id' => $conf->global->MAIN_AUTHENTICATION_OIDC_CLIENT_ID, + 'client_secret' => $conf->global->MAIN_AUTHENTICATION_OIDC_CLIENT_SECRET, + 'code' => $auth_code, + 'redirect_uri' => $conf->global->MAIN_AUTHENTICATION_OIDC_REDIRECT_URL + ]; + + $token_response = getURLContent($conf->global->MAIN_AUTHENTICATION_OIDC_TOKEN_URL, 'POST', http_build_query($auth_param)); + $token_content = json_decode($token_response['content']); + dol_syslog("functions_openid_connect::check_user_password_openid_connect /token=".print_r($token_response, true), LOG_DEBUG); + + if ($token_content->access_token) { + + // Step 3: retrieve user info using token + $userinfo_headers = array('Authorization: Bearer '.$token_content->access_token); + $userinfo_response = getURLContent($conf->global->MAIN_AUTHENTICATION_OIDC_USERINFO_URL, 'GET', '', 1, $userinfo_headers); + $userinfo_content = json_decode($userinfo_response['content']); + dol_syslog("functions_openid_connect::check_user_password_openid_connect /userinfo=".print_r($userinfo_response, true), LOG_DEBUG); + + // Get the user attribute (claim) matching the Dolibarr login + $login_claim = 'email'; // default + if (!empty($conf->global->MAIN_AUTHENTICATION_OIDC_LOGIN_CLAIM)) { + $login_claim = $conf->global->MAIN_AUTHENTICATION_OIDC_LOGIN_CLAIM; + } + + if (array_key_exists($login_claim, $userinfo_content)) { + // Success: retrieve claim to return to Dolibarr as login + $login = $userinfo_content->$login_claim; + $_SESSION["dol_loginmesg"] = ""; + } elseif ($userinfo_content->error) { + // Got user info response but content is an error + $_SESSION["dol_loginmesg"] = "Error in OAuth 2.0 flow (".$userinfo_content->error_description.")"; + } elseif ($userinfo_response['http_code'] == 200) { + // Claim does not exist + $_SESSION["dol_loginmesg"] = "OpenID Connect claim not found: ".$login_claim; + } elseif ($userinfo_response['curl_error_no']) { + // User info request error + $_SESSION["dol_loginmesg"] = "Network error: ".$userinfo_response['curl_error_msg']." (".$userinfo_response['curl_error_no'].")"; + } else { + // Other user info request error + $_SESSION["dol_loginmesg"] = "Userinfo request error (".$userinfo_response['http_code'].")"; + } + + } elseif ($token_content->error) { + // Got token response but content is an error + $_SESSION["dol_loginmesg"] = "Error in OAuth 2.0 flow (".$token_content->error_description.")"; + } elseif ($token_response['curl_error_no']) { + // Token request error + $_SESSION["dol_loginmesg"] = "Network error: ".$token_response['curl_error_msg']." (".$token_response['curl_error_no'].")"; + } else { + // Other token request error + $_SESSION["dol_loginmesg"] = "Token request error (".$token_response['http_code'].")"; + } + + } else { + // No code received + $_SESSION["dol_loginmesg"] = "Error in OAuth 2.0 flow (no code received)"; + } + + dol_syslog("functions_openid_connect::check_user_password_openid_connect END"); + + return !empty($login) ? $login : false; +} + From 8ba94e7294f55625a728e156be500b24165f89c5 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 3 Nov 2022 15:45:53 +0000 Subject: [PATCH 005/417] Fixing style errors. --- htdocs/core/login/functions_openid_connect.php | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php index 32f7f934117..5be96b213ea 100644 --- a/htdocs/core/login/functions_openid_connect.php +++ b/htdocs/core/login/functions_openid_connect.php @@ -43,11 +43,9 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit // Step 1 is done by user: request an authorization code if (GETPOSTISSET('username')) { - // OIDC does not require credentials here: pass on to next auth handler $_SESSION["dol_loginmesg"] = "Not an OpenID Connect flow"; dol_syslog("functions_openid_connect::check_user_password_openid_connect not an OIDC flow"); - } elseif (GETPOSTISSET['code']) { $auth_code = GETPOST('code', 'aZ09'); dol_syslog("functions_openid_connect::check_user_password_openid_connect code=".$auth_code); @@ -58,7 +56,7 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit 'client_id' => $conf->global->MAIN_AUTHENTICATION_OIDC_CLIENT_ID, 'client_secret' => $conf->global->MAIN_AUTHENTICATION_OIDC_CLIENT_SECRET, 'code' => $auth_code, - 'redirect_uri' => $conf->global->MAIN_AUTHENTICATION_OIDC_REDIRECT_URL + 'redirect_uri' => $conf->global->MAIN_AUTHENTICATION_OIDC_REDIRECT_URL ]; $token_response = getURLContent($conf->global->MAIN_AUTHENTICATION_OIDC_TOKEN_URL, 'POST', http_build_query($auth_param)); @@ -66,7 +64,6 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit dol_syslog("functions_openid_connect::check_user_password_openid_connect /token=".print_r($token_response, true), LOG_DEBUG); if ($token_content->access_token) { - // Step 3: retrieve user info using token $userinfo_headers = array('Authorization: Bearer '.$token_content->access_token); $userinfo_response = getURLContent($conf->global->MAIN_AUTHENTICATION_OIDC_USERINFO_URL, 'GET', '', 1, $userinfo_headers); @@ -96,7 +93,6 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit // Other user info request error $_SESSION["dol_loginmesg"] = "Userinfo request error (".$userinfo_response['http_code'].")"; } - } elseif ($token_content->error) { // Got token response but content is an error $_SESSION["dol_loginmesg"] = "Error in OAuth 2.0 flow (".$token_content->error_description.")"; @@ -107,14 +103,12 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit // Other token request error $_SESSION["dol_loginmesg"] = "Token request error (".$token_response['http_code'].")"; } - - } else { + } else { // No code received $_SESSION["dol_loginmesg"] = "Error in OAuth 2.0 flow (no code received)"; - } + } dol_syslog("functions_openid_connect::check_user_password_openid_connect END"); return !empty($login) ? $login : false; } - From f1c14316937459ac26077a69b5effde90070bbbf Mon Sep 17 00:00:00 2001 From: kkhelifa Date: Thu, 17 Nov 2022 17:09:13 +0100 Subject: [PATCH 006/417] FIX: Set extrafield value of multiselect type --- htdocs/core/class/commonobject.class.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 27b00377411..95bf1085637 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5988,6 +5988,12 @@ abstract class CommonObject dol_syslog('Error bad setup of extrafield', LOG_WARNING); } break; + case 'checkbox': + case 'chkbxlst': + if (is_array($this->array_options[$key])) { + $new_array_options[$key] = implode(',', $this->array_options[$key]); + } + break; } } @@ -6333,6 +6339,12 @@ abstract class CommonObject } break; */ + case 'checkbox': + case 'chkbxlst': + if (is_array($this->array_options[$key])) { + $new_array_options[$key] = implode(',', $this->array_options[$key]); + } + break; } $this->db->begin(); From 1c659c6ae8c02c51b83bddab176f36be966a6221 Mon Sep 17 00:00:00 2001 From: FLIO Date: Wed, 11 Jan 2023 15:38:13 +0100 Subject: [PATCH 007/417] feature(#21426) Added in the export module the possibility to choose between utf-8 and iso format --- ....modules.php => export_csviso.modules.php} | 20 +- .../modules/export/export_csvutf8.modules.php | 379 ++++++++++++++++++ 2 files changed, 386 insertions(+), 13 deletions(-) rename htdocs/core/modules/export/{export_csv.modules.php => export_csviso.modules.php} (94%) create mode 100644 htdocs/core/modules/export/export_csvutf8.modules.php diff --git a/htdocs/core/modules/export/export_csv.modules.php b/htdocs/core/modules/export/export_csviso.modules.php similarity index 94% rename from htdocs/core/modules/export/export_csv.modules.php rename to htdocs/core/modules/export/export_csviso.modules.php index 26f20378b23..00759d3de55 100644 --- a/htdocs/core/modules/export/export_csv.modules.php +++ b/htdocs/core/modules/export/export_csviso.modules.php @@ -74,9 +74,8 @@ class ExportCsv extends ModeleExports } $this->escape = '"'; $this->enclosure = '"'; - - $this->id = 'csv'; // Same value then xxx in file name export_xxx.modules.php - $this->label = 'CSV'; // Label of driver + $this->id = 'csviso'; // Same value then xxx in file name export_xxx.modules.php + $this->label = 'CSV ISO-8859-1'; // Label of driver $this->desc = $langs->trans("CSVFormatDesc", $this->separator, $this->enclosure, $this->escape); $this->extension = 'csv'; // Extension for generated file by this driver $this->picto = 'mime/other'; // Picto @@ -215,11 +214,9 @@ class ExportCsv extends ModeleExports // phpcs:enable global $conf; - if (!empty($conf->global->EXPORT_CSV_FORCE_CHARSET)) { - $outputlangs->charset_output = $conf->global->EXPORT_CSV_FORCE_CHARSET; - } else { - $outputlangs->charset_output = 'ISO-8859-1'; - } + $outputlangs->charset_output = 'ISO-8859-1'; + $conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1'; + $selectlabel = array(); foreach ($array_selected_sorted as $code => $value) { @@ -256,11 +253,8 @@ class ExportCsv extends ModeleExports // phpcs:enable global $conf; - if (!empty($conf->global->EXPORT_CSV_FORCE_CHARSET)) { - $outputlangs->charset_output = $conf->global->EXPORT_CSV_FORCE_CHARSET; - } else { - $outputlangs->charset_output = 'ISO-8859-1'; - } + $outputlangs->charset_output = 'ISO-8859-1'; + $conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1'; $this->col = 0; diff --git a/htdocs/core/modules/export/export_csvutf8.modules.php b/htdocs/core/modules/export/export_csvutf8.modules.php new file mode 100644 index 00000000000..75958fb7b35 --- /dev/null +++ b/htdocs/core/modules/export/export_csvutf8.modules.php @@ -0,0 +1,379 @@ + + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/modules/export/export_csv.modules.php + * \ingroup export + * \brief File of class to build exports with CSV format + */ + +require_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php'; + +// avoid timeout for big export +set_time_limit(0); + +/** + * Class to build export files with format CSV + */ +class ExportCsvUtf8 extends ModeleExports +{ + /** + * @var string ID ex: csv, tsv, excel... + */ + public $id; + + /** + * @var string export files label + */ + public $label; + + public $extension; + + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; + + public $label_lib; + + public $version_lib; + + public $separator; + + public $handle; // Handle fichier + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $conf, $langs; + $this->db = $db; + + $this->separator = ','; + if (!empty($conf->global->EXPORT_CSV_SEPARATOR_TO_USE)) { + $this->separator = $conf->global->EXPORT_CSV_SEPARATOR_TO_USE; + } + $this->escape = '"'; + $this->enclosure = '"'; + + $this->id = 'csvutf8'; // Same value then xxx in file name export_xxx.modules.php + $this->label = 'CSV UTF-8'; // Label of driver + $this->desc = $langs->trans("CSVFormatDesc", $this->separator, $this->enclosure, $this->escape); + $this->extension = 'csv'; // Extension for generated file by this driver + $this->picto = 'mime/other'; // Picto + $this->version = '1.32'; // Driver version + + // If driver use an external library, put its name here + $this->label_lib = 'Dolibarr'; + $this->version_lib = DOL_VERSION; + } + + /** + * getDriverId + * + * @return string + */ + public function getDriverId() + { + return $this->id; + } + + /** + * getDriverLabel + * + * @return string Return driver label + */ + public function getDriverLabel() + { + return $this->label; + } + + /** + * getDriverDesc + * + * @return string + */ + public function getDriverDesc() + { + return $this->desc; + } + + /** + * getDriverExtension + * + * @return string + */ + public function getDriverExtension() + { + return $this->extension; + } + + /** + * getDriverVersion + * + * @return string + */ + public function getDriverVersion() + { + return $this->version; + } + + /** + * getLabelLabel + * + * @return string + */ + public function getLibLabel() + { + return $this->label_lib; + } + + /** + * getLibVersion + * + * @return string + */ + public function getLibVersion() + { + return $this->version_lib; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Open output file + * + * @param string $file Path of filename to generate + * @param Translate $outputlangs Output language object + * @return int <0 if KO, >=0 if OK + */ + public function open_file($file, $outputlangs) + { + // phpcs:enable + global $langs; + + dol_syslog("ExportCsv::open_file file=".$file); + + $ret = 1; + + $outputlangs->load("exports"); + $this->handle = fopen($file, "wt"); + if (!$this->handle) { + $langs->load("errors"); + $this->error = $langs->trans("ErrorFailToCreateFile", $file); + $ret = -1; + } + + return $ret; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output header into file + * + * @param Translate $outputlangs Output language object + * @return int <0 if KO, >0 if OK + */ + public function write_header($outputlangs) + { + // phpcs:enable + return 0; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output title line into file + * + * @param array $array_export_fields_label Array with list of label of fields + * @param array $array_selected_sorted Array with list of field to export + * @param Translate $outputlangs Object lang to translate values + * @param array $array_types Array with types of fields + * @return int <0 if KO, >0 if OK + */ + public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types) + { + // phpcs:enable + global $conf; + + $outputlangs->charset_output = 'UTF-8'; + // var_dump($outputlangs->charset_output);exit; + // var_dump($conf->global->EXPORT_CSV_FORCE_CHARSET, "here");exit; + $selectlabel = array(); + + foreach ($array_selected_sorted as $code => $value) { + $newvalue = $outputlangs->transnoentities($array_export_fields_label[$code]); // newvalue is now $outputlangs->charset_output encoded + $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); + + fwrite($this->handle, $newvalue.$this->separator); + $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; + + if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { + $selectlabel[$code."_label"] = $newvalue."_label"; + } + } + foreach ($selectlabel as $key => $value) { + fwrite($this->handle, $value.$this->separator); + } + fwrite($this->handle, "\n"); + return 0; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output record line into file + * + * @param array $array_selected_sorted Array with list of field to export + * @param resource $objp A record from a fetch with all fields from select + * @param Translate $outputlangs Object lang to translate values + * @param array $array_types Array with types of fields + * @return int <0 if KO, >0 if OK + */ + public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types) + { + // phpcs:enable + global $conf; + + $outputlangs->charset_output = 'UTF-8'; + // var_dump($conf->global->EXPORT_CSV_FORCE_CHARSET, "here");exit; + $this->col = 0; + + $reg = array(); + $selectlabelvalues = array(); + foreach ($array_selected_sorted as $code => $value) { + if (strpos($code, ' as ') == 0) { + $alias = str_replace(array('.', '-', '(', ')'), '_', $code); + } else { + $alias = substr($code, strpos($code, ' as ') + 4); + } + if (empty($alias)) { + dol_print_error('', 'Bad value for field with key='.$code.'. Try to redefine export.'); + } + + $newvalue = $outputlangs->convToOutputCharset($objp->$alias); // objp->$alias must be utf8 encoded as any var in memory // newvalue is now $outputlangs->charset_output encoded + $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; + + // Translation newvalue + if (preg_match('/^\((.*)\)$/i', $newvalue, $reg)) { + $newvalue = $outputlangs->transnoentities($reg[1]); + } + + // Clean data and add encloser if required (depending on value of USE_STRICT_CSV_RULES) + $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); + + if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { + $array = jsonOrUnserialize($typefield); + if (is_array($array) && !empty($newvalue)) { + $array = $array['options']; + $selectlabelvalues[$code."_label"] = $array[$newvalue]; + } else { + $selectlabelvalues[$code."_label"] = ""; + } + } + + fwrite($this->handle, $newvalue.$this->separator); + $this->col++; + } + foreach ($selectlabelvalues as $key => $value) { + fwrite($this->handle, $value.$this->separator); + $this->col++; + } + + fwrite($this->handle, "\n"); + return 0; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output footer into file + * + * @param Translate $outputlangs Output language object + * @return int <0 if KO, >0 if OK + */ + public function write_footer($outputlangs) + { + // phpcs:enable + return 0; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Close file handle + * + * @return int <0 if KO, >0 if OK + */ + public function close_file() + { + // phpcs:enable + fclose($this->handle); + return 0; + } + + + /** + * Clean a cell to respect rules of CSV file cells + * Note: It uses $this->separator + * Note: We keep this function public to be able to test + * + * @param string $newvalue String to clean + * @param string $charset Input AND Output character set + * @return string Value cleaned + */ + public function csvClean($newvalue, $charset) + { + global $conf; + $addquote = 0; + + // Rule Dolibarr: No HTML + //print $charset.' '.$newvalue."\n"; + //$newvalue=dol_string_nohtmltag($newvalue,0,$charset); + $newvalue = dol_htmlcleanlastbr($newvalue); + //print $charset.' '.$newvalue."\n"; + + // Rule 1 CSV: No CR, LF in cells (except if USE_STRICT_CSV_RULES is 1, we can keep record as it is but we must add quotes) + $oldvalue = $newvalue; + $newvalue = str_replace("\r", '', $newvalue); + $newvalue = str_replace("\n", '\n', $newvalue); + if (!empty($conf->global->USE_STRICT_CSV_RULES) && $oldvalue != $newvalue) { + // If we must use enclusure on text with CR/LF) + if ($conf->global->USE_STRICT_CSV_RULES == 1) { + // If we use strict CSV rules (original value must remain but we add quote) + $newvalue = $oldvalue; + } + $addquote = 1; + } + + // Rule 2 CSV: If value contains ", we must escape with ", and add " + if (preg_match('/"/', $newvalue)) { + $addquote = 1; + $newvalue = str_replace('"', '""', $newvalue); + } + + // Rule 3 CSV: If value contains separator, we must add " + if (preg_match('/'.$this->separator.'/', $newvalue)) { + $addquote = 1; + } + + return ($addquote ? '"' : '').$newvalue.($addquote ? '"' : ''); + } +} From c5d3474e10b87d7cccf8546c12a06da49a5a8054 Mon Sep 17 00:00:00 2001 From: FLIO Date: Tue, 17 Jan 2023 18:25:49 +0100 Subject: [PATCH 008/417] Create class module export csv for extend csv utf-8 and iso --- .../modules/export/export_csviso.modules.php | 328 +---------------- .../modules/export/export_csvutf8.modules.php | 328 +---------------- .../core/modules/export/module_export_csv.php | 348 ++++++++++++++++++ 3 files changed, 362 insertions(+), 642 deletions(-) create mode 100644 htdocs/core/modules/export/module_export_csv.php diff --git a/htdocs/core/modules/export/export_csviso.modules.php b/htdocs/core/modules/export/export_csviso.modules.php index 00759d3de55..b477868c09c 100644 --- a/htdocs/core/modules/export/export_csviso.modules.php +++ b/htdocs/core/modules/export/export_csviso.modules.php @@ -21,43 +21,17 @@ * \brief File of class to build exports with CSV format */ -require_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php'; +require_once DOL_DOCUMENT_ROOT.'/core/modules/export/module_export_csv.php'; // avoid timeout for big export set_time_limit(0); /** - * Class to build export files with format CSV + * Class to build export files with format CSV iso */ -class ExportCsv extends ModeleExports +class ExportCsvIso extends ExportCsv { - /** - * @var string ID ex: csv, tsv, excel... - */ - public $id; - - /** - * @var string export files label - */ - public $label; - - public $extension; - - /** - * Dolibarr version of the loaded document - * @var string - */ - public $version = 'dolibarr'; - - public $label_lib; - - public $version_lib; - - public $separator; - - public $handle; // Handle fichier - - + /** * Constructor * @@ -72,6 +46,9 @@ class ExportCsv extends ModeleExports if (!empty($conf->global->EXPORT_CSV_SEPARATOR_TO_USE)) { $this->separator = $conf->global->EXPORT_CSV_SEPARATOR_TO_USE; } + + $conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1'; + $this->escape = '"'; $this->enclosure = '"'; $this->id = 'csviso'; // Same value then xxx in file name export_xxx.modules.php @@ -85,295 +62,4 @@ class ExportCsv extends ModeleExports $this->label_lib = 'Dolibarr'; $this->version_lib = DOL_VERSION; } - - /** - * getDriverId - * - * @return string - */ - public function getDriverId() - { - return $this->id; - } - - /** - * getDriverLabel - * - * @return string Return driver label - */ - public function getDriverLabel() - { - return $this->label; - } - - /** - * getDriverDesc - * - * @return string - */ - public function getDriverDesc() - { - return $this->desc; - } - - /** - * getDriverExtension - * - * @return string - */ - public function getDriverExtension() - { - return $this->extension; - } - - /** - * getDriverVersion - * - * @return string - */ - public function getDriverVersion() - { - return $this->version; - } - - /** - * getLabelLabel - * - * @return string - */ - public function getLibLabel() - { - return $this->label_lib; - } - - /** - * getLibVersion - * - * @return string - */ - public function getLibVersion() - { - return $this->version_lib; - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Open output file - * - * @param string $file Path of filename to generate - * @param Translate $outputlangs Output language object - * @return int <0 if KO, >=0 if OK - */ - public function open_file($file, $outputlangs) - { - // phpcs:enable - global $langs; - - dol_syslog("ExportCsv::open_file file=".$file); - - $ret = 1; - - $outputlangs->load("exports"); - $this->handle = fopen($file, "wt"); - if (!$this->handle) { - $langs->load("errors"); - $this->error = $langs->trans("ErrorFailToCreateFile", $file); - $ret = -1; - } - - return $ret; - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Output header into file - * - * @param Translate $outputlangs Output language object - * @return int <0 if KO, >0 if OK - */ - public function write_header($outputlangs) - { - // phpcs:enable - return 0; - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Output title line into file - * - * @param array $array_export_fields_label Array with list of label of fields - * @param array $array_selected_sorted Array with list of field to export - * @param Translate $outputlangs Object lang to translate values - * @param array $array_types Array with types of fields - * @return int <0 if KO, >0 if OK - */ - public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types) - { - // phpcs:enable - global $conf; - - $outputlangs->charset_output = 'ISO-8859-1'; - $conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1'; - - $selectlabel = array(); - - foreach ($array_selected_sorted as $code => $value) { - $newvalue = $outputlangs->transnoentities($array_export_fields_label[$code]); // newvalue is now $outputlangs->charset_output encoded - $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); - - fwrite($this->handle, $newvalue.$this->separator); - $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; - - if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { - $selectlabel[$code."_label"] = $newvalue."_label"; - } - } - foreach ($selectlabel as $key => $value) { - fwrite($this->handle, $value.$this->separator); - } - fwrite($this->handle, "\n"); - return 0; - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Output record line into file - * - * @param array $array_selected_sorted Array with list of field to export - * @param resource $objp A record from a fetch with all fields from select - * @param Translate $outputlangs Object lang to translate values - * @param array $array_types Array with types of fields - * @return int <0 if KO, >0 if OK - */ - public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types) - { - // phpcs:enable - global $conf; - - $outputlangs->charset_output = 'ISO-8859-1'; - $conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1'; - - $this->col = 0; - - $reg = array(); - $selectlabelvalues = array(); - foreach ($array_selected_sorted as $code => $value) { - if (strpos($code, ' as ') == 0) { - $alias = str_replace(array('.', '-', '(', ')'), '_', $code); - } else { - $alias = substr($code, strpos($code, ' as ') + 4); - } - if (empty($alias)) { - dol_print_error('', 'Bad value for field with key='.$code.'. Try to redefine export.'); - } - - $newvalue = $outputlangs->convToOutputCharset($objp->$alias); // objp->$alias must be utf8 encoded as any var in memory // newvalue is now $outputlangs->charset_output encoded - $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; - - // Translation newvalue - if (preg_match('/^\((.*)\)$/i', $newvalue, $reg)) { - $newvalue = $outputlangs->transnoentities($reg[1]); - } - - // Clean data and add encloser if required (depending on value of USE_STRICT_CSV_RULES) - $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); - - if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { - $array = jsonOrUnserialize($typefield); - if (is_array($array) && !empty($newvalue)) { - $array = $array['options']; - $selectlabelvalues[$code."_label"] = $array[$newvalue]; - } else { - $selectlabelvalues[$code."_label"] = ""; - } - } - - fwrite($this->handle, $newvalue.$this->separator); - $this->col++; - } - foreach ($selectlabelvalues as $key => $value) { - fwrite($this->handle, $value.$this->separator); - $this->col++; - } - - fwrite($this->handle, "\n"); - return 0; - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Output footer into file - * - * @param Translate $outputlangs Output language object - * @return int <0 if KO, >0 if OK - */ - public function write_footer($outputlangs) - { - // phpcs:enable - return 0; - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Close file handle - * - * @return int <0 if KO, >0 if OK - */ - public function close_file() - { - // phpcs:enable - fclose($this->handle); - return 0; - } - - - /** - * Clean a cell to respect rules of CSV file cells - * Note: It uses $this->separator - * Note: We keep this function public to be able to test - * - * @param string $newvalue String to clean - * @param string $charset Input AND Output character set - * @return string Value cleaned - */ - public function csvClean($newvalue, $charset) - { - global $conf; - $addquote = 0; - - // Rule Dolibarr: No HTML - //print $charset.' '.$newvalue."\n"; - //$newvalue=dol_string_nohtmltag($newvalue,0,$charset); - $newvalue = dol_htmlcleanlastbr($newvalue); - //print $charset.' '.$newvalue."\n"; - - // Rule 1 CSV: No CR, LF in cells (except if USE_STRICT_CSV_RULES is 1, we can keep record as it is but we must add quotes) - $oldvalue = $newvalue; - $newvalue = str_replace("\r", '', $newvalue); - $newvalue = str_replace("\n", '\n', $newvalue); - if (!empty($conf->global->USE_STRICT_CSV_RULES) && $oldvalue != $newvalue) { - // If we must use enclusure on text with CR/LF) - if ($conf->global->USE_STRICT_CSV_RULES == 1) { - // If we use strict CSV rules (original value must remain but we add quote) - $newvalue = $oldvalue; - } - $addquote = 1; - } - - // Rule 2 CSV: If value contains ", we must escape with ", and add " - if (preg_match('/"/', $newvalue)) { - $addquote = 1; - $newvalue = str_replace('"', '""', $newvalue); - } - - // Rule 3 CSV: If value contains separator, we must add " - if (preg_match('/'.$this->separator.'/', $newvalue)) { - $addquote = 1; - } - - return ($addquote ? '"' : '').$newvalue.($addquote ? '"' : ''); - } } diff --git a/htdocs/core/modules/export/export_csvutf8.modules.php b/htdocs/core/modules/export/export_csvutf8.modules.php index 75958fb7b35..f8b254cabe9 100644 --- a/htdocs/core/modules/export/export_csvutf8.modules.php +++ b/htdocs/core/modules/export/export_csvutf8.modules.php @@ -21,43 +21,17 @@ * \brief File of class to build exports with CSV format */ -require_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php'; +require_once DOL_DOCUMENT_ROOT.'/core/modules/export/module_export_csv.php'; // avoid timeout for big export set_time_limit(0); /** - * Class to build export files with format CSV + * Class to build export files with format CSV utf-8 */ -class ExportCsvUtf8 extends ModeleExports +class ExportCsvUtf8 extends ExportCsv { - /** - * @var string ID ex: csv, tsv, excel... - */ - public $id; - - /** - * @var string export files label - */ - public $label; - - public $extension; - - /** - * Dolibarr version of the loaded document - * @var string - */ - public $version = 'dolibarr'; - - public $label_lib; - - public $version_lib; - - public $separator; - - public $handle; // Handle fichier - - + /** * Constructor * @@ -72,9 +46,11 @@ class ExportCsvUtf8 extends ModeleExports if (!empty($conf->global->EXPORT_CSV_SEPARATOR_TO_USE)) { $this->separator = $conf->global->EXPORT_CSV_SEPARATOR_TO_USE; } + + $conf->global->EXPORT_CSV_FORCE_CHARSET = 'UTF-8'; + $this->escape = '"'; $this->enclosure = '"'; - $this->id = 'csvutf8'; // Same value then xxx in file name export_xxx.modules.php $this->label = 'CSV UTF-8'; // Label of driver $this->desc = $langs->trans("CSVFormatDesc", $this->separator, $this->enclosure, $this->escape); @@ -86,294 +62,4 @@ class ExportCsvUtf8 extends ModeleExports $this->label_lib = 'Dolibarr'; $this->version_lib = DOL_VERSION; } - - /** - * getDriverId - * - * @return string - */ - public function getDriverId() - { - return $this->id; - } - - /** - * getDriverLabel - * - * @return string Return driver label - */ - public function getDriverLabel() - { - return $this->label; - } - - /** - * getDriverDesc - * - * @return string - */ - public function getDriverDesc() - { - return $this->desc; - } - - /** - * getDriverExtension - * - * @return string - */ - public function getDriverExtension() - { - return $this->extension; - } - - /** - * getDriverVersion - * - * @return string - */ - public function getDriverVersion() - { - return $this->version; - } - - /** - * getLabelLabel - * - * @return string - */ - public function getLibLabel() - { - return $this->label_lib; - } - - /** - * getLibVersion - * - * @return string - */ - public function getLibVersion() - { - return $this->version_lib; - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Open output file - * - * @param string $file Path of filename to generate - * @param Translate $outputlangs Output language object - * @return int <0 if KO, >=0 if OK - */ - public function open_file($file, $outputlangs) - { - // phpcs:enable - global $langs; - - dol_syslog("ExportCsv::open_file file=".$file); - - $ret = 1; - - $outputlangs->load("exports"); - $this->handle = fopen($file, "wt"); - if (!$this->handle) { - $langs->load("errors"); - $this->error = $langs->trans("ErrorFailToCreateFile", $file); - $ret = -1; - } - - return $ret; - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Output header into file - * - * @param Translate $outputlangs Output language object - * @return int <0 if KO, >0 if OK - */ - public function write_header($outputlangs) - { - // phpcs:enable - return 0; - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Output title line into file - * - * @param array $array_export_fields_label Array with list of label of fields - * @param array $array_selected_sorted Array with list of field to export - * @param Translate $outputlangs Object lang to translate values - * @param array $array_types Array with types of fields - * @return int <0 if KO, >0 if OK - */ - public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types) - { - // phpcs:enable - global $conf; - - $outputlangs->charset_output = 'UTF-8'; - // var_dump($outputlangs->charset_output);exit; - // var_dump($conf->global->EXPORT_CSV_FORCE_CHARSET, "here");exit; - $selectlabel = array(); - - foreach ($array_selected_sorted as $code => $value) { - $newvalue = $outputlangs->transnoentities($array_export_fields_label[$code]); // newvalue is now $outputlangs->charset_output encoded - $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); - - fwrite($this->handle, $newvalue.$this->separator); - $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; - - if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { - $selectlabel[$code."_label"] = $newvalue."_label"; - } - } - foreach ($selectlabel as $key => $value) { - fwrite($this->handle, $value.$this->separator); - } - fwrite($this->handle, "\n"); - return 0; - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Output record line into file - * - * @param array $array_selected_sorted Array with list of field to export - * @param resource $objp A record from a fetch with all fields from select - * @param Translate $outputlangs Object lang to translate values - * @param array $array_types Array with types of fields - * @return int <0 if KO, >0 if OK - */ - public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types) - { - // phpcs:enable - global $conf; - - $outputlangs->charset_output = 'UTF-8'; - // var_dump($conf->global->EXPORT_CSV_FORCE_CHARSET, "here");exit; - $this->col = 0; - - $reg = array(); - $selectlabelvalues = array(); - foreach ($array_selected_sorted as $code => $value) { - if (strpos($code, ' as ') == 0) { - $alias = str_replace(array('.', '-', '(', ')'), '_', $code); - } else { - $alias = substr($code, strpos($code, ' as ') + 4); - } - if (empty($alias)) { - dol_print_error('', 'Bad value for field with key='.$code.'. Try to redefine export.'); - } - - $newvalue = $outputlangs->convToOutputCharset($objp->$alias); // objp->$alias must be utf8 encoded as any var in memory // newvalue is now $outputlangs->charset_output encoded - $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; - - // Translation newvalue - if (preg_match('/^\((.*)\)$/i', $newvalue, $reg)) { - $newvalue = $outputlangs->transnoentities($reg[1]); - } - - // Clean data and add encloser if required (depending on value of USE_STRICT_CSV_RULES) - $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); - - if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { - $array = jsonOrUnserialize($typefield); - if (is_array($array) && !empty($newvalue)) { - $array = $array['options']; - $selectlabelvalues[$code."_label"] = $array[$newvalue]; - } else { - $selectlabelvalues[$code."_label"] = ""; - } - } - - fwrite($this->handle, $newvalue.$this->separator); - $this->col++; - } - foreach ($selectlabelvalues as $key => $value) { - fwrite($this->handle, $value.$this->separator); - $this->col++; - } - - fwrite($this->handle, "\n"); - return 0; - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Output footer into file - * - * @param Translate $outputlangs Output language object - * @return int <0 if KO, >0 if OK - */ - public function write_footer($outputlangs) - { - // phpcs:enable - return 0; - } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Close file handle - * - * @return int <0 if KO, >0 if OK - */ - public function close_file() - { - // phpcs:enable - fclose($this->handle); - return 0; - } - - - /** - * Clean a cell to respect rules of CSV file cells - * Note: It uses $this->separator - * Note: We keep this function public to be able to test - * - * @param string $newvalue String to clean - * @param string $charset Input AND Output character set - * @return string Value cleaned - */ - public function csvClean($newvalue, $charset) - { - global $conf; - $addquote = 0; - - // Rule Dolibarr: No HTML - //print $charset.' '.$newvalue."\n"; - //$newvalue=dol_string_nohtmltag($newvalue,0,$charset); - $newvalue = dol_htmlcleanlastbr($newvalue); - //print $charset.' '.$newvalue."\n"; - - // Rule 1 CSV: No CR, LF in cells (except if USE_STRICT_CSV_RULES is 1, we can keep record as it is but we must add quotes) - $oldvalue = $newvalue; - $newvalue = str_replace("\r", '', $newvalue); - $newvalue = str_replace("\n", '\n', $newvalue); - if (!empty($conf->global->USE_STRICT_CSV_RULES) && $oldvalue != $newvalue) { - // If we must use enclusure on text with CR/LF) - if ($conf->global->USE_STRICT_CSV_RULES == 1) { - // If we use strict CSV rules (original value must remain but we add quote) - $newvalue = $oldvalue; - } - $addquote = 1; - } - - // Rule 2 CSV: If value contains ", we must escape with ", and add " - if (preg_match('/"/', $newvalue)) { - $addquote = 1; - $newvalue = str_replace('"', '""', $newvalue); - } - - // Rule 3 CSV: If value contains separator, we must add " - if (preg_match('/'.$this->separator.'/', $newvalue)) { - $addquote = 1; - } - - return ($addquote ? '"' : '').$newvalue.($addquote ? '"' : ''); - } } diff --git a/htdocs/core/modules/export/module_export_csv.php b/htdocs/core/modules/export/module_export_csv.php new file mode 100644 index 00000000000..442c7cb628f --- /dev/null +++ b/htdocs/core/modules/export/module_export_csv.php @@ -0,0 +1,348 @@ + + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/modules/export/export_csv.modules.php + * \ingroup export + * \brief File of class to build exports with CSV format + */ + +require_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php'; + +// avoid timeout for big export +set_time_limit(0); + +/** + * Class to build export files with format CSV + */ +class ExportCsv extends ModeleExports +{ + /** + * @var string ID ex: csv, tsv, excel... + */ + public $id; + + /** + * @var string export files label + */ + public $label; + + public $extension; + + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; + + public $label_lib; + + public $version_lib; + + public $separator; + + public $handle; // Handle fichier + + /** + * getDriverId + * + * @return string + */ + public function getDriverId() + { + return $this->id; + } + + /** + * getDriverLabel + * + * @return string Return driver label + */ + public function getDriverLabel() + { + return $this->label; + } + + /** + * getDriverDesc + * + * @return string + */ + public function getDriverDesc() + { + return $this->desc; + } + + /** + * getDriverExtension + * + * @return string + */ + public function getDriverExtension() + { + return $this->extension; + } + + /** + * getDriverVersion + * + * @return string + */ + public function getDriverVersion() + { + return $this->version; + } + + /** + * getLabelLabel + * + * @return string + */ + public function getLibLabel() + { + return $this->label_lib; + } + + /** + * getLibVersion + * + * @return string + */ + public function getLibVersion() + { + return $this->version_lib; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Open output file + * + * @param string $file Path of filename to generate + * @param Translate $outputlangs Output language object + * @return int <0 if KO, >=0 if OK + */ + public function open_file($file, $outputlangs) + { + // phpcs:enable + global $langs; + + dol_syslog("ExportCsv::open_file file=".$file); + + $ret = 1; + + $outputlangs->load("exports"); + $this->handle = fopen($file, "wt"); + if (!$this->handle) { + $langs->load("errors"); + $this->error = $langs->trans("ErrorFailToCreateFile", $file); + $ret = -1; + } + + return $ret; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output header into file + * + * @param Translate $outputlangs Output language object + * @return int <0 if KO, >0 if OK + */ + public function write_header($outputlangs) + { + // phpcs:enable + return 0; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output title line into file + * + * @param array $array_export_fields_label Array with list of label of fields + * @param array $array_selected_sorted Array with list of field to export + * @param Translate $outputlangs Object lang to translate values + * @param array $array_types Array with types of fields + * @return int <0 if KO, >0 if OK + */ + public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types) + { + // phpcs:enable + global $conf; + + $outputlangs->charset_output = $conf->global->EXPORT_CSV_FORCE_CHARSET; + + $selectlabel = array(); + + foreach ($array_selected_sorted as $code => $value) { + $newvalue = $outputlangs->transnoentities($array_export_fields_label[$code]); // newvalue is now $outputlangs->charset_output encoded + $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); + + fwrite($this->handle, $newvalue.$this->separator); + $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; + + if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { + $selectlabel[$code."_label"] = $newvalue."_label"; + } + } + foreach ($selectlabel as $key => $value) { + fwrite($this->handle, $value.$this->separator); + } + fwrite($this->handle, "\n"); + return 0; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output record line into file + * + * @param array $array_selected_sorted Array with list of field to export + * @param resource $objp A record from a fetch with all fields from select + * @param Translate $outputlangs Object lang to translate values + * @param array $array_types Array with types of fields + * @return int <0 if KO, >0 if OK + */ + public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types) + { + // phpcs:enable + global $conf; + + $outputlangs->charset_output = $conf->global->EXPORT_CSV_FORCE_CHARSET; + + $this->col = 0; + + $reg = array(); + $selectlabelvalues = array(); + foreach ($array_selected_sorted as $code => $value) { + if (strpos($code, ' as ') == 0) { + $alias = str_replace(array('.', '-', '(', ')'), '_', $code); + } else { + $alias = substr($code, strpos($code, ' as ') + 4); + } + if (empty($alias)) { + dol_print_error('', 'Bad value for field with key='.$code.'. Try to redefine export.'); + } + + $newvalue = $outputlangs->convToOutputCharset($objp->$alias); // objp->$alias must be utf8 encoded as any var in memory // newvalue is now $outputlangs->charset_output encoded + $typefield = isset($array_types[$code]) ? $array_types[$code] : ''; + + // Translation newvalue + if (preg_match('/^\((.*)\)$/i', $newvalue, $reg)) { + $newvalue = $outputlangs->transnoentities($reg[1]); + } + + // Clean data and add encloser if required (depending on value of USE_STRICT_CSV_RULES) + $newvalue = $this->csvClean($newvalue, $outputlangs->charset_output); + + if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) { + $array = jsonOrUnserialize($typefield); + if (is_array($array) && !empty($newvalue)) { + $array = $array['options']; + $selectlabelvalues[$code."_label"] = $array[$newvalue]; + } else { + $selectlabelvalues[$code."_label"] = ""; + } + } + + fwrite($this->handle, $newvalue.$this->separator); + $this->col++; + } + foreach ($selectlabelvalues as $key => $value) { + fwrite($this->handle, $value.$this->separator); + $this->col++; + } + + fwrite($this->handle, "\n"); + return 0; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output footer into file + * + * @param Translate $outputlangs Output language object + * @return int <0 if KO, >0 if OK + */ + public function write_footer($outputlangs) + { + // phpcs:enable + return 0; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Close file handle + * + * @return int <0 if KO, >0 if OK + */ + public function close_file() + { + // phpcs:enable + fclose($this->handle); + return 0; + } + + + /** + * Clean a cell to respect rules of CSV file cells + * Note: It uses $this->separator + * Note: We keep this function public to be able to test + * + * @param string $newvalue String to clean + * @param string $charset Input AND Output character set + * @return string Value cleaned + */ + public function csvClean($newvalue, $charset) + { + global $conf; + $addquote = 0; + + // Rule Dolibarr: No HTML + //print $charset.' '.$newvalue."\n"; + //$newvalue=dol_string_nohtmltag($newvalue,0,$charset); + $newvalue = dol_htmlcleanlastbr($newvalue); + //print $charset.' '.$newvalue."\n"; + + // Rule 1 CSV: No CR, LF in cells (except if USE_STRICT_CSV_RULES is 1, we can keep record as it is but we must add quotes) + $oldvalue = $newvalue; + $newvalue = str_replace("\r", '', $newvalue); + $newvalue = str_replace("\n", '\n', $newvalue); + if (!empty($conf->global->USE_STRICT_CSV_RULES) && $oldvalue != $newvalue) { + // If we must use enclusure on text with CR/LF) + if ($conf->global->USE_STRICT_CSV_RULES == 1) { + // If we use strict CSV rules (original value must remain but we add quote) + $newvalue = $oldvalue; + } + $addquote = 1; + } + + // Rule 2 CSV: If value contains ", we must escape with ", and add " + if (preg_match('/"/', $newvalue)) { + $addquote = 1; + $newvalue = str_replace('"', '""', $newvalue); + } + + // Rule 3 CSV: If value contains separator, we must add " + if (preg_match('/'.$this->separator.'/', $newvalue)) { + $addquote = 1; + } + + return ($addquote ? '"' : '').$newvalue.($addquote ? '"' : ''); + } +} From 28d0f492f487922e59a042ff36142da37b9d4477 Mon Sep 17 00:00:00 2001 From: FLIO Date: Tue, 17 Jan 2023 18:26:19 +0100 Subject: [PATCH 009/417] Create class module export csv --- htdocs/core/modules/export/export_csviso.modules.php | 2 +- htdocs/core/modules/export/export_csvutf8.modules.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/export/export_csviso.modules.php b/htdocs/core/modules/export/export_csviso.modules.php index b477868c09c..573dbdcadd0 100644 --- a/htdocs/core/modules/export/export_csviso.modules.php +++ b/htdocs/core/modules/export/export_csviso.modules.php @@ -31,7 +31,7 @@ set_time_limit(0); */ class ExportCsvIso extends ExportCsv { - + /** * Constructor * diff --git a/htdocs/core/modules/export/export_csvutf8.modules.php b/htdocs/core/modules/export/export_csvutf8.modules.php index f8b254cabe9..13000c00e25 100644 --- a/htdocs/core/modules/export/export_csvutf8.modules.php +++ b/htdocs/core/modules/export/export_csvutf8.modules.php @@ -31,7 +31,7 @@ set_time_limit(0); */ class ExportCsvUtf8 extends ExportCsv { - + /** * Constructor * From cb9e2a1bdfba1bf7a74d2d181c7799e575d5730f Mon Sep 17 00:00:00 2001 From: Jeritiana Ravelojaona Date: Sat, 21 Jan 2023 14:05:56 +0300 Subject: [PATCH 010/417] Update htdocs/core/login/functions_openid_connect.php Co-authored-by: Florent Poinsaut <1256948+FlorentPoinsaut@users.noreply.github.com> --- htdocs/core/login/functions_openid_connect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php index 5be96b213ea..53741347e66 100644 --- a/htdocs/core/login/functions_openid_connect.php +++ b/htdocs/core/login/functions_openid_connect.php @@ -46,7 +46,7 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit // OIDC does not require credentials here: pass on to next auth handler $_SESSION["dol_loginmesg"] = "Not an OpenID Connect flow"; dol_syslog("functions_openid_connect::check_user_password_openid_connect not an OIDC flow"); - } elseif (GETPOSTISSET['code']) { + } elseif (GETPOSTISSET('code')) { $auth_code = GETPOST('code', 'aZ09'); dol_syslog("functions_openid_connect::check_user_password_openid_connect code=".$auth_code); From 1d962a40ecbecf9824670b1a11ace23f52db13a0 Mon Sep 17 00:00:00 2001 From: Jeritiana Ravelojaona Date: Sat, 21 Jan 2023 14:06:09 +0300 Subject: [PATCH 011/417] Update htdocs/core/login/functions_openid_connect.php Co-authored-by: Florent Poinsaut <1256948+FlorentPoinsaut@users.noreply.github.com> --- htdocs/core/login/functions_openid_connect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php index 53741347e66..93fea1bb566 100644 --- a/htdocs/core/login/functions_openid_connect.php +++ b/htdocs/core/login/functions_openid_connect.php @@ -56,7 +56,7 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit 'client_id' => $conf->global->MAIN_AUTHENTICATION_OIDC_CLIENT_ID, 'client_secret' => $conf->global->MAIN_AUTHENTICATION_OIDC_CLIENT_SECRET, 'code' => $auth_code, - 'redirect_uri' => $conf->global->MAIN_AUTHENTICATION_OIDC_REDIRECT_URL + 'redirect_uri' => $conf->global->MAIN_AUTHENTICATION_OIDC_REDIRECT_URL ]; $token_response = getURLContent($conf->global->MAIN_AUTHENTICATION_OIDC_TOKEN_URL, 'POST', http_build_query($auth_param)); From b1ea162104c9fb7091a5be6fca9d2539b70e2689 Mon Sep 17 00:00:00 2001 From: Jeritiana Ravelojaona Date: Sat, 21 Jan 2023 14:06:23 +0300 Subject: [PATCH 012/417] Update htdocs/core/login/functions_openid_connect.php Co-authored-by: Florent Poinsaut <1256948+FlorentPoinsaut@users.noreply.github.com> --- htdocs/core/login/functions_openid_connect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php index 93fea1bb566..7bc459902b1 100644 --- a/htdocs/core/login/functions_openid_connect.php +++ b/htdocs/core/login/functions_openid_connect.php @@ -76,7 +76,7 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit $login_claim = $conf->global->MAIN_AUTHENTICATION_OIDC_LOGIN_CLAIM; } - if (array_key_exists($login_claim, $userinfo_content)) { + if (property_exists($userinfo_content, $login_claim)) { // Success: retrieve claim to return to Dolibarr as login $login = $userinfo_content->$login_claim; $_SESSION["dol_loginmesg"] = ""; From 37bd06d9bcc9b69f579658f92fb9c3f81f6ff4fa Mon Sep 17 00:00:00 2001 From: Jeritiana Ravelojaona Date: Sat, 21 Jan 2023 14:06:36 +0300 Subject: [PATCH 013/417] Update htdocs/core/login/functions_openid_connect.php Co-authored-by: Florent Poinsaut <1256948+FlorentPoinsaut@users.noreply.github.com> --- htdocs/core/login/functions_openid_connect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php index 7bc459902b1..db6281f14d1 100644 --- a/htdocs/core/login/functions_openid_connect.php +++ b/htdocs/core/login/functions_openid_connect.php @@ -63,7 +63,7 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit $token_content = json_decode($token_response['content']); dol_syslog("functions_openid_connect::check_user_password_openid_connect /token=".print_r($token_response, true), LOG_DEBUG); - if ($token_content->access_token) { + if (property_exists($token_content, 'access_token')) { // Step 3: retrieve user info using token $userinfo_headers = array('Authorization: Bearer '.$token_content->access_token); $userinfo_response = getURLContent($conf->global->MAIN_AUTHENTICATION_OIDC_USERINFO_URL, 'GET', '', 1, $userinfo_headers); From 881c2f833fb41c2d04a9c77eab0535fb32681cba Mon Sep 17 00:00:00 2001 From: Jeritiana Ravelojaona Date: Sat, 21 Jan 2023 14:06:48 +0300 Subject: [PATCH 014/417] Update htdocs/core/login/functions_openid_connect.php Co-authored-by: Florent Poinsaut <1256948+FlorentPoinsaut@users.noreply.github.com> --- htdocs/core/login/functions_openid_connect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php index db6281f14d1..fbdca8a8706 100644 --- a/htdocs/core/login/functions_openid_connect.php +++ b/htdocs/core/login/functions_openid_connect.php @@ -34,7 +34,7 @@ include_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; */ function check_user_password_openid_connect($usertotest, $passwordtotest, $entitytotest) { - global $conf; + global $db, $conf, $langs; dol_syslog("functions_openid_connect::check_user_password_openid_connect"); From dc12fdbef447dbb9ecca9fc6dc6c014fb704fa39 Mon Sep 17 00:00:00 2001 From: Jeritiana Ravelojaona Date: Sat, 21 Jan 2023 14:06:58 +0300 Subject: [PATCH 015/417] Update htdocs/core/login/functions_openid_connect.php Co-authored-by: Florent Poinsaut <1256948+FlorentPoinsaut@users.noreply.github.com> --- .../core/login/functions_openid_connect.php | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php index fbdca8a8706..ea72235ec29 100644 --- a/htdocs/core/login/functions_openid_connect.php +++ b/htdocs/core/login/functions_openid_connect.php @@ -78,8 +78,33 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit if (property_exists($userinfo_content, $login_claim)) { // Success: retrieve claim to return to Dolibarr as login - $login = $userinfo_content->$login_claim; - $_SESSION["dol_loginmesg"] = ""; + $sql = 'SELECT login, entity, datestartvalidity, dateendvalidity'; + $sql .= ' FROM '.MAIN_DB_PREFIX.'user'; + $sql .= " WHERE login = '".$userinfo_content->$login_claim."'"; + $sql .= ' AND entity IN (0,'.(array_key_exists('dol_entity', $_SESSION) ? ((int) $_SESSION["dol_entity"]) : 1).')'; + + dol_syslog("functions_openid::check_user_password_openid", LOG_DEBUG); + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $now = dol_now(); + if ($obj->datestartvalidity && $db->jdate($obj->datestartvalidity) > $now) { + // Load translation files required by the page + $langs->loadLangs(array('main', 'errors')); + $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity"); + return '--bad-login-validity--'; + } + if ($obj->dateendvalidity && $db->jdate($obj->dateendvalidity) < dol_get_first_hour($now)) { + // Load translation files required by the page + $langs->loadLangs(array('main', 'errors')); + $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity"); + return '--bad-login-validity--'; + } + + $login = $obj->login; + } + } } elseif ($userinfo_content->error) { // Got user info response but content is an error $_SESSION["dol_loginmesg"] = "Error in OAuth 2.0 flow (".$userinfo_content->error_description.")"; From 8e1a753e3f6ab12f221e279edcf89768dad58e33 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sat, 21 Jan 2023 11:07:27 +0000 Subject: [PATCH 016/417] Fixing style errors. --- htdocs/core/login/functions_openid_connect.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/login/functions_openid_connect.php b/htdocs/core/login/functions_openid_connect.php index ea72235ec29..dcff99adaad 100644 --- a/htdocs/core/login/functions_openid_connect.php +++ b/htdocs/core/login/functions_openid_connect.php @@ -82,7 +82,7 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit $sql .= ' FROM '.MAIN_DB_PREFIX.'user'; $sql .= " WHERE login = '".$userinfo_content->$login_claim."'"; $sql .= ' AND entity IN (0,'.(array_key_exists('dol_entity', $_SESSION) ? ((int) $_SESSION["dol_entity"]) : 1).')'; - + dol_syslog("functions_openid::check_user_password_openid", LOG_DEBUG); $resql = $db->query($sql); if ($resql) { @@ -101,7 +101,7 @@ function check_user_password_openid_connect($usertotest, $passwordtotest, $entit $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity"); return '--bad-login-validity--'; } - + $login = $obj->login; } } From c8c998044b3ada2e4d0f4a7c312af34d2324d6c8 Mon Sep 17 00:00:00 2001 From: FLIO Date: Tue, 7 Feb 2023 12:13:34 +0100 Subject: [PATCH 017/417] feature renamed the module_export_csv file and edited the iso and utf files to override the write_title and write_record functions to initialize EXPORT_CSV_FORCE_CHARSET --- ..._export_csv.php => export_csv.modules.php} | 0 .../modules/export/export_csviso.modules.php | 38 +++++++++++++++++- .../modules/export/export_csvutf8.modules.php | 40 +++++++++++++++++-- 3 files changed, 74 insertions(+), 4 deletions(-) rename htdocs/core/modules/export/{module_export_csv.php => export_csv.modules.php} (100%) diff --git a/htdocs/core/modules/export/module_export_csv.php b/htdocs/core/modules/export/export_csv.modules.php similarity index 100% rename from htdocs/core/modules/export/module_export_csv.php rename to htdocs/core/modules/export/export_csv.modules.php diff --git a/htdocs/core/modules/export/export_csviso.modules.php b/htdocs/core/modules/export/export_csviso.modules.php index 573dbdcadd0..ad40e7ae807 100644 --- a/htdocs/core/modules/export/export_csviso.modules.php +++ b/htdocs/core/modules/export/export_csviso.modules.php @@ -21,7 +21,7 @@ * \brief File of class to build exports with CSV format */ -require_once DOL_DOCUMENT_ROOT.'/core/modules/export/module_export_csv.php'; +require_once DOL_DOCUMENT_ROOT.'/core/modules/export/export_csv.modules.php'; // avoid timeout for big export set_time_limit(0); @@ -62,4 +62,40 @@ class ExportCsvIso extends ExportCsv $this->label_lib = 'Dolibarr'; $this->version_lib = DOL_VERSION; } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output title line into file + * + * @param array $array_export_fields_label Array with list of label of fields + * @param array $array_selected_sorted Array with list of field to export + * @param Translate $outputlangs Object lang to translate values + * @param array $array_types Array with types of fields + * @return int <0 if KO, >0 if OK + */ + public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types) + { + global $conf; + $conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1'; + + parent::write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output record line into file + * + * @param array $array_selected_sorted Array with list of field to export + * @param resource $objp A record from a fetch with all fields from select + * @param Translate $outputlangs Object lang to translate values + * @param array $array_types Array with types of fields + * @return int <0 if KO, >0 if OK + */ + public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types) + { + global $conf; + $conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1'; + + parent::write_record($array_selected_sorted, $objp, $outputlangs, $array_types); + } } diff --git a/htdocs/core/modules/export/export_csvutf8.modules.php b/htdocs/core/modules/export/export_csvutf8.modules.php index 13000c00e25..bc6a7d70d49 100644 --- a/htdocs/core/modules/export/export_csvutf8.modules.php +++ b/htdocs/core/modules/export/export_csvutf8.modules.php @@ -21,7 +21,7 @@ * \brief File of class to build exports with CSV format */ -require_once DOL_DOCUMENT_ROOT.'/core/modules/export/module_export_csv.php'; +require_once DOL_DOCUMENT_ROOT.'/core/modules/export/export_csv.modules.php'; // avoid timeout for big export set_time_limit(0); @@ -47,8 +47,6 @@ class ExportCsvUtf8 extends ExportCsv $this->separator = $conf->global->EXPORT_CSV_SEPARATOR_TO_USE; } - $conf->global->EXPORT_CSV_FORCE_CHARSET = 'UTF-8'; - $this->escape = '"'; $this->enclosure = '"'; $this->id = 'csvutf8'; // Same value then xxx in file name export_xxx.modules.php @@ -62,4 +60,40 @@ class ExportCsvUtf8 extends ExportCsv $this->label_lib = 'Dolibarr'; $this->version_lib = DOL_VERSION; } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output title line into file + * + * @param array $array_export_fields_label Array with list of label of fields + * @param array $array_selected_sorted Array with list of field to export + * @param Translate $outputlangs Object lang to translate values + * @param array $array_types Array with types of fields + * @return int <0 if KO, >0 if OK + */ + public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types) + { + global $conf; + $conf->global->EXPORT_CSV_FORCE_CHARSET = 'UTF-8'; + + parent::write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Output record line into file + * + * @param array $array_selected_sorted Array with list of field to export + * @param resource $objp A record from a fetch with all fields from select + * @param Translate $outputlangs Object lang to translate values + * @param array $array_types Array with types of fields + * @return int <0 if KO, >0 if OK + */ + public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types) + { + global $conf; + + $conf->global->EXPORT_CSV_FORCE_CHARSET = 'UTF-8'; + parent::write_record($array_selected_sorted, $objp, $outputlangs, $array_types); + } } From c000eeeecf18c5fdb5890e1f1332270c703c4c5c Mon Sep 17 00:00:00 2001 From: FLIO Date: Thu, 16 Feb 2023 01:00:39 +0100 Subject: [PATCH 018/417] feature (#21426) edit ExportTest for resolve error and add test for utf8 --- test/phpunit/ExportTest.php | 102 ++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 3 deletions(-) diff --git a/test/phpunit/ExportTest.php b/test/phpunit/ExportTest.php index cf2f0520908..0a0a1c867ba 100644 --- a/test/phpunit/ExportTest.php +++ b/test/phpunit/ExportTest.php @@ -149,6 +149,94 @@ class ExportTest extends PHPUnit\Framework\TestCase print __METHOD__."\n"; } + /** + * Other tests + * + * @return void + */ + public function testExportCsvUtf() + { + global $conf,$user,$langs,$db; + + $model='csvutf8'; + + $conf->global->EXPORT_CSV_SEPARATOR_TO_USE = ','; + print 'EXPORT_CSV_SEPARATOR_TO_USE = '.$conf->global->EXPORT_CSV_SEPARATOR_TO_USE; + + // Creation of class to export using model ExportXXX + $dir = DOL_DOCUMENT_ROOT . "/core/modules/export/"; + $file = "export_".$model.".modules.php"; + $classname = "Export".$model; + require_once $dir.$file; + $objmodel = new $classname($db); + + // First test without option USE_STRICT_CSV_RULES + unset($conf->global->USE_STRICT_CSV_RULES); + + $valtotest='A simple string'; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, 'A simple string'); + + $valtotest='A string with , and ; inside'; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, '"A string with , and ; inside"', 'Error in csvClean for '.$file); + + $valtotest='A string with " inside'; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, '"A string with "" inside"'); + + $valtotest='A string with " inside and '."\r\n".' carriage returns'; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, '"A string with "" inside and \n carriage returns"'); + + $valtotest='A string with html
content
inside
'."\n"; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, '"A string with html
content
inside"'); + + // Same tests with strict mode + $conf->global->USE_STRICT_CSV_RULES = 1; + + $valtotest='A simple string'; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, 'A simple string'); + + $valtotest='A string with , and ; inside'; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, '"A string with , and ; inside"'); + + $valtotest='A string with " inside'; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, '"A string with "" inside"'); + + $valtotest='A string with " inside and '."\r\n".' carriage returns'; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, "\"A string with \"\" inside and \r\n carriage returns\""); + + $valtotest='A string with html
content
inside
'."\n"; + print __METHOD__." valtotest=".$valtotest."\n"; + $result = $objmodel->csvClean($valtotest, $langs->charset_output); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, '"A string with html
content
inside"'); + } + /** * Other tests @@ -159,7 +247,7 @@ class ExportTest extends PHPUnit\Framework\TestCase { global $conf,$user,$langs,$db; - $model='csv'; + $model='csviso'; $conf->global->EXPORT_CSV_SEPARATOR_TO_USE = ','; print 'EXPORT_CSV_SEPARATOR_TO_USE = '.$conf->global->EXPORT_CSV_SEPARATOR_TO_USE; @@ -263,7 +351,15 @@ class ExportTest extends PHPUnit\Framework\TestCase dol_mkdir($conf->export->dir_temp); - $model='csv'; + $model='csviso'; + + // Build export file + print "Process build_file for model = ".$model."\n"; + $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql); + $expectedresult = 1; + $this->assertEquals($expectedresult, $result, 'Error in CSV export'); + + $model='csvutf8'; // Build export file print "Process build_file for model = ".$model."\n"; @@ -353,7 +449,7 @@ class ExportTest extends PHPUnit\Framework\TestCase { global $conf,$user,$langs,$db; - $model='csv'; + $model='csviso'; $filterdatatoexport=''; //$filterdatatoexport=''; From cfe6ebfeee54fc313bb6ae58504ec03e377c6385 Mon Sep 17 00:00:00 2001 From: FLIO Date: Wed, 22 Feb 2023 10:29:47 +0100 Subject: [PATCH 019/417] fix (#21426) edit file name of export_csv.modules because it adds an export type when choosing the export type --- htdocs/core/modules/export/export_csviso.modules.php | 2 +- htdocs/core/modules/export/export_csvutf8.modules.php | 2 +- .../export/{export_csv.modules.php => exports_csv.modules.php} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename htdocs/core/modules/export/{export_csv.modules.php => exports_csv.modules.php} (100%) diff --git a/htdocs/core/modules/export/export_csviso.modules.php b/htdocs/core/modules/export/export_csviso.modules.php index ad40e7ae807..29a9e24e76a 100644 --- a/htdocs/core/modules/export/export_csviso.modules.php +++ b/htdocs/core/modules/export/export_csviso.modules.php @@ -21,7 +21,7 @@ * \brief File of class to build exports with CSV format */ -require_once DOL_DOCUMENT_ROOT.'/core/modules/export/export_csv.modules.php'; +require_once DOL_DOCUMENT_ROOT.'/core/modules/export/exports_csv.modules.php'; // avoid timeout for big export set_time_limit(0); diff --git a/htdocs/core/modules/export/export_csvutf8.modules.php b/htdocs/core/modules/export/export_csvutf8.modules.php index bc6a7d70d49..f517dd00839 100644 --- a/htdocs/core/modules/export/export_csvutf8.modules.php +++ b/htdocs/core/modules/export/export_csvutf8.modules.php @@ -21,7 +21,7 @@ * \brief File of class to build exports with CSV format */ -require_once DOL_DOCUMENT_ROOT.'/core/modules/export/export_csv.modules.php'; +require_once DOL_DOCUMENT_ROOT.'/core/modules/export/exports_csv.modules.php'; // avoid timeout for big export set_time_limit(0); diff --git a/htdocs/core/modules/export/export_csv.modules.php b/htdocs/core/modules/export/exports_csv.modules.php similarity index 100% rename from htdocs/core/modules/export/export_csv.modules.php rename to htdocs/core/modules/export/exports_csv.modules.php From 91f39fb4f412b10b964c7be3c38407bddf3bb8f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Courtier?= Date: Mon, 20 Mar 2023 11:36:28 +0100 Subject: [PATCH 020/417] FIX: Correct Evaluation for extrafields --- htdocs/core/class/commonobject.class.php | 6 +++--- htdocs/core/class/extrafields.class.php | 14 +++++++------- htdocs/core/tpl/extrafields_view.tpl.php | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index e7d2c61bd4c..9bda1575d37 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -8110,7 +8110,7 @@ abstract class CommonObject // Test on 'enabled' ('enabled' is different than 'list' = 'visibility') $enabled = 1; if ($enabled && isset($extrafields->attributes[$this->table_element]['enabled'][$key])) { - $enabled = dol_eval($extrafields->attributes[$this->table_element]['enabled'][$key], 1, 1, '1'); + $enabled = dol_eval($extrafields->attributes[$this->table_element]['enabled'][$key], 1, 1, '2'); } if (empty($enabled)) { continue; @@ -8118,12 +8118,12 @@ abstract class CommonObject $visibility = 1; if ($visibility && isset($extrafields->attributes[$this->table_element]['list'][$key])) { - $visibility = dol_eval($extrafields->attributes[$this->table_element]['list'][$key], 1, 1, '1'); + $visibility = dol_eval($extrafields->attributes[$this->table_element]['list'][$key], 1, 1, '2'); } $perms = 1; if ($perms && isset($extrafields->attributes[$this->table_element]['perms'][$key])) { - $perms = dol_eval($extrafields->attributes[$this->table_element]['perms'][$key], 1, 1, '1'); + $perms = dol_eval($extrafields->attributes[$this->table_element]['perms'][$key], 1, 1, '2'); } if (($mode == 'create') && abs($visibility) != 1 && abs($visibility) != 3) { diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 5d91febc65d..a1150fb97fc 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -958,9 +958,9 @@ class ExtraFields $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key]; $required = $this->attributes[$extrafieldsobjectkey]['required'][$key]; $param = $this->attributes[$extrafieldsobjectkey]['param'][$key]; - $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '1'); + $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2'); $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key]; - $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '1'); + $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2'); $totalizable = $this->attributes[$extrafieldsobjectkey]['totalizable'][$key]; $help = $this->attributes[$extrafieldsobjectkey]['help'][$key]; $hidden = (empty($list) ? 1 : 0); // If empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller) @@ -1591,9 +1591,9 @@ class ExtraFields $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key]; $required = $this->attributes[$extrafieldsobjectkey]['required'][$key]; $param = $this->attributes[$extrafieldsobjectkey]['param'][$key]; - $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '1'); + $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2'); $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key]; - $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '1'); + $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2'); $help = $this->attributes[$extrafieldsobjectkey]['help'][$key]; $hidden = (empty($list) ? 1 : 0); // If $list empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller) @@ -2080,17 +2080,17 @@ class ExtraFields $enabled = 1; if (isset($this->attributes[$object->table_element]['enabled'][$key])) { // 'enabled' is often a condition on module enabled or not - $enabled = dol_eval($this->attributes[$object->table_element]['enabled'][$key], 1, 1, '1'); + $enabled = dol_eval($this->attributes[$object->table_element]['enabled'][$key], 1, 1, '2'); } $visibility = 1; if (isset($this->attributes[$object->table_element]['list'][$key])) { // 'list' is option for visibility - $visibility = intval(dol_eval($this->attributes[$object->table_element]['list'][$key], 1, 1, '1')); + $visibility = intval(dol_eval($this->attributes[$object->table_element]['list'][$key], 1, 1, '2')); } $perms = 1; if (isset($this->attributes[$object->table_element]['perms'][$key])) { - $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1, 1, '1'); + $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1, 1, '2'); } if (empty($enabled) || ( diff --git a/htdocs/core/tpl/extrafields_view.tpl.php b/htdocs/core/tpl/extrafields_view.tpl.php index 7d99a021f69..c75317471fb 100644 --- a/htdocs/core/tpl/extrafields_view.tpl.php +++ b/htdocs/core/tpl/extrafields_view.tpl.php @@ -72,15 +72,15 @@ if (empty($reshook) && isset($extrafields->attributes[$object->table_element]['l $enabled = 1; if ($enabled && isset($extrafields->attributes[$object->table_element]['enabled'][$tmpkeyextra])) { - $enabled = dol_eval($extrafields->attributes[$object->table_element]['enabled'][$tmpkeyextra], 1); + $enabled = dol_eval($extrafields->attributes[$object->table_element]['enabled'][$tmpkeyextra], 1, 1, '2'); } if ($enabled && isset($extrafields->attributes[$object->table_element]['list'][$tmpkeyextra])) { - $enabled = dol_eval($extrafields->attributes[$object->table_element]['list'][$tmpkeyextra], 1); + $enabled = dol_eval($extrafields->attributes[$object->table_element]['list'][$tmpkeyextra], 1, 1, '2'); } $perms = 1; if ($perms && isset($extrafields->attributes[$object->table_element]['perms'][$tmpkeyextra])) { - $perms = dol_eval($extrafields->attributes[$object->table_element]['perms'][$tmpkeyextra], 1); + $perms = dol_eval($extrafields->attributes[$object->table_element]['perms'][$tmpkeyextra], 1, 1, '2'); } //print $tmpkeyextra.'-'.$enabled.'-'.$perms.'
'."\n"; From d4f20df3ea174a49a53056c8d1c00131eb6c6e78 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Tue, 28 Mar 2023 13:52:20 +0200 Subject: [PATCH 021/417] FIX : no usage of the function updateProduction in the update function --- htdocs/mrp/class/mo.class.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 9c27a21b1f5..43b6adac644 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -612,11 +612,6 @@ class Mo extends CommonObject $error++; } - $result = $this->updateProduction($user, $notrigger); - if ($result <= 0) { - $error++; - } - if (!$error) { $this->db->commit(); return 1; From 620cbf398ab1790f489ff2fadfa5d68ff1b9fcdb Mon Sep 17 00:00:00 2001 From: kkhelifa Date: Thu, 30 Mar 2023 11:10:22 +0200 Subject: [PATCH 022/417] Correction --- htdocs/core/class/commonobject.class.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 95bf1085637..6380730816f 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5992,6 +5992,8 @@ abstract class CommonObject case 'chkbxlst': if (is_array($this->array_options[$key])) { $new_array_options[$key] = implode(',', $this->array_options[$key]); + } else { + $new_array_options[$key] = $this->array_options[$key]; } break; } @@ -6343,6 +6345,8 @@ abstract class CommonObject case 'chkbxlst': if (is_array($this->array_options[$key])) { $new_array_options[$key] = implode(',', $this->array_options[$key]); + } else { + $new_array_options[$key] = $this->array_options[$key]; } break; } From 1d59cdc41b346b88e0b27616190e2fb5e5267ef7 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Mon, 3 Apr 2023 10:13:11 +0200 Subject: [PATCH 023/417] FIX : Add the possibility to events oxwner to check their events from the list when the perm "Read the actions (events or tasks) of others" is not active --- htdocs/comm/action/class/actioncomm.class.php | 2 +- htdocs/comm/action/list.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index cf45a7d70d0..d930ea96b2c 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -1566,7 +1566,7 @@ class ActionComm extends CommonObject } $canread = 0; - if ($user->rights->agenda->myactions->read && $this->authorid == $user->id) { + if ($user->rights->agenda->myactions->read && ($this->authorid == $user->id || $this->userownerid == $user->id)) { $canread = 1; // Can read my event } if ($user->rights->agenda->myactions->read && array_key_exists($user->id, $this->userassigned)) { diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index c9f0f31391f..bd1f628f55c 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -917,6 +917,7 @@ while ($i < $imaxinloop) { $actionstatic->datep = $db->jdate($obj->dp); $actionstatic->percentage = $obj->percent; $actionstatic->authorid = $obj->fk_user_author; + $actionstatic->userownerid = $obj->fk_user_action; // Initialize $this->userassigned && this->socpeopleassigned array && this->userownerid // but only if we need it From 805d457be11d32e62043bf67118f751902d71a19 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Mon, 3 Apr 2023 16:54:37 +0200 Subject: [PATCH 024/417] FIX : redesign of the function : updateProduction --- htdocs/mrp/class/mo.class.php | 99 ++++++----------------------------- htdocs/mrp/mo_card.php | 2 + 2 files changed, 19 insertions(+), 82 deletions(-) diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 43b6adac644..7745d05d71a 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -631,93 +631,28 @@ class Mo extends CommonObject public function updateProduction(User $user, $notrigger = true) { $error = 0; - $role = ""; - if ($this->status != self::STATUS_DRAFT) { - //$this->error = 'BadStatusForUpdateProduction'; - //return -1; - return 1; - } + if ($this->status != self::STATUS_DRAFT) return 1; $this->db->begin(); - // Insert lines in mrp_production table from BOM data - if (!$error) { - // TODO Check that production has not started. If yes, we stop here. + $oldQty = $this->oldQty; + $newQty = $this->qty; + if($newQty != $oldQty) { + $sql = 'SELECT rowid FROM ' . MAIN_DB_PREFIX . 'mrp_production WHERE fk_mo = ' . $this->id; + $resql = $this->db->query($sql); + if($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $moLine = new MoLine($this->db); + $res = $moLine->fetch($obj->rowid); + if(!$res) $error++; - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'mrp_production WHERE fk_mo = '.((int) $this->id); - $this->db->query($sql); - - $moline = new MoLine($this->db); - - // Line to produce - $moline->fk_mo = $this->id; - $moline->qty = $this->qty; - $moline->fk_product = $this->fk_product; - $moline->position = 1; - - if ($this->fk_bom > 0) { // If a BOM is defined, we know what to produce. - include_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php'; - $bom = new Bom($this->db); - $bom->fetch($this->fk_bom); - if ($bom->bomtype == 1) { - $role = 'toproduce'; - $moline->role = 'toconsume'; - } else { - $role = 'toconsume'; - $moline->role = 'toproduce'; - } - } else { - if ($this->mrptype == 1) { - $moline->role = 'toconsume'; - } else { - $moline->role = 'toproduce'; - } - } - - $resultline = $moline->create($user, false); // Never use triggers here - if ($resultline <= 0) { - $error++; - $this->error = $moline->error; - $this->errors = $moline->errors; - dol_print_error($this->db, $moline->error, $moline->errors); - } - - if ($this->fk_bom > 0) { // If a BOM is defined, we know what to consume. - if ($bom->id > 0) { - // Lines to consume - if (!$error) { - foreach ($bom->lines as $line) { - $moline = new MoLine($this->db); - - $moline->fk_mo = $this->id; - $moline->origin_id = $line->id; - $moline->origin_type = 'bomline'; - if ($line->qty_frozen) { - $moline->qty = $line->qty; // Qty to consume does not depends on quantity to produce - } else { - $moline->qty = price2num(($line->qty / ( !empty($bom->qty) ? $bom->qty : 1 ) ) * $this->qty / ( !empty($line->efficiency) ? $line->efficiency : 1 ), 'MS'); // Calculate with Qty to produce and more presition - } - if ($moline->qty <= 0) { - $error++; - $this->error = "BadValueForquantityToConsume"; - break; - } else { - $moline->fk_product = $line->fk_product; - $moline->role = $role; - $moline->position = $line->position; - $moline->qty_frozen = $line->qty_frozen; - $moline->disable_stock_change = $line->disable_stock_change; - - $resultline = $moline->create($user, false); // Never use triggers here - if ($resultline <= 0) { - $error++; - $this->error = $moline->error; - $this->errors = $moline->errors; - dol_print_error($this->db, $moline->error, $moline->errors); - break; - } - } + if($moLine->role == 'toconsume' || $moLine->role == 'toproduce') { + if (empty($moLine->qty_frozen)) { + $qty = $newQty * $moLine->qty / $oldQty; + $moLine->qty = price2num($qty * (!empty($line->efficiency) ? $line->efficiency : 1 ), 'MS'); // Calculate with Qty to produce and more presition + $res = $moLine->update($user); + if(!$res) $error++; } } } diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php index b3a4b3aced8..8a460056a13 100644 --- a/htdocs/mrp/mo_card.php +++ b/htdocs/mrp/mo_card.php @@ -123,6 +123,8 @@ if (empty($reshook)) { $backurlforlist = dol_buildpath('/mrp/mo_list.php', 1); + $object->oldQty = $object->qty; + if (empty($backtopage) || ($cancel && empty($id))) { if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { From 700efad2355a6a2ecabc5a1d710c3477a165a8a9 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 3 Apr 2023 15:00:40 +0000 Subject: [PATCH 025/417] Fixing style errors. --- htdocs/mrp/class/mo.class.php | 10 +++++----- htdocs/mrp/mo_card.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 7745d05d71a..8e0b94ccb5b 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -638,21 +638,21 @@ class Mo extends CommonObject $oldQty = $this->oldQty; $newQty = $this->qty; - if($newQty != $oldQty) { + if ($newQty != $oldQty) { $sql = 'SELECT rowid FROM ' . MAIN_DB_PREFIX . 'mrp_production WHERE fk_mo = ' . $this->id; $resql = $this->db->query($sql); - if($resql) { + if ($resql) { while ($obj = $this->db->fetch_object($resql)) { $moLine = new MoLine($this->db); $res = $moLine->fetch($obj->rowid); - if(!$res) $error++; + if (!$res) $error++; - if($moLine->role == 'toconsume' || $moLine->role == 'toproduce') { + if ($moLine->role == 'toconsume' || $moLine->role == 'toproduce') { if (empty($moLine->qty_frozen)) { $qty = $newQty * $moLine->qty / $oldQty; $moLine->qty = price2num($qty * (!empty($line->efficiency) ? $line->efficiency : 1 ), 'MS'); // Calculate with Qty to produce and more presition $res = $moLine->update($user); - if(!$res) $error++; + if (!$res) $error++; } } } diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php index 8a460056a13..974e6eae4df 100644 --- a/htdocs/mrp/mo_card.php +++ b/htdocs/mrp/mo_card.php @@ -123,7 +123,7 @@ if (empty($reshook)) { $backurlforlist = dol_buildpath('/mrp/mo_list.php', 1); - $object->oldQty = $object->qty; + $object->oldQty = $object->qty; if (empty($backtopage) || ($cancel && empty($id))) { if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { From bb2bb638e622e5c5e2d1f5b230c8b9cbd88a1536 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 03:15:42 +0200 Subject: [PATCH 026/417] FIX Filter on member status --- htdocs/adherents/list.php | 5 +++-- htdocs/adherents/type.php | 4 ++-- htdocs/core/lib/functions.lib.php | 7 ++++++- htdocs/langs/en_US/members.lang | 1 + 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 64cc4fa8dc4..bcbbbd5f701 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -408,10 +408,10 @@ if ($search_filter == 'waitingsubscription') { $sql .= " AND (datefin IS NULL AND t.subscription = '1')"; } if ($search_filter == 'uptodate') { - $sql .= " AND (datefin >= '".$db->idate($now)."' OR t.subscription = '0')"; + $sql .= " AND (datefin >= '".$db->idate($now)."' OR (datefin IS NULL AND t.subscription = '0'))"; } if ($search_filter == 'outofdate') { - $sql .= " AND (datefin < '".$db->idate($now)."' AND t.subscription = '1')"; + $sql .= " AND (datefin < '".$db->idate($now)."')"; } if ($search_status != '') { // Peut valoir un nombre ou liste de nombre separes par virgules @@ -500,6 +500,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { } $db->free($resql); } +//print $sql; // Complete request and execute it with limit $sql .= $db->order($sortfield, $sortorder); diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 7361ba8fa7f..2f10848a827 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -383,7 +383,7 @@ if ($action == 'create') { print $form->selectarray("morphy", $morphys, GETPOSTISSET("morphy") ? GETPOST("morphy", 'aZ09') : 'morphy'); print ""; - print '
'; @@ -459,7 +459,7 @@ if ($rowid > 0) { print ''; print ''; - print ''; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index a5303555f71..942473a362b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7953,6 +7953,10 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, } if (is_object($object) && $object->element == 'member') { $typeforonlinepayment = 'member'; + $amounttouse = 0; + if (!empty($object->last_subscription_amount)) { + $amounttouse = $object->last_subscription_amount; + } } if (is_object($object) && $object->element == 'contrat') { $typeforonlinepayment = 'contract'; @@ -7960,7 +7964,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, if (is_object($object) && $object->element == 'fichinter') { $typeforonlinepayment = 'ficheinter'; } - $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $substitutionarray['__REF__']); + + $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $substitutionarray['__REF__'], $amounttouse); $paymenturl = $url; } diff --git a/htdocs/langs/en_US/members.lang b/htdocs/langs/en_US/members.lang index b35b704b87f..4da2b7af21b 100644 --- a/htdocs/langs/en_US/members.lang +++ b/htdocs/langs/en_US/members.lang @@ -92,6 +92,7 @@ NoTypeDefinedGoToSetup=No member types defined. Go to menu "Members types" NewMemberType=New member type WelcomeEMail=Welcome email SubscriptionRequired=Contribution required +SubscriptionRequiredDesc=If subscription is required, a subscription with a start or end date must be recorded to have the member up to date (whatever is subscription amount, even if subscription is free). DeleteType=Delete VoteAllowed=Vote allowed Physical=Individual From 87397a4d207bd35c17ea031536716a0b0f5d1b46 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Wed, 5 Apr 2023 10:48:45 +0200 Subject: [PATCH 027/417] NEW: Accountancy - Add specific page to export accounting data rather than the journals page --- htdocs/accountancy/bookkeeping/export.php | 1403 +++++++++++++++++++++ htdocs/accountancy/bookkeeping/list.php | 287 +---- htdocs/core/menus/init_menu_auguria.sql | 9 +- htdocs/core/menus/standard/eldy.lib.php | 3 + htdocs/langs/en_US/accountancy.lang | 7 +- 5 files changed, 1422 insertions(+), 287 deletions(-) create mode 100644 htdocs/accountancy/bookkeeping/export.php diff --git a/htdocs/accountancy/bookkeeping/export.php b/htdocs/accountancy/bookkeeping/export.php new file mode 100644 index 00000000000..a9dcb76ce53 --- /dev/null +++ b/htdocs/accountancy/bookkeeping/export.php @@ -0,0 +1,1403 @@ + + * Copyright (C) 2013-2016 Florian Henry + * Copyright (C) 2013-2023 Alexandre Spangaro + * Copyright (C) 2022 Lionel Vessiller + * Copyright (C) 2016-2017 Laurent Destailleur + * Copyright (C) 2018-2021 Frédéric France + * Copyright (C) 2022 Progiseize + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/accountancy/bookkeeping/export.php + * \ingroup Accountancy (Double entries) + * \brief Export operation of book keeping + */ + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php'; +require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; +require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + +// Load translation files required by the page +$langs->loadLangs(array("accountancy", "compta")); + +$socid = GETPOST('socid', 'int'); + +$action = GETPOST('action', 'aZ09'); +$massaction = GETPOST('massaction', 'alpha'); +$confirm = GETPOST('confirm', 'alpha'); +$toselect = GETPOST('toselect', 'array'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'bookkeepinglist'; +$search_mvt_num = GETPOST('search_mvt_num', 'int'); +$search_doc_type = GETPOST("search_doc_type", 'alpha'); +$search_doc_ref = GETPOST("search_doc_ref", 'alpha'); +$search_date_startyear = GETPOST('search_date_startyear', 'int'); +$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); +$search_date_startday = GETPOST('search_date_startday', 'int'); +$search_date_endyear = GETPOST('search_date_endyear', 'int'); +$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); +$search_date_endday = GETPOST('search_date_endday', 'int'); +$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); +$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); +$search_doc_date = dol_mktime(0, 0, 0, GETPOST('doc_datemonth', 'int'), GETPOST('doc_dateday', 'int'), GETPOST('doc_dateyear', 'int')); +$search_date_creation_startyear = GETPOST('search_date_creation_startyear', 'int'); +$search_date_creation_startmonth = GETPOST('search_date_creation_startmonth', 'int'); +$search_date_creation_startday = GETPOST('search_date_creation_startday', 'int'); +$search_date_creation_endyear = GETPOST('search_date_creation_endyear', 'int'); +$search_date_creation_endmonth = GETPOST('search_date_creation_endmonth', 'int'); +$search_date_creation_endday = GETPOST('search_date_creation_endday', 'int'); +$search_date_creation_start = dol_mktime(0, 0, 0, $search_date_creation_startmonth, $search_date_creation_startday, $search_date_creation_startyear); +$search_date_creation_end = dol_mktime(23, 59, 59, $search_date_creation_endmonth, $search_date_creation_endday, $search_date_creation_endyear); +$search_date_modification_startyear = GETPOST('search_date_modification_startyear', 'int'); +$search_date_modification_startmonth = GETPOST('search_date_modification_startmonth', 'int'); +$search_date_modification_startday = GETPOST('search_date_modification_startday', 'int'); +$search_date_modification_endyear = GETPOST('search_date_modification_endyear', 'int'); +$search_date_modification_endmonth = GETPOST('search_date_modification_endmonth', 'int'); +$search_date_modification_endday = GETPOST('search_date_modification_endday', 'int'); +$search_date_modification_start = dol_mktime(0, 0, 0, $search_date_modification_startmonth, $search_date_modification_startday, $search_date_modification_startyear); +$search_date_modification_end = dol_mktime(23, 59, 59, $search_date_modification_endmonth, $search_date_modification_endday, $search_date_modification_endyear); +$search_date_export_startyear = GETPOST('search_date_export_startyear', 'int'); +$search_date_export_startmonth = GETPOST('search_date_export_startmonth', 'int'); +$search_date_export_startday = GETPOST('search_date_export_startday', 'int'); +$search_date_export_endyear = GETPOST('search_date_export_endyear', 'int'); +$search_date_export_endmonth = GETPOST('search_date_export_endmonth', 'int'); +$search_date_export_endday = GETPOST('search_date_export_endday', 'int'); +$search_date_export_start = dol_mktime(0, 0, 0, $search_date_export_startmonth, $search_date_export_startday, $search_date_export_startyear); +$search_date_export_end = dol_mktime(23, 59, 59, $search_date_export_endmonth, $search_date_export_endday, $search_date_export_endyear); +$search_date_validation_startyear = GETPOST('search_date_validation_startyear', 'int'); +$search_date_validation_startmonth = GETPOST('search_date_validation_startmonth', 'int'); +$search_date_validation_startday = GETPOST('search_date_validation_startday', 'int'); +$search_date_validation_endyear = GETPOST('search_date_validation_endyear', 'int'); +$search_date_validation_endmonth = GETPOST('search_date_validation_endmonth', 'int'); +$search_date_validation_endday = GETPOST('search_date_validation_endday', 'int'); +$search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_startmonth, $search_date_validation_startday, $search_date_validation_startyear); +$search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear); +$search_import_key = GETPOST("search_import_key", 'alpha'); + +//var_dump($search_date_start);exit; +if (GETPOST("button_delmvt_x") || GETPOST("button_delmvt.x") || GETPOST("button_delmvt")) { + $action = 'delbookkeepingyear'; +} +if (GETPOST("button_export_file_x") || GETPOST("button_export_file.x") || GETPOST("button_export_file")) { + $action = 'export_file'; +} + +$search_account_category = GETPOST('search_account_category', 'int'); + +$search_accountancy_code = GETPOST("search_accountancy_code", 'alpha'); +$search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha'); +if ($search_accountancy_code_start == - 1) { + $search_accountancy_code_start = ''; +} +$search_accountancy_code_end = GETPOST('search_accountancy_code_end', 'alpha'); +if ($search_accountancy_code_end == - 1) { + $search_accountancy_code_end = ''; +} + +$search_accountancy_aux_code = GETPOST("search_accountancy_aux_code", 'alpha'); +$search_accountancy_aux_code_start = GETPOST('search_accountancy_aux_code_start', 'alpha'); +if ($search_accountancy_aux_code_start == - 1) { + $search_accountancy_aux_code_start = ''; +} +$search_accountancy_aux_code_end = GETPOST('search_accountancy_aux_code_end', 'alpha'); +if ($search_accountancy_aux_code_end == - 1) { + $search_accountancy_aux_code_end = ''; +} +$search_mvt_label = GETPOST('search_mvt_label', 'alpha'); +$search_direction = GETPOST('search_direction', 'alpha'); +$search_debit = GETPOST('search_debit', 'alpha'); +$search_credit = GETPOST('search_credit', 'alpha'); +$search_ledger_code = GETPOST('search_ledger_code', 'array'); +$search_lettering_code = GETPOST('search_lettering_code', 'alpha'); +$search_not_reconciled = GETPOST('search_not_reconciled', 'alpha'); + +// Load variable for pagination +$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$optioncss = GETPOST('optioncss', 'alpha'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page < 0) { + $page = 0; +} +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if ($sortorder == "") { + $sortorder = "ASC"; +} +if ($sortfield == "") { + $sortfield = "t.piece_num,t.rowid"; +} + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$object = new BookKeeping($db); +$hookmanager->initHooks(array('bookkeepingexport')); + +$formaccounting = new FormAccounting($db); +$form = new Form($db); + +if (!in_array($action, array('export_file', 'delmouv', 'delmouvconfirm')) && !GETPOSTISSET('begin') && !GETPOSTISSET('formfilteraction') && GETPOST('page', 'int') == '' && !GETPOST('noreset', 'int') && $user->hasRight('accounting', 'mouvements', 'export')) { + if (empty($search_date_start) && empty($search_date_end) && !GETPOSTISSET('restore_lastsearch_values') && !GETPOST('search_accountancy_code_start')) { + $query = "SELECT date_start, date_end from ".MAIN_DB_PREFIX."accounting_fiscalyear "; + $query .= " where date_start < '".$db->idate(dol_now())."' and date_end > '".$db->idate(dol_now())."' limit 1"; + $res = $db->query($query); + + if ($res->num_rows > 0) { + $fiscalYear = $db->fetch_object($res); + $search_date_start = strtotime($fiscalYear->date_start); + $search_date_end = strtotime($fiscalYear->date_end); + } else { + $month_start = ($conf->global->SOCIETE_FISCAL_MONTH_START ? ($conf->global->SOCIETE_FISCAL_MONTH_START) : 1); + $year_start = dol_print_date(dol_now(), '%Y'); + if (dol_print_date(dol_now(), '%m') < $month_start) { + $year_start--; // If current month is lower that starting fiscal month, we start last year + } + $year_end = $year_start + 1; + $month_end = $month_start - 1; + if ($month_end < 1) { + $month_end = 12; + $year_end--; + } + $search_date_start = dol_mktime(0, 0, 0, $month_start, 1, $year_start); + $search_date_end = dol_get_last_day($year_end, $month_end); + } + } +} + + +$arrayfields = array( + 't.piece_num'=>array('label'=>$langs->trans("TransactionNumShort"), 'checked'=>1), + 't.code_journal'=>array('label'=>$langs->trans("Codejournal"), 'checked'=>1), + 't.doc_date'=>array('label'=>$langs->trans("Docdate"), 'checked'=>1), + 't.doc_ref'=>array('label'=>$langs->trans("Piece"), 'checked'=>1), + 't.numero_compte'=>array('label'=>$langs->trans("AccountAccountingShort"), 'checked'=>1), + 't.subledger_account'=>array('label'=>$langs->trans("SubledgerAccount"), 'checked'=>1), + 't.label_operation'=>array('label'=>$langs->trans("Label"), 'checked'=>1), + 't.debit'=>array('label'=>$langs->trans("AccountingDebit"), 'checked'=>1), + 't.credit'=>array('label'=>$langs->trans("AccountingCredit"), 'checked'=>1), + 't.lettering_code'=>array('label'=>$langs->trans("LetteringCode"), 'checked'=>1), + 't.date_creation'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0), + 't.tms'=>array('label'=>$langs->trans("DateModification"), 'checked'=>0), + 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1), + 't.date_validated'=>array('label'=>$langs->trans("DateValidationAndLock"), 'checked'=>1, 'enabled'=>!getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")), + 't.import_key'=>array('label'=>$langs->trans("ImportId"), 'checked'=>0, 'position'=>1100), +); + +if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { + unset($arrayfields['t.lettering_code']); +} + +$accountancyexport = new AccountancyExport($db); +$listofformat = $accountancyexport->getType(); +$formatexportset = getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV'); +if (empty($listofformat[$formatexportset])) { + $formatexportset = 1; +} + +$error = 0; + +if (!isModEnabled('accounting')) { + accessforbidden(); +} +if ($user->socid > 0) { + accessforbidden(); +} +if (!$user->hasRight('accounting', 'mouvements', 'lire')) { + accessforbidden(); +} + + +/* + * Actions + */ + +$param = ''; + +if (GETPOST('cancel', 'alpha')) { + $action = 'list'; $massaction = ''; +} +if (!GETPOST('confirmmassaction', 'alpha')) { + $massaction = ''; +} + +$parameters = array('socid'=>$socid); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $search_mvt_num = ''; + $search_doc_type = ''; + $search_doc_ref = ''; + $search_doc_date = ''; + $search_account_category = ''; + $search_accountancy_code = ''; + $search_accountancy_code_start = ''; + $search_accountancy_code_end = ''; + $search_accountancy_aux_code = ''; + $search_accountancy_aux_code_start = ''; + $search_accountancy_aux_code_end = ''; + $search_mvt_label = ''; + $search_direction = ''; + $search_ledger_code = array(); + $search_date_startyear = ''; + $search_date_startmonth = ''; + $search_date_startday = ''; + $search_date_endyear = ''; + $search_date_endmonth = ''; + $search_date_endday = ''; + $search_date_start = ''; + $search_date_end = ''; + $search_date_creation_startyear = ''; + $search_date_creation_startmonth = ''; + $search_date_creation_startday = ''; + $search_date_creation_endyear = ''; + $search_date_creation_endmonth = ''; + $search_date_creation_endday = ''; + $search_date_creation_start = ''; + $search_date_creation_end = ''; + $search_date_modification_startyear = ''; + $search_date_modification_startmonth = ''; + $search_date_modification_startday = ''; + $search_date_modification_endyear = ''; + $search_date_modification_endmonth = ''; + $search_date_modification_endday = ''; + $search_date_modification_start = ''; + $search_date_modification_end = ''; + $search_date_export_startyear = ''; + $search_date_export_startmonth = ''; + $search_date_export_startday = ''; + $search_date_export_endyear = ''; + $search_date_export_endmonth = ''; + $search_date_export_endday = ''; + $search_date_export_start = ''; + $search_date_export_end = ''; + $search_date_validation_startyear = ''; + $search_date_validation_startmonth = ''; + $search_date_validation_startday = ''; + $search_date_validation_endyear = ''; + $search_date_validation_endmonth = ''; + $search_date_validation_endday = ''; + $search_date_validation_start = ''; + $search_date_validation_end = ''; + $search_debit = ''; + $search_credit = ''; + $search_lettering_code = ''; + $search_not_reconciled = ''; + $search_import_key = ''; + $toselect = array(); + } + + // Must be after the remove filter action, before the export. + $filter = array(); + if (!empty($search_date_start)) { + $filter['t.doc_date>='] = $search_date_start; + $tmp = dol_getdate($search_date_start); + $param .= '&search_date_startmonth='.urlencode($tmp['mon']).'&search_date_startday='.urlencode($tmp['mday']).'&search_date_startyear='.urlencode($tmp['year']); + } + if (!empty($search_date_end)) { + $filter['t.doc_date<='] = $search_date_end; + $tmp = dol_getdate($search_date_end); + $param .= '&search_date_endmonth='.urlencode($tmp['mon']).'&search_date_endday='.urlencode($tmp['mday']).'&search_date_endyear='.urlencode($tmp['year']); + } + if (!empty($search_doc_date)) { + $filter['t.doc_date'] = $search_doc_date; + $tmp = dol_getdate($search_doc_date); + $param .= '&doc_datemonth='.urlencode($tmp['mon']).'&doc_dateday='.urlencode($tmp['mday']).'&doc_dateyear='.urlencode($tmp['year']); + } + if (!empty($search_doc_type)) { + $filter['t.doc_type'] = $search_doc_type; + $param .= '&search_doc_type='.urlencode($search_doc_type); + } + if (!empty($search_doc_ref)) { + $filter['t.doc_ref'] = $search_doc_ref; + $param .= '&search_doc_ref='.urlencode($search_doc_ref); + } + if ($search_account_category != '-1' && !empty($search_account_category)) { + require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.php'; + $accountingcategory = new AccountancyCategory($db); + + $listofaccountsforgroup = $accountingcategory->getCptsCat(0, 'fk_accounting_category = '.((int) $search_account_category)); + $listofaccountsforgroup2 = array(); + if (is_array($listofaccountsforgroup)) { + foreach ($listofaccountsforgroup as $tmpval) { + $listofaccountsforgroup2[] = "'".$db->escape($tmpval['id'])."'"; + } + } + $filter['t.search_accounting_code_in'] = join(',', $listofaccountsforgroup2); + $param .= '&search_account_category='.urlencode($search_account_category); + } + if (!empty($search_accountancy_code)) { + $filter['t.numero_compte'] = $search_accountancy_code; + $param .= '&search_accountancy_code='.urlencode($search_accountancy_code); + } + if (!empty($search_accountancy_code_start)) { + $filter['t.numero_compte>='] = $search_accountancy_code_start; + $param .= '&search_accountancy_code_start='.urlencode($search_accountancy_code_start); + } + if (!empty($search_accountancy_code_end)) { + $filter['t.numero_compte<='] = $search_accountancy_code_end; + $param .= '&search_accountancy_code_end='.urlencode($search_accountancy_code_end); + } + if (!empty($search_accountancy_aux_code)) { + $filter['t.subledger_account'] = $search_accountancy_aux_code; + $param .= '&search_accountancy_aux_code='.urlencode($search_accountancy_aux_code); + } + if (!empty($search_accountancy_aux_code_start)) { + $filter['t.subledger_account>='] = $search_accountancy_aux_code_start; + $param .= '&search_accountancy_aux_code_start='.urlencode($search_accountancy_aux_code_start); + } + if (!empty($search_accountancy_aux_code_end)) { + $filter['t.subledger_account<='] = $search_accountancy_aux_code_end; + $param .= '&search_accountancy_aux_code_end='.urlencode($search_accountancy_aux_code_end); + } + if (!empty($search_mvt_label)) { + $filter['t.label_operation'] = $search_mvt_label; + $param .= '&search_mvt_label='.urlencode($search_mvt_label); + } + if (!empty($search_direction)) { + $filter['t.sens'] = $search_direction; + $param .= '&search_direction='.urlencode($search_direction); + } + if (!empty($search_ledger_code)) { + $filter['t.code_journal'] = $search_ledger_code; + foreach ($search_ledger_code as $code) { + $param .= '&search_ledger_code[]='.urlencode($code); + } + } + if (!empty($search_mvt_num)) { + $filter['t.piece_num'] = $search_mvt_num; + $param .= '&search_mvt_num='.urlencode($search_mvt_num); + } + if (!empty($search_date_creation_start)) { + $filter['t.date_creation>='] = $search_date_creation_start; + $tmp = dol_getdate($search_date_creation_start); + $param .= '&search_date_creation_startmonth='.urlencode($tmp['mon']).'&search_date_creation_startday='.urlencode($tmp['mday']).'&search_date_creation_startyear='.urlencode($tmp['year']); + } + if (!empty($search_date_creation_end)) { + $filter['t.date_creation<='] = $search_date_creation_end; + $tmp = dol_getdate($search_date_creation_end); + $param .= '&search_date_creation_endmonth='.urlencode($tmp['mon']).'&search_date_creation_endday='.urlencode($tmp['mday']).'&search_date_creation_endyear='.urlencode($tmp['year']); + } + if (!empty($search_date_modification_start)) { + $filter['t.tms>='] = $search_date_modification_start; + $tmp = dol_getdate($search_date_modification_start); + $param .= '&search_date_modification_startmonth='.urlencode($tmp['mon']).'&search_date_modification_startday='.urlencode($tmp['mday']).'&search_date_modification_startyear='.urlencode($tmp['year']); + } + if (!empty($search_date_modification_end)) { + $filter['t.tms<='] = $search_date_modification_end; + $tmp = dol_getdate($search_date_modification_end); + $param .= '&search_date_modification_endmonth='.urlencode($tmp['mon']).'&search_date_modification_endday='.urlencode($tmp['mday']).'&search_date_modification_endyear='.urlencode($tmp['year']); + } + if (!empty($search_date_export_start)) { + $filter['t.date_export>='] = $search_date_export_start; + $tmp = dol_getdate($search_date_export_start); + $param .= '&search_date_export_startmonth='.urlencode($tmp['mon']).'&search_date_export_startday='.urlencode($tmp['mday']).'&search_date_export_startyear='.urlencode($tmp['year']); + } + if (!empty($search_date_export_end)) { + $filter['t.date_export<='] = $search_date_export_end; + $tmp = dol_getdate($search_date_export_end); + $param .= '&search_date_export_endmonth='.urlencode($tmp['mon']).'&search_date_export_endday='.urlencode($tmp['mday']).'&search_date_export_endyear='.urlencode($tmp['year']); + } + if (!empty($search_date_validation_start)) { + $filter['t.date_validated>='] = $search_date_validation_start; + $tmp = dol_getdate($search_date_validation_start); + $param .= '&search_date_validation_startmonth='.urlencode($tmp['mon']).'&search_date_validation_startday='.urlencode($tmp['mday']).'&search_date_validation_startyear='.urlencode($tmp['year']); + } + if (!empty($search_date_validation_end)) { + $filter['t.date_validated<='] = $search_date_validation_end; + $tmp = dol_getdate($search_date_validation_end); + $param .= '&search_date_validation_endmonth='.urlencode($tmp['mon']).'&search_date_validation_endday='.urlencode($tmp['mday']).'&search_date_validation_endyear='.urlencode($tmp['year']); + } + if (!empty($search_debit)) { + $filter['t.debit'] = $search_debit; + $param .= '&search_debit='.urlencode($search_debit); + } + if (!empty($search_credit)) { + $filter['t.credit'] = $search_credit; + $param .= '&search_credit='.urlencode($search_credit); + } + if (!empty($search_lettering_code)) { + $filter['t.lettering_code'] = $search_lettering_code; + $param .= '&search_lettering_code='.urlencode($search_lettering_code); + } + if (!empty($search_not_reconciled)) { + $filter['t.reconciled_option'] = $search_not_reconciled; + $param .= '&search_not_reconciled='.urlencode($search_not_reconciled); + } + if (!empty($search_import_key)) { + $filter['t.import_key'] = $search_import_key; + $param .= '&search_import_key='.urlencode($search_import_key); + } + + if ($action == 'setreexport') { + $setreexport = GETPOST('value', 'int'); + if (!dolibarr_set_const($db, "ACCOUNTING_REEXPORT", $setreexport, 'yesno', 0, '', $conf->entity)) { + $error++; + } + + if (!$error) { + if ($conf->global->ACCOUNTING_REEXPORT == 1) { + setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsDisable"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsEnable"), null, 'warnings'); + } + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } + } + + // Mass actions + $objectclass = 'Bookkeeping'; + $objectlabel = 'Bookkeeping'; + $permissiontoread = $user->hasRight('societe', 'lire'); + $permissiontodelete = $user->hasRight('societe', 'supprimer'); + $permissiontoadd = $user->hasRight('societe', 'creer'); + $uploaddir = $conf->societe->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + +// Build and execute select (used by page and export action) +// must de set after the action that set $filter +// -------------------------------------------------------------------- + +$sql = 'SELECT'; +$sql .= ' t.rowid,'; +$sql .= " t.doc_date,"; +$sql .= " t.doc_type,"; +$sql .= " t.doc_ref,"; +$sql .= " t.fk_doc,"; +$sql .= " t.fk_docdet,"; +$sql .= " t.thirdparty_code,"; +$sql .= " t.subledger_account,"; +$sql .= " t.subledger_label,"; +$sql .= " t.numero_compte,"; +$sql .= " t.label_compte,"; +$sql .= " t.label_operation,"; +$sql .= " t.debit,"; +$sql .= " t.credit,"; +$sql .= " t.lettering_code,"; +$sql .= " t.montant as amount,"; +$sql .= " t.sens,"; +$sql .= " t.fk_user_author,"; +$sql .= " t.import_key,"; +$sql .= " t.code_journal,"; +$sql .= " t.journal_label,"; +$sql .= " t.piece_num,"; +$sql .= " t.date_creation,"; +$sql .= " t.tms as date_modification,"; +$sql .= " t.date_export,"; +$sql .= " t.date_validated as date_validation,"; +$sql .= " t.import_key"; + +$sqlfields = $sql; // $sql fields to remove for count total + +$sql .= ' FROM '.MAIN_DB_PREFIX.$object->table_element.' as t'; +// Manage filter +$sqlwhere = array(); +if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.doc_date') { + $sqlwhere[] = $key."='".$db->idate($value)."'"; + } elseif ($key == 't.doc_date>=' || $key == 't.doc_date<=') { + $sqlwhere[] = $key."'".$db->idate($value)."'"; + } elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=' || $key == 't.subledger_account>=' || $key == 't.subledger_account<=') { + $sqlwhere[] = $key."'".$db->escape($value)."'"; + } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') { + $sqlwhere[] = $key.'='.((int) $value); + } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') { + $sqlwhere[] = $key." LIKE '".$db->escape($value)."%'"; + } elseif ($key == 't.subledger_account') { + $sqlwhere[] = natural_search($key, $value, 0, 1); + } elseif ($key == 't.date_creation>=' || $key == 't.date_creation<=') { + $sqlwhere[] = $key."'".$db->idate($value)."'"; + } elseif ($key == 't.tms>=' || $key == 't.tms<=') { + $sqlwhere[] = $key."'".$db->idate($value)."'"; + } elseif ($key == 't.date_export>=' || $key == 't.date_export<=') { + $sqlwhere[] = $key."'".$db->idate($value)."'"; + } elseif ($key == 't.date_validated>=' || $key == 't.date_validated<=') { + $sqlwhere[] = $key."'".$db->idate($value)."'"; + } elseif ($key == 't.credit' || $key == 't.debit') { + $sqlwhere[] = natural_search($key, $value, 1, 1); + } elseif ($key == 't.reconciled_option') { + $sqlwhere[] = 't.lettering_code IS NULL'; + } elseif ($key == 't.code_journal' && !empty($value)) { + if (is_array($value)) { + $sqlwhere[] = natural_search("t.code_journal", join(',', $value), 3, 1); + } else { + $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); + } + } elseif ($key == 't.search_accounting_code_in' && !empty($value)) { + $sqlwhere[] = 't.numero_compte IN ('.$db->sanitize($value, 1).')'; + } else { + $sqlwhere[] = natural_search($key, $value, 0, 1); + } + } +} +$sql .= ' WHERE t.entity IN ('.getEntity('accountancy').')'; +if (!empty($conf->global->ACCOUNTING_REEXPORT)) { + $sql .= " AND t.date_export IS NULL"; +} +if (count($sqlwhere) > 0) { + $sql .= ' AND '.implode(' AND ', $sqlwhere); +} +//print $sql; + + +// Export into a file with format defined into setup (FEC, CSV, ...) +// Must be after definition of $sql +if ($action == 'export_fileconfirm' && $user->hasRight('accounting', 'mouvements', 'export')) { + // TODO Replace the fetchAll to get all ->line followed by call to ->export(). It currently consumes too much memory on large export. + // Replace this with the query($sql) and loop on each line to export them. + $result = $object->fetchAll($sortorder, $sortfield, 0, 0, $filter, 'AND', (empty($conf->global->ACCOUNTING_REEXPORT) ? 0 : 1)); + + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } else { + // Export files then exit + $accountancyexport = new AccountancyExport($db); + + $formatexport = GETPOST('formatexport', 'int'); + $notexportlettering = GETPOST('notexportlettering', 'alpha'); + + if (!empty($notexportlettering)) { + if (is_array($object->lines)) { + foreach ($object->lines as $k => $movement) { + unset($object->lines[$k]->lettering_code); + unset($object->lines[$k]->date_lettering); + } + } + } + + $notifiedexportdate = GETPOST('notifiedexportdate', 'alpha'); + $notifiedvalidationdate = GETPOST('notifiedvalidationdate', 'alpha'); + $withAttachment = !empty(trim(GETPOST('notifiedexportfull', 'alphanohtml'))) ? 1 : 0; + + // Output data on screen or download + $result = $accountancyexport->export($object->lines, $formatexport, $withAttachment); + + $error = 0; + if ($result < 0) { + $error++; + } else { + if (!empty($notifiedexportdate) || !empty($notifiedvalidationdate)) { + if (is_array($object->lines)) { + dol_syslog("/accountancy/bookkeeping/list.php Function export_file Specify movements as exported", LOG_DEBUG); + + // Specify as export : update field date_export or date_validated + $db->begin(); + + // TODO Merge update for each line into one global using rowid IN (list of movement ids) + foreach ($object->lines as $movement) { + $now = dol_now(); + + $setfields = ''; + if (!empty($notifiedexportdate) && empty($movement->date_export)) { + $setfields .= ($setfields ? "," : "")." date_export = '".$db->idate($now)."'"; + } + if (!empty($notifiedvalidationdate) && empty($movement->date_validation)) { + $setfields .= ($setfields ? "," : "")." date_validated = '".$db->idate($now)."'"; + } + + if ($setfields) { + $sql = " UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping"; + $sql .= " SET ".$setfields; + $sql .= " WHERE rowid = ".((int) $movement->id); + + $result = $db->query($sql); + if (!$result) { + $error++; + break; + } + } + } + + if (!$error) { + $db->commit(); + } else { + $error++; + $accountancyexport->errors[] = $langs->trans('NotAllExportedMovementsCouldBeRecordedAsExportedOrValidated'); + $db->rollback(); + } + } + } + } + + if ($error) { + setEventMessages('', $accountancyexport->errors, 'errors'); + header('Location: '.$_SERVER['PHP_SELF']); + } + exit(); // download or show errors + } +} + + +/* + * View + */ + +$formother = new FormOther($db); +$formfile = new FormFile($db); + +$title_page = $langs->trans("Operations").' - '.$langs->trans("ExportAccountancy"); + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->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); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + } 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; + } + $db->free($resql); +} + +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); +} + +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + +$arrayofselected = is_array($toselect) ? $toselect : array(); + +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title_page); + +$formconfirm = ''; + +if ($action == 'export_file') { + $form_question = array(); + + $form_question['formatexport'] = array( + 'name' => 'formatexport', + 'type' => 'select', + 'label' => $langs->trans('Modelcsv'), // TODO Use Selectmodelcsv and show a select combo + 'values' => $listofformat, + 'default' => $formatexportset, + 'morecss' => 'minwidth200 maxwidth200' + ); + + $form_question['separator0'] = array('name'=>'separator0', 'type'=>'separator'); + + if (getDolGlobalInt("ACCOUNTING_ENABLE_LETTERING")) { + // If 1, we check by default. + $checked = !empty($conf->global->ACCOUNTING_DEFAULT_NOT_EXPORT_LETTERING) ? 'true' : 'false'; + $form_question['notexportlettering'] = array( + 'name' => 'notexportlettering', + 'type' => 'checkbox', + 'label' => $langs->trans('NotExportLettering'), + 'value' => $checked, + ); + + $form_question['separator1'] = array('name'=>'separator1', 'type'=>'separator'); + } + + // If 1 or not set, we check by default. + $checked = (!isset($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_EXPORT_DATE) || !empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_EXPORT_DATE)); + $form_question['notifiedexportdate'] = array( + 'name' => 'notifiedexportdate', + 'type' => 'checkbox', + 'label' => $langs->trans('NotifiedExportDate'), + 'value' => (!empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_EXPORT_DATE) ? 'false' : 'true'), + ); + + $form_question['separator2'] = array('name'=>'separator2', 'type'=>'separator'); + + if (!getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")) { + // If 0 or not set, we NOT check by default. + $checked = (isset($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_VALIDATION_DATE) || !empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_VALIDATION_DATE)); + $form_question['notifiedvalidationdate'] = array( + 'name' => 'notifiedvalidationdate', + 'type' => 'checkbox', + 'label' => $langs->trans('NotifiedValidationDate', $langs->transnoentitiesnoconv("MenuAccountancyClosure")), + 'value' => $checked, + ); + + $form_question['separator3'] = array('name'=>'separator3', 'type'=>'separator'); + } + + // add documents in an archive for accountancy export (Quadratus) + if (getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV') == AccountancyExport::$EXPORT_TYPE_QUADRATUS) { + $form_question['notifiedexportfull'] = array( + 'name' => 'notifiedexportfull', + 'type' => 'checkbox', + 'label' => $langs->trans('NotifiedExportFull'), + 'value' => 'false', + ); + } + + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").'...', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 420, 600); +} + +// Print form confirm +print $formconfirm; + +//$param=''; param started before +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); +} +if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); +} + +// List of mass actions available +$arrayofmassactions = array(); +$massactionbutton = $form->selectMassAction($massaction, $arrayofmassactions); + +print '
'; +print ''; +print ''; +if ($optioncss != '') { + print ''; +} +print ''; +print ''; +print ''; +print ''; + +if (count($filter)) { + $buttonLabel = $langs->trans("ExportFilteredList"); +} else { + $buttonLabel = $langs->trans("ExportList"); +} + +$parameters = array('param' => $param); +$reshook = $hookmanager->executeHooks('addMoreActionsButtonsList', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +$newcardbutton = empty($hookmanager->resPrint) ? '' : $hookmanager->resPrint; + +if (empty($reshook)) { + // Button re-export + if (!empty($conf->global->ACCOUNTING_REEXPORT)) { + $newcardbutton .= ''.img_picto($langs->trans("ClickToShowAlreadyExportedLines"), 'switch_off', 'class="small size15x valignmiddle"'); + $newcardbutton .= ''.$langs->trans("ClickToShowAlreadyExportedLines").''; + $newcardbutton .= ''; + } else { + $newcardbutton .= ''.img_picto($langs->trans("DocsAlreadyExportedAreIncluded"), 'switch_on', 'class="warning size15x valignmiddle"'); + $newcardbutton .= ''.$langs->trans("DocsAlreadyExportedAreIncluded").''; + $newcardbutton .= ''; + } + + if ($user->hasRight('accounting', 'mouvements', 'export')) { + $newcardbutton .= dolGetButtonTitle($buttonLabel, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', 'fa fa-file-export paddingleft', $_SERVER["PHP_SELF"].'?action=export_file&token='.newToken().($param ? '&'.$param : '').'&sortfield='.urlencode($sortfield).'&sortorder='.urlencode($sortorder), $user->hasRight('accounting', 'mouvements', 'export')); + } +} + +print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1); + +print info_admin($langs->trans("WarningDataDisappearsWhenDataIsExported"), 0, 0, 0); +print '
'; + +//$topicmail = "Information"; +//$modelmail = "accountingbookkeeping"; +//$objecttmp = new BookKeeping($db); +//$trackid = 'bk'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields +if ($massactionbutton && $contextpage != 'poslist') { + $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); +} + +$moreforfilter = ''; +$moreforfilter .= '
'; +$moreforfilter .= $langs->trans('AccountingCategory').': '; +$moreforfilter .= '
'; +$moreforfilter .= $formaccounting->select_accounting_category($search_account_category, 'search_account_category', 1, 0, 0, 0); +$moreforfilter .= '
'; +$moreforfilter .= '
'; + +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +if (empty($reshook)) { + $moreforfilter .= $hookmanager->resPrint; +} else { + $moreforfilter = $hookmanager->resPrint; +} + +print '
'; +print $moreforfilter; +print '
'; + +print '
'; +print '
'.img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ').''.img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_WAREHOUSE, $search_warehouse_categ, 'search_warehouse_categ').'
'.$langs->trans("SubscriptionRequired").''; + print '
'.$form->textwithpicto($langs->trans("SubscriptionRequired"), $langs->trans("SubscriptionRequiredDesc")).''; print $form->selectyesno("subscription", 1, 1); print '
'.$langs->trans("MembersNature").''.$object->getmorphylib($object->morphy).'
'.$langs->trans("SubscriptionRequired").''; + print '
'.$form->textwithpicto($langs->trans("SubscriptionRequired"), $langs->trans("SubscriptionRequiredDesc")).''; print yn($object->subscription); print '
'; + +// Filters lines +print ''; +// Action column +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; +} +// Movement number +if (!empty($arrayfields['t.piece_num']['checked'])) { + print ''; +} +// Code journal +if (!empty($arrayfields['t.code_journal']['checked'])) { + print ''; +} +// Date document +if (!empty($arrayfields['t.doc_date']['checked'])) { + print ''; +} +// Ref document +if (!empty($arrayfields['t.doc_ref']['checked'])) { + print ''; +} +// Accountancy account +if (!empty($arrayfields['t.numero_compte']['checked'])) { + print ''; +} +// Subledger account +if (!empty($arrayfields['t.subledger_account']['checked'])) { + print ''; +} +// Label operation +if (!empty($arrayfields['t.label_operation']['checked'])) { + print ''; +} +// Debit +if (!empty($arrayfields['t.debit']['checked'])) { + print ''; +} +// Credit +if (!empty($arrayfields['t.credit']['checked'])) { + print ''; +} +// Lettering code +if (!empty($arrayfields['t.lettering_code']['checked'])) { + print ''; +} + +// Fields from hook +$parameters = array('arrayfields'=>$arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +// Date creation +if (!empty($arrayfields['t.date_creation']['checked'])) { + print ''; +} +// Date modification +if (!empty($arrayfields['t.tms']['checked'])) { + print ''; +} +// Date export +if (!empty($arrayfields['t.date_export']['checked'])) { + print ''; +} +// Date validation +if (!empty($arrayfields['t.date_validated']['checked'])) { + print ''; +} +if (!empty($arrayfields['t.import_key']['checked'])) { + print ''; +} +// Action column +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; +} +print "\n"; + +print ''; +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch actioncolumn ');} +if (!empty($arrayfields['t.piece_num']['checked'])) { + print_liste_field_titre($arrayfields['t.piece_num']['label'], $_SERVER['PHP_SELF'], "t.piece_num", "", $param, "", $sortfield, $sortorder); +} +if (!empty($arrayfields['t.code_journal']['checked'])) { + print_liste_field_titre($arrayfields['t.code_journal']['label'], $_SERVER['PHP_SELF'], "t.code_journal", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['t.doc_date']['checked'])) { + print_liste_field_titre($arrayfields['t.doc_date']['label'], $_SERVER['PHP_SELF'], "t.doc_date", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['t.doc_ref']['checked'])) { + print_liste_field_titre($arrayfields['t.doc_ref']['label'], $_SERVER['PHP_SELF'], "t.doc_ref", "", $param, "", $sortfield, $sortorder); +} +if (!empty($arrayfields['t.numero_compte']['checked'])) { + print_liste_field_titre($arrayfields['t.numero_compte']['label'], $_SERVER['PHP_SELF'], "t.numero_compte", "", $param, "", $sortfield, $sortorder); +} +if (!empty($arrayfields['t.subledger_account']['checked'])) { + print_liste_field_titre($arrayfields['t.subledger_account']['label'], $_SERVER['PHP_SELF'], "t.subledger_account", "", $param, "", $sortfield, $sortorder); +} +if (!empty($arrayfields['t.label_operation']['checked'])) { + print_liste_field_titre($arrayfields['t.label_operation']['label'], $_SERVER['PHP_SELF'], "t.label_operation", "", $param, "", $sortfield, $sortorder); +} +if (!empty($arrayfields['t.debit']['checked'])) { + print_liste_field_titre($arrayfields['t.debit']['label'], $_SERVER['PHP_SELF'], "t.debit", "", $param, '', $sortfield, $sortorder, 'right '); +} +if (!empty($arrayfields['t.credit']['checked'])) { + print_liste_field_titre($arrayfields['t.credit']['label'], $_SERVER['PHP_SELF'], "t.credit", "", $param, '', $sortfield, $sortorder, 'right '); +} +if (!empty($arrayfields['t.lettering_code']['checked'])) { + print_liste_field_titre($arrayfields['t.lettering_code']['label'], $_SERVER['PHP_SELF'], "t.lettering_code", "", $param, '', $sortfield, $sortorder, 'center '); +} +// Hook fields +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +if (!empty($arrayfields['t.date_creation']['checked'])) { + print_liste_field_titre($arrayfields['t.date_creation']['label'], $_SERVER['PHP_SELF'], "t.date_creation", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['t.tms']['checked'])) { + print_liste_field_titre($arrayfields['t.tms']['label'], $_SERVER['PHP_SELF'], "t.tms", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['t.date_export']['checked'])) { + print_liste_field_titre($arrayfields['t.date_export']['label'], $_SERVER['PHP_SELF'], "t.date_export,t.doc_date", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['t.date_validated']['checked'])) { + print_liste_field_titre($arrayfields['t.date_validated']['label'], $_SERVER['PHP_SELF'], "t.date_validated,t.doc_date", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['t.import_key']['checked'])) { + print_liste_field_titre($arrayfields['t.import_key']['label'], $_SERVER["PHP_SELF"], "t.import_key", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +} +print "\n"; + + +$line = new BookKeepingLine(); + +// Loop on record +// -------------------------------------------------------------------- +$i = 0; +$totalarray = array(); +$totalarray['nbfield'] = 0; +$total_debit = 0; +$total_credit = 0; +$totalarray['val'] = array (); +$totalarray['val']['totaldebit'] = 0; +$totalarray['val']['totalcredit'] = 0; + +while ($i < min($num, $limit)) { + $obj = $db->fetch_object($resql); + if (empty($obj)) { + break; // Should not happen + } + + $line->id = $obj->rowid; + $line->doc_date = $db->jdate($obj->doc_date); + $line->doc_type = $obj->doc_type; + $line->doc_ref = $obj->doc_ref; + $line->fk_doc = $obj->fk_doc; + $line->fk_docdet = $obj->fk_docdet; + $line->thirdparty_code = $obj->thirdparty_code; + $line->subledger_account = $obj->subledger_account; + $line->subledger_label = $obj->subledger_label; + $line->numero_compte = $obj->numero_compte; + $line->label_compte = $obj->label_compte; + $line->label_operation = $obj->label_operation; + $line->debit = $obj->debit; + $line->credit = $obj->credit; + $line->montant = $obj->amount; // deprecated + $line->amount = $obj->amount; + $line->sens = $obj->sens; + $line->lettering_code = $obj->lettering_code; + $line->fk_user_author = $obj->fk_user_author; + $line->import_key = $obj->import_key; + $line->code_journal = $obj->code_journal; + $line->journal_label = $obj->journal_label; + $line->piece_num = $obj->piece_num; + $line->date_creation = $db->jdate($obj->date_creation); + $line->date_modification = $db->jdate($obj->date_modification); + $line->date_export = $db->jdate($obj->date_export); + $line->date_validation = $db->jdate($obj->date_validation); + + $total_debit += $line->debit; + $total_credit += $line->credit; + + print ''; + // Action column + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Piece number + if (!empty($arrayfields['t.piece_num']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Journal code + if (!empty($arrayfields['t.code_journal']['checked'])) { + $accountingjournal = new AccountingJournal($db); + $result = $accountingjournal->fetch('', $line->code_journal); + $journaltoshow = (($result > 0) ? $accountingjournal->getNomUrl(0, 0, 0, '', 0) : $line->code_journal); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Document date + if (!empty($arrayfields['t.doc_date']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Document ref + if (!empty($arrayfields['t.doc_ref']['checked'])) { + if ($line->doc_type == 'customer_invoice') { + $langs->loadLangs(array('bills')); + + require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + $objectstatic = new Facture($db); + $objectstatic->fetch($line->fk_doc); + //$modulepart = 'facture'; + + $filename = dol_sanitizeFileName($line->doc_ref); + $filedir = $conf->facture->dir_output.'/'.dol_sanitizeFileName($line->doc_ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$objectstatic->id; + $documentlink = $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); + } elseif ($line->doc_type == 'supplier_invoice') { + $langs->loadLangs(array('bills')); + + require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; + $objectstatic = new FactureFournisseur($db); + $objectstatic->fetch($line->fk_doc); + //$modulepart = 'invoice_supplier'; + + $filename = dol_sanitizeFileName($line->doc_ref); + $filedir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($line->fk_doc, 2, 0, 0, $objectstatic, $modulepart).dol_sanitizeFileName($line->doc_ref); + $subdir = get_exdir($objectstatic->id, 2, 0, 0, $objectstatic, $modulepart).dol_sanitizeFileName($line->doc_ref); + $documentlink = $formfile->getDocumentsLink($objectstatic->element, $subdir, $filedir); + } elseif ($line->doc_type == 'expense_report') { + $langs->loadLangs(array('trips')); + + require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; + $objectstatic = new ExpenseReport($db); + $objectstatic->fetch($line->fk_doc); + //$modulepart = 'expensereport'; + + $filename = dol_sanitizeFileName($line->doc_ref); + $filedir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($line->doc_ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$objectstatic->id; + $documentlink = $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); + } elseif ($line->doc_type == 'bank') { + require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; + $objectstatic = new AccountLine($db); + $objectstatic->fetch($line->fk_doc); + } else { + // Other type + } + + $labeltoshow = ''; + $labeltoshowalt = ''; + if ($line->doc_type == 'customer_invoice' || $line->doc_type == 'supplier_invoice' || $line->doc_type == 'expense_report') { + $labeltoshow .= $objectstatic->getNomUrl(1, '', 0, 0, '', 0, -1, 1); + $labeltoshow .= $documentlink; + $labeltoshowalt .= $objectstatic->ref; + } elseif ($line->doc_type == 'bank') { + $labeltoshow .= $objectstatic->getNomUrl(1); + $labeltoshowalt .= $objectstatic->ref; + $bank_ref = strstr($line->doc_ref, '-'); + $labeltoshow .= " " . $bank_ref; + $labeltoshowalt .= " " . $bank_ref; + } else { + $labeltoshow .= $line->doc_ref; + $labeltoshowalt .= $line->doc_ref; + } + + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Account number + if (!empty($arrayfields['t.numero_compte']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Subledger account + if (!empty($arrayfields['t.subledger_account']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Label operation + if (!empty($arrayfields['t.label_operation']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Amount debit + if (!empty($arrayfields['t.debit']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'totaldebit'; + } + $totalarray['val']['totaldebit'] += $line->debit; + } + + // Amount credit + if (!empty($arrayfields['t.credit']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'totalcredit'; + } + $totalarray['val']['totalcredit'] += $line->credit; + } + + // Lettering code + if (!empty($arrayfields['t.lettering_code']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + // Creation operation date + if (!empty($arrayfields['t.date_creation']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Modification operation date + if (!empty($arrayfields['t.tms']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Exported operation date + if (!empty($arrayfields['t.date_export']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Validated operation date + if (!empty($arrayfields['t.date_validated']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + if (!empty($arrayfields['t.import_key']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Action column + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + + print "\n"; + + $i++; +} + +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print "
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; + print $formaccounting->multi_select_journal($search_ledger_code, 'search_ledger_code', 0, 1, 1, 1, 'small maxwidth75'); + print ''; + print '
'; + print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); + print '
'; + print '
'; + print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to")); + print '
'; + print '
'; + print '
'; + print $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth150', 'account'); + print '
'; + print '
'; + print $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth150', 'account'); + print '
'; + print '
'; + // TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because it does not + // use setup of keypress to select thirdparty and this hang browser on large database. + if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { + print '
'; + //print $langs->trans('From').' '; + print $formaccounting->select_auxaccount($search_accountancy_aux_code_start, 'search_accountancy_aux_code_start', $langs->trans('From'), 'maxwidth250', 'subledgeraccount'); + print '
'; + print '
'; + print $formaccounting->select_auxaccount($search_accountancy_aux_code_end, 'search_accountancy_aux_code_end', $langs->trans('to'), 'maxwidth250', 'subledgeraccount'); + print '
'; + } else { + print ''; + } + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'.$langs->trans("NotReconciled").''; + print '
'; + print '
'; + print $form->selectDate($search_date_creation_start, 'search_date_creation_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); + print '
'; + print '
'; + print $form->selectDate($search_date_creation_end, 'search_date_creation_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to")); + print '
'; + print '
'; + print '
'; + print $form->selectDate($search_date_modification_start, 'search_date_modification_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); + print '
'; + print '
'; + print $form->selectDate($search_date_modification_end, 'search_date_modification_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); + print '
'; + print '
'; + print '
'; + print $form->selectDate($search_date_export_start, 'search_date_export_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); + print '
'; + print '
'; + print $form->selectDate($search_date_export_end, 'search_date_export_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to")); + print '
'; + print '
'; + print '
'; + print $form->selectDate($search_date_validation_start, 'search_date_validation_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("From")); + print '
'; + print '
'; + print $form->selectDate($search_date_validation_end, 'search_date_validation_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans("to")); + print '
'; + print '
'; + print ''; + print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'; + if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($line->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + $object->id = $line->id; + $object->piece_num = $line->piece_num; + print $object->getNomUrl(1, '', 0, '', 1); + print ''.$journaltoshow.''.dol_print_date($line->doc_date, 'day').''; + print $labeltoshow; + print "'.length_accountg($line->numero_compte).''.length_accounta($line->subledger_account).''.dol_escape_htmltag($line->label_operation).''.($line->debit != 0 ? price($line->debit) : '').''.($line->credit != 0 ? price($line->credit) : '').''.$line->lettering_code.''.dol_print_date($line->date_creation, 'dayhour', 'tzuserrel').''.dol_print_date($line->date_modification, 'dayhour', 'tzuserrel').''.dol_print_date($line->date_export, 'dayhour', 'tzuserrel').''.dol_print_date($line->date_validation, 'dayhour', 'tzuserrel').''.$obj->import_key."'; + if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($line->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
'.$langs->trans("NoRecordFound").'
"; +print '
'; + +print ''; + +// End of page +llxFooter(); + +$db->close(); diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 217474db0c9..c1874476fbc 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -1,7 +1,7 @@ * Copyright (C) 2013-2016 Florian Henry - * Copyright (C) 2013-2022 Alexandre Spangaro + * Copyright (C) 2013-2023 Alexandre Spangaro * Copyright (C) 2022 Lionel Vessiller * Copyright (C) 2016-2017 Laurent Destailleur * Copyright (C) 2018-2021 Frédéric France @@ -29,7 +29,6 @@ // Load Dolibarr environment require '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; @@ -96,14 +95,6 @@ $search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_star $search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear); $search_import_key = GETPOST("search_import_key", 'alpha'); -//var_dump($search_date_start);exit; -if (GETPOST("button_delmvt_x") || GETPOST("button_delmvt.x") || GETPOST("button_delmvt")) { - $action = 'delbookkeepingyear'; -} -if (GETPOST("button_export_file_x") || GETPOST("button_export_file.x") || GETPOST("button_export_file")) { - $action = 'export_file'; -} - $search_account_category = GETPOST('search_account_category', 'int'); $search_accountancy_code = GETPOST("search_accountancy_code", 'alpha'); @@ -159,7 +150,7 @@ $hookmanager->initHooks(array('bookkeepinglist')); $formaccounting = new FormAccounting($db); $form = new Form($db); -if (!in_array($action, array('export_file', 'delmouv', 'delmouvconfirm')) && !GETPOSTISSET('begin') && !GETPOSTISSET('formfilteraction') && GETPOST('page', 'int') == '' && !GETPOST('noreset', 'int') && $user->hasRight('accounting', 'mouvements', 'export')) { +if (!in_array($action, array('delmouv', 'delmouvconfirm')) && !GETPOSTISSET('begin') && !GETPOSTISSET('formfilteraction') && GETPOST('page', 'int') == '' && !GETPOST('noreset', 'int') && $user->hasRight('accounting', 'mouvements', 'export')) { if (empty($search_date_start) && empty($search_date_end) && !GETPOSTISSET('restore_lastsearch_values') && !GETPOST('search_accountancy_code_start')) { $query = "SELECT date_start, date_end from ".MAIN_DB_PREFIX."accounting_fiscalyear "; $query .= " where date_start < '".$db->idate(dol_now())."' and date_end > '".$db->idate(dol_now())."' limit 1"; @@ -201,8 +192,8 @@ $arrayfields = array( 't.lettering_code'=>array('label'=>$langs->trans("LetteringCode"), 'checked'=>1), 't.date_creation'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0), 't.tms'=>array('label'=>$langs->trans("DateModification"), 'checked'=>0), - 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>1), - 't.date_validated'=>array('label'=>$langs->trans("DateValidationAndLock"), 'checked'=>1, 'enabled'=>!getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")), + 't.date_export'=>array('label'=>$langs->trans("DateExport"), 'checked'=>0), + 't.date_validated'=>array('label'=>$langs->trans("DateValidationAndLock"), 'checked'=>0, 'enabled'=>!getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")), 't.import_key'=>array('label'=>$langs->trans("ImportId"), 'checked'=>0, 'position'=>1100), ); @@ -210,13 +201,6 @@ if (empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { unset($arrayfields['t.lettering_code']); } -$accountancyexport = new AccountancyExport($db); -$listofformat = $accountancyexport->getType(); -$formatexportset = getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV'); -if (empty($listofformat[$formatexportset])) { - $formatexportset = 1; -} - $error = 0; if (!isModEnabled('accounting')) { @@ -457,49 +441,6 @@ if (empty($reshook)) { $param .= '&search_import_key='.urlencode($search_import_key); } - //if ($action == 'delbookkeepingyearconfirm' && !$user->hasRight('accounting', 'mouvements', 'supprimer_tous')) { - // $delmonth = GETPOST('delmonth', 'int'); - // $delyear = GETPOST('delyear', 'int'); - // if ($delyear == -1) { - // $delyear = 0; - // } - // $deljournal = GETPOST('deljournal', 'alpha'); - // if ($deljournal == -1) { - // $deljournal = 0; - // } - // - // if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) { - // $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0)); - // if ($result < 0) { - // setEventMessages($object->error, $object->errors, 'errors'); - // } else { - // setEventMessages("RecordDeleted", null, 'mesgs'); - // } - // - // // Make a redirect to avoid to launch the delete later after a back button - // header("Location: list.php".($param ? '?'.$param : '')); - // exit; - // } else { - // setEventMessages("NoRecordDeleted", null, 'warnings'); - // } - //} - if ($action == 'setreexport') { - $setreexport = GETPOST('value', 'int'); - if (!dolibarr_set_const($db, "ACCOUNTING_REEXPORT", $setreexport, 'yesno', 0, '', $conf->entity)) { - $error++; - } - - if (!$error) { - if ($conf->global->ACCOUNTING_REEXPORT == 1) { - setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsEnable"), null, 'mesgs'); - } else { - setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsDisable"), null, 'warnings'); - } - } else { - setEventMessages($langs->trans("Error"), null, 'errors'); - } - } - // Mass actions $objectclass = 'Bookkeeping'; $objectlabel = 'Bookkeeping'; @@ -707,103 +648,12 @@ if (count($filter) > 0) { } } $sql .= ' WHERE t.entity IN ('.getEntity('accountancy').')'; -if (empty($conf->global->ACCOUNTING_REEXPORT)) { - $sql .= " AND t.date_export IS NULL"; -} + if (count($sqlwhere) > 0) { $sql .= ' AND '.implode(' AND ', $sqlwhere); } //print $sql; - -// Export into a file with format defined into setup (FEC, CSV, ...) -// Must be after definition of $sql -if ($action == 'export_fileconfirm' && $user->hasRight('accounting', 'mouvements', 'export')) { - // TODO Replace the fetchAll to get all ->line followed by call to ->export(). It currently consumes too much memory on large export. - // Replace this with the query($sql) and loop on each line to export them. - $result = $object->fetchAll($sortorder, $sortfield, 0, 0, $filter, 'AND', (empty($conf->global->ACCOUNTING_REEXPORT) ? 0 : 1)); - - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } else { - // Export files then exit - $accountancyexport = new AccountancyExport($db); - - $formatexport = GETPOST('formatexport', 'int'); - $notexportlettering = GETPOST('notexportlettering', 'alpha'); - - if (!empty($notexportlettering)) { - if (is_array($object->lines)) { - foreach ($object->lines as $k => $movement) { - unset($object->lines[$k]->lettering_code); - unset($object->lines[$k]->date_lettering); - } - } - } - - $notifiedexportdate = GETPOST('notifiedexportdate', 'alpha'); - $notifiedvalidationdate = GETPOST('notifiedvalidationdate', 'alpha'); - $withAttachment = !empty(trim(GETPOST('notifiedexportfull', 'alphanohtml'))) ? 1 : 0; - - // Output data on screen or download - $result = $accountancyexport->export($object->lines, $formatexport, $withAttachment); - - $error = 0; - if ($result < 0) { - $error++; - } else { - if (!empty($notifiedexportdate) || !empty($notifiedvalidationdate)) { - if (is_array($object->lines)) { - dol_syslog("/accountancy/bookkeeping/list.php Function export_file Specify movements as exported", LOG_DEBUG); - - // Specify as export : update field date_export or date_validated - $db->begin(); - - // TODO Merge update for each line into one gloacl using rowid IN (list of movement ids) - foreach ($object->lines as $movement) { - $now = dol_now(); - - $setfields = ''; - if (!empty($notifiedexportdate) && empty($movement->date_export)) { - $setfields .= ($setfields ? "," : "")." date_export = '".$db->idate($now)."'"; - } - if (!empty($notifiedvalidationdate) && empty($movement->date_validation)) { - $setfields .= ($setfields ? "," : "")." date_validated = '".$db->idate($now)."'"; - } - - if ($setfields) { - $sql = " UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping"; - $sql .= " SET ".$setfields; - $sql .= " WHERE rowid = ".((int) $movement->id); - - $result = $db->query($sql); - if (!$result) { - $error++; - break; - } - } - } - - if (!$error) { - $db->commit(); - } else { - $error++; - $accountancyexport->errors[] = $langs->trans('NotAllExportedMovementsCouldBeRecordedAsExportedOrValidated'); - $db->rollback(); - } - } - } - } - - if ($error) { - setEventMessages('', $accountancyexport->errors, 'errors'); - header('Location: '.$_SERVER['PHP_SELF']); - } - exit(); // download or show errors - } -} - - /* * View */ @@ -857,111 +707,6 @@ llxHeader('', $title_page); $formconfirm = ''; -if ($action == 'export_file') { - $form_question = array(); - - $form_question['formatexport'] = array( - 'name' => 'formatexport', - 'type' => 'select', - 'label' => $langs->trans('Modelcsv'), // TODO Use Selectmodelcsv and show a select combo - 'values' => $listofformat, - 'default' => $formatexportset, - 'morecss' => 'minwidth200 maxwidth200' - ); - - $form_question['separator0'] = array('name'=>'separator0', 'type'=>'separator'); - - if (getDolGlobalInt("ACCOUNTING_ENABLE_LETTERING")) { - // If 1, we check by default. - $checked = !empty($conf->global->ACCOUNTING_DEFAULT_NOT_EXPORT_LETTERING) ? 'true' : 'false'; - $form_question['notexportlettering'] = array( - 'name' => 'notexportlettering', - 'type' => 'checkbox', - 'label' => $langs->trans('NotExportLettering'), - 'value' => $checked, - ); - - $form_question['separator1'] = array('name'=>'separator1', 'type'=>'separator'); - } - - // If 1 or not set, we check by default. - $checked = (!isset($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_EXPORT_DATE) || !empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_EXPORT_DATE)); - $form_question['notifiedexportdate'] = array( - 'name' => 'notifiedexportdate', - 'type' => 'checkbox', - 'label' => $langs->trans('NotifiedExportDate'), - 'value' => (!empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_EXPORT_DATE) ? 'false' : 'true'), - ); - - $form_question['separator2'] = array('name'=>'separator2', 'type'=>'separator'); - - if (!getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")) { - // If 0 or not set, we NOT check by default. - $checked = (isset($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_VALIDATION_DATE) || !empty($conf->global->ACCOUNTING_DEFAULT_NOT_NOTIFIED_VALIDATION_DATE)); - $form_question['notifiedvalidationdate'] = array( - 'name' => 'notifiedvalidationdate', - 'type' => 'checkbox', - 'label' => $langs->trans('NotifiedValidationDate', $langs->transnoentitiesnoconv("MenuAccountancyClosure")), - 'value' => $checked, - ); - - $form_question['separator3'] = array('name'=>'separator3', 'type'=>'separator'); - } - - // add documents in an archive for accountancy export (Quadratus) - if (getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV') == AccountancyExport::$EXPORT_TYPE_QUADRATUS) { - $form_question['notifiedexportfull'] = array( - 'name' => 'notifiedexportfull', - 'type' => 'checkbox', - 'label' => $langs->trans('NotifiedExportFull'), - 'value' => 'false', - ); - } - - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").'...', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 420, 600); -} - -//if ($action == 'delbookkeepingyear') { -// $form_question = array(); -// $delyear = GETPOST('delyear', 'int'); -// $deljournal = GETPOST('deljournal', 'alpha'); -// -// if (empty($delyear)) { -// $delyear = dol_print_date(dol_now(), '%Y'); -// } -// $month_array = array(); -// for ($i = 1; $i <= 12; $i++) { -// $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i)); -// } -// $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array'); -// $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1); -// -// $form_question['delmonth'] = array( -// 'name' => 'delmonth', -// 'type' => 'select', -// 'label' => $langs->trans('DelMonth'), -// 'values' => $month_array, -// 'morecss' => 'minwidth150', -// 'default' => '' -// ); -// $form_question['delyear'] = array( -// 'name' => 'delyear', -// 'type' => 'select', -// 'label' => $langs->trans('DelYear'), -// 'values' => $year_array, -// 'default' => $delyear -// ); -// $form_question['deljournal'] = array( -// 'name' => 'deljournal', -// 'type' => 'other', // We don't use select here, the journal_array is already a select html component -// 'label' => $langs->trans('DelJournal'), -// 'value' => $journal_array, -// 'default' => $deljournal -// ); -// -// $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 320); -//} - // Print form confirm print $formconfirm; @@ -1015,21 +760,6 @@ if ($reshook < 0) { $newcardbutton = empty($hookmanager->resPrint) ? '' : $hookmanager->resPrint; if (empty($reshook)) { - // Button re-export - if (!empty($conf->global->ACCOUNTING_REEXPORT)) { - $newcardbutton .= ''.img_picto($langs->trans("ClickToHideAlreadyExportedLines"), 'switch_off', 'class="small size15x valignmiddle"'); - $newcardbutton .= ''.$langs->trans("ClickToHideAlreadyExportedLines").''; - $newcardbutton .= ''; - } else { - $newcardbutton .= ''.img_picto($langs->trans("DocsAlreadyExportedAreExcluded"), 'switch_on', 'class="warning size15x valignmiddle"'); - $newcardbutton .= ''.$langs->trans("DocsAlreadyExportedAreExcluded").''; - $newcardbutton .= ''; - } - - if ($user->hasRight('accounting', 'mouvements', 'export')) { - $newcardbutton .= dolGetButtonTitle($buttonLabel, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', 'fa fa-file-export paddingleft', $_SERVER["PHP_SELF"].'?action=export_file&token='.newToken().($param ? '&'.$param : '').'&sortfield='.urlencode($sortfield).'&sortorder='.urlencode($sortorder), $user->hasRight('accounting', 'mouvements', 'export')); - } - $newcardbutton .= dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly')); $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?type=sub'.$param, '', 1, array('morecss' => 'marginleftonly')); @@ -1608,13 +1338,6 @@ print $hookmanager->resPrint; print ""; print ''; -// TODO Replace this with mass delete action -//if ($user->rights->accounting->mouvements->supprimer_tous) { -// print '
'."\n"; -// print ''.$langs->trans("DeleteMvt").''; -// print '
'; -//} - print ''; // End of page diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index 8be5531965c..450c77b0e13 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -335,13 +335,16 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2430__+MAX_llx_menu__, 'accountancy', 'balance', 2400__+MAX_llx_menu__, '/accountancy/bookkeeping/balance.php?mainmenu=accountancy&leftmenu=accountancy_balance', 'AccountBalance', 1, 'accountancy', '$user->rights->accounting->mouvements->lire', '', 0, 10, __ENTITY__); -- General Ledger -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2432__+MAX_llx_menu__, 'accountancy', 'bookkeeping', 2400__+MAX_llx_menu__, '/accountancy/bookkeeping/listbyaccount.php?mainmenu=accountancy&leftmenu=accountancy_bookeeping', 'Bookkeeping', 1, 'accountancy', '$user->rights->accounting->mouvements->lire', '', 0, 12, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2432__+MAX_llx_menu__, 'accountancy', 'bookkeeping', 2400__+MAX_llx_menu__, '/accountancy/bookkeeping/listbyaccount.php?mainmenu=accountancy&leftmenu=accountancy_bookkeeping', 'Bookkeeping', 1, 'accountancy', '$user->rights->accounting->mouvements->lire', '', 0, 12, __ENTITY__); -- Journals -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2434__+MAX_llx_menu__, 'accountancy', 'bookkeeping', 2400__+MAX_llx_menu__, '/accountancy/bookkeeping/list.php?mainmenu=accountancy&leftmenu=accountancy_bookeeping', 'Journals', 1, 'accountancy', '$user->rights->accounting->mouvements->lire', '', 0, 15, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2433__+MAX_llx_menu__, 'accountancy', 'bookkeeping', 2400__+MAX_llx_menu__, '/accountancy/bookkeeping/list.php?mainmenu=accountancy&leftmenu=accountancy_bookkeeping', 'Journals', 1, 'accountancy', '$user->rights->accounting->mouvements->lire', '', 0, 13, __ENTITY__); + +-- Export accountancy +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2435__+MAX_llx_menu__, 'accountancy', 'bookkeeping', 2400__+MAX_llx_menu__, '/accountancy/bookkeeping/export.php?mainmenu=accountancy&leftmenu=accountancy_bookkeeping', 'MenuExportAccountancy', 1, 'accountancy', '$user->rights->accounting->mouvements->lire', '', 0, 15, __ENTITY__); -- Closure -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2437__+MAX_llx_menu__, 'accountancy', 'accountancy_closure', 2400__+MAX_llx_menu__, '/accountancy/closure/index.php?mainmenu=accountancy&leftmenu=accountancy_closure', 'MenuAccountancyClosure', 1, 'accountancy', '$user->rights->accounting->fiscalyear->write', '', 0, 17, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2437__+MAX_llx_menu__, 'accountancy', 'accountancy_closure', 2400__+MAX_llx_menu__, '/accountancy/closure/index.php?mainmenu=accountancy&leftmenu=accountancy_closure', 'MenuAccountancyClosure', 1, 'accountancy', '$user->rights->accounting->fiscalyear->write', '', 0, 16, __ENTITY__); -- Reports insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->accounting->enabled', __HANDLER__, 'left', 2440__+MAX_llx_menu__, 'accountancy', 'accountancy_report', 2400__+MAX_llx_menu__, '/compta/resultat/index.php?mainmenu=accountancy&leftmenu=accountancy_report', 'Reportings', 1, 'main', '$user->rights->compta->resultat->lire || $user->rights->accounting->comptarapport->lire', '', 0, 17, __ENTITY__); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 7c51180fe68..68417602475 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1773,6 +1773,9 @@ function get_left_menu_accountancy($mainmenu, &$newmenu, $usemenuhider = 1, $lef // Account Balance $newmenu->add("/accountancy/bookkeeping/balance.php?mainmenu=accountancy&leftmenu=accountancy_accountancy", $langs->trans("AccountBalance"), 1, $user->hasRight('accounting', 'mouvements', 'lire')); + // Export accountancy + $newmenu->add("/accountancy/bookkeeping/export.php?mainmenu=accountancy&leftmenu=accountancy_accountancy", $langs->trans("MenuExportAccountancy"), 1, $user->hasRight('accounting', 'mouvements', 'lire')); + // Closure $newmenu->add("/accountancy/closure/index.php?mainmenu=accountancy&leftmenu=accountancy_closure", $langs->trans("MenuAccountancyClosure"), 1, $user->hasRight('accounting', 'fiscalyear', 'write'), '', $mainmenu, 'closure'); diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index f189c96939d..9f7726018ea 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -52,6 +52,8 @@ AccountantFiles=Export source documents ExportAccountingSourceDocHelp=With this tool, you can search and export the source events that are used to generate your accountancy.
The exported ZIP file will contain the lists of requested items in CSV, as well as their attached files in their original format (PDF, ODT, DOCX...). ExportAccountingSourceDocHelp2=To export your journals, use the menu entry %s - %s. ExportAccountingProjectHelp=Specify a project if you need an accounting report only for a specific project. Expense reports and loan payments are not included in project reports. +ExportAccountancy=Export accountancy +WarningDataDisappearsWhenDataIsExportedReport=Warning, this list contains only the accounting entries that have not been exported. If you want to display the accounting entries already exported to re-export them, click on the button above. VueByAccountAccounting=View by accounting account VueBySubAccountAccounting=View by accounting subaccount @@ -113,6 +115,7 @@ MenuLoanAccounts=Loan accounts MenuProductsAccounts=Product accounts MenuClosureAccounts=Closure accounts MenuAccountancyClosure=Closure +MenuExportAccountancy=Export accountancy MenuAccountancyValidationMovements=Validate movements ProductsBinding=Products accounts TransferInAccounting=Transfer in accounting @@ -479,7 +482,7 @@ FECFormatMulticurrencyCode=Multicurrency code (Idevise) DateExport=Date export WarningReportNotReliable=Warning, this report is not based on the Ledger, so does not contains transaction modified manually in the Ledger. If your journalization is up to date, the bookkeeping view is more accurate. ExpenseReportJournal=Expense Report Journal -DocsAlreadyExportedAreExcluded=Docs already exported are excluded -ClickToHideAlreadyExportedLines=Click to hide already exported lines +DocsAlreadyExportedAreIncluded=Docs already exported are included +ClickToShowAlreadyExportedLines=Click to show already exported lines NAccounts=%s accounts From dc96eeedf347cda7ff382f66d3c72640b09d4b2a Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Wed, 5 Apr 2023 11:06:06 +0200 Subject: [PATCH 028/417] Fix language --- htdocs/langs/en_US/accountancy.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 9f7726018ea..bfd428e869e 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -53,7 +53,7 @@ ExportAccountingSourceDocHelp=With this tool, you can search and export the sour ExportAccountingSourceDocHelp2=To export your journals, use the menu entry %s - %s. ExportAccountingProjectHelp=Specify a project if you need an accounting report only for a specific project. Expense reports and loan payments are not included in project reports. ExportAccountancy=Export accountancy -WarningDataDisappearsWhenDataIsExportedReport=Warning, this list contains only the accounting entries that have not been exported. If you want to display the accounting entries already exported to re-export them, click on the button above. +WarningDataDisappearsWhenDataIsExported=Warning, this list contains only the accounting entries that have not been exported. If you want to display the accounting entries already exported to re-export them, click on the button above. VueByAccountAccounting=View by accounting account VueBySubAccountAccounting=View by accounting subaccount From afda5c041698027c0daf61c4ca2a6af90e0ec45a Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 11:21:22 +0200 Subject: [PATCH 029/417] update code for a better php8 compliance --- htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 50b22f1b439..41eda7174da 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1197,10 +1197,10 @@ class pdf_crabe extends ModelePDFFactures if ($object->type != 2) { // Check a payment mode is defined if (empty($object->mode_reglement_code) - && empty($conf->global->FACTURE_CHQ_NUMBER) + && !getDolGlobalInt('FACTURE_CHQ_NUMBER') && !getDolGlobalInt('FACTURE_RIB_NUMBER')) { $this->error = $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"); - } elseif (($object->mode_reglement_code == 'CHQ' && empty($conf->global->FACTURE_CHQ_NUMBER) && empty($object->fk_account) && empty($object->fk_bank)) + } elseif (($object->mode_reglement_code == 'CHQ' && !getDolGlobalInt('FACTURE_CHQ_NUMBER') && empty($object->fk_account) && empty($object->fk_bank)) || ($object->mode_reglement_code == 'VIR' && !getDolGlobalInt('FACTURE_RIB_NUMBER') && empty($object->fk_account) && empty($object->fk_bank))) { // Avoid having any valid PDF with setup that is not complete $outputlangs->load("errors"); @@ -1286,12 +1286,12 @@ class pdf_crabe extends ModelePDFFactures // Show payment mode CHQ if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') { // If payment mode unregulated or payment mode forced to CHQ - if (!empty($conf->global->FACTURE_CHQ_NUMBER)) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) { $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE); if ($conf->global->FACTURE_CHQ_NUMBER > 0) { $account = new Account($this->db); - $account->fetch($conf->global->FACTURE_CHQ_NUMBER); + $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER')); $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); From ee04c5a0fc11d7a5d4a2e466835e74f7a3273328 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 11:23:53 +0200 Subject: [PATCH 030/417] update code for a better php8 compliance --- htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index cbdb1608beb..ee826a0b0ef 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1289,10 +1289,10 @@ class pdf_sponge extends ModelePDFFactures if ($object->type != 2) { // Check a payment mode is defined if (empty($object->mode_reglement_code) - && empty($conf->global->FACTURE_CHQ_NUMBER) + && !getDolGlobalInt('FACTURE_CHQ_NUMBER') && !getDolGlobalInt('FACTURE_RIB_NUMBER')) { $this->error = $outputlangs->transnoentities("ErrorNoPaiementModeConfigured"); - } elseif (($object->mode_reglement_code == 'CHQ' && empty($conf->global->FACTURE_CHQ_NUMBER) && empty($object->fk_account) && empty($object->fk_bank)) + } elseif (($object->mode_reglement_code == 'CHQ' && !getDolGlobalInt('FACTURE_CHQ_NUMBER') && empty($object->fk_account) && empty($object->fk_bank)) || ($object->mode_reglement_code == 'VIR' && !getDolGlobalInt('FACTURE_RIB_NUMBER') && empty($object->fk_account) && empty($object->fk_bank))) { // Avoid having any valid PDF with setup that is not complete $outputlangs->load("errors"); @@ -1381,12 +1381,12 @@ class pdf_sponge extends ModelePDFFactures // Show payment mode CHQ if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') { // If payment mode unregulated or payment mode forced to CHQ - if (!empty($conf->global->FACTURE_CHQ_NUMBER)) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) { $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE); if ($conf->global->FACTURE_CHQ_NUMBER > 0) { $account = new Account($this->db); - $account->fetch($conf->global->FACTURE_CHQ_NUMBER); + $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER')); $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); From 95558914a9ef2d71be1ed929a2468793b3bd3d2c Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 11:25:17 +0200 Subject: [PATCH 031/417] update code for a better php8 compliance --- htdocs/core/modules/propale/doc/pdf_azur.modules.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index a46bd5f108c..e9da62a42bb 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -1032,12 +1032,12 @@ class pdf_azur extends ModelePDFPropales // Show payment mode CHQ if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') { // Si mode reglement non force ou si force a CHQ - if (!empty($conf->global->FACTURE_CHQ_NUMBER)) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) { $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE); if ($conf->global->FACTURE_CHQ_NUMBER > 0) { $account = new Account($this->db); - $account->fetch($conf->global->FACTURE_CHQ_NUMBER); + $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER')); $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); From 029cbbceca943fa0bbbabb179b709b068197a084 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 11:26:50 +0200 Subject: [PATCH 032/417] update code for a better php8 compliance --- htdocs/core/modules/propale/doc/pdf_cyan.modules.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index b8ef09f04ba..56184668f20 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -1143,12 +1143,12 @@ class pdf_cyan extends ModelePDFPropales // Show payment mode CHQ if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') { // Si mode reglement non force ou si force a CHQ - if (!empty($conf->global->FACTURE_CHQ_NUMBER)) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) { $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE); if ($conf->global->FACTURE_CHQ_NUMBER > 0) { $account = new Account($this->db); - $account->fetch($conf->global->FACTURE_CHQ_NUMBER); + $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER')); $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); @@ -1162,7 +1162,7 @@ class pdf_cyan extends ModelePDFPropales $posy = $pdf->GetY() + 2; } } - if ($conf->global->FACTURE_CHQ_NUMBER == -1) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER') == -1) { $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', 0); From a3fe67f3e5287ca6b085af8ca3756edd2e981848 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 11:27:55 +0200 Subject: [PATCH 033/417] update code for a better php8 compliance --- .../stocktransfer/doc/pdf_eagle_proforma.modules.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php b/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php index 8b0a032c4c9..41bbf8c32f9 100644 --- a/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php +++ b/htdocs/core/modules/stocktransfer/doc/pdf_eagle_proforma.modules.php @@ -943,10 +943,10 @@ class pdf_eagle_proforma extends ModelePDFCommandes // Show payment mode CHQ if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') { // Si mode reglement non force ou si force a CHQ - if (!empty($conf->global->FACTURE_CHQ_NUMBER)) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) { if ($conf->global->FACTURE_CHQ_NUMBER > 0) { $account = new Account($this->db); - $account->fetch($conf->global->FACTURE_CHQ_NUMBER); + $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER')); $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - 3); @@ -960,7 +960,7 @@ class pdf_eagle_proforma extends ModelePDFCommandes $posy = $pdf->GetY() + 2; } } - if ($conf->global->FACTURE_CHQ_NUMBER == -1) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER') == -1) { $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - 3); $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', 0); From eeea2decee4485a3e62445d722e1d0c2eb50fb09 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 11:28:53 +0200 Subject: [PATCH 034/417] update code for a better php8 compliance --- .../modules/supplier_proposal/doc/pdf_aurore.modules.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php index 0fec1c99997..5a2eaeddf47 100644 --- a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php @@ -841,12 +841,12 @@ class pdf_aurore extends ModelePDFSupplierProposal // Show payment mode CHQ if (empty($object->mode_reglement_code) || $object->mode_reglement_code == 'CHQ') { // Si mode reglement non force ou si force a CHQ - if (!empty($conf->global->FACTURE_CHQ_NUMBER)) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER')) { $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE); if ($conf->global->FACTURE_CHQ_NUMBER > 0) { $account = new Account($this->db); - $account->fetch($conf->global->FACTURE_CHQ_NUMBER); + $account->fetch(getDolGlobalInt('FACTURE_CHQ_NUMBER')); $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); @@ -860,7 +860,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $posy = $pdf->GetY() + 2; } } - if ($conf->global->FACTURE_CHQ_NUMBER == -1) { + if (getDolGlobalInt('FACTURE_CHQ_NUMBER') == -1) { $pdf->SetXY($this->marge_gauche, $posy); $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle); $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByChequeOrderedTo', $this->emetteur->name), 0, 'L', 0); From 2c90f7335ea26149688d21977372e76f87b52649 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Wed, 5 Apr 2023 11:42:50 +0200 Subject: [PATCH 035/417] FIX : Travis --- htdocs/mrp/class/mo.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 7745d05d71a..97075ddd440 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -638,8 +638,8 @@ class Mo extends CommonObject $oldQty = $this->oldQty; $newQty = $this->qty; - if($newQty != $oldQty) { - $sql = 'SELECT rowid FROM ' . MAIN_DB_PREFIX . 'mrp_production WHERE fk_mo = ' . $this->id; + if($newQty != $oldQty && !empty($this->oldQty)) { + $sql = 'SELECT rowid FROM ' . MAIN_DB_PREFIX . 'mrp_production WHERE fk_mo = ' . (int) $this->id; $resql = $this->db->query($sql); if($resql) { while ($obj = $this->db->fetch_object($resql)) { From 3a13924685a454e1c7a571047ce9fea405710f86 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 5 Apr 2023 12:43:52 +0200 Subject: [PATCH 036/417] FIX - Operator to search category Knowledge --- htdocs/knowledgemanagement/knowledgerecord_list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/knowledgemanagement/knowledgerecord_list.php b/htdocs/knowledgemanagement/knowledgerecord_list.php index cafb5776cf7..c4b6eb7eaa6 100644 --- a/htdocs/knowledgemanagement/knowledgerecord_list.php +++ b/htdocs/knowledgemanagement/knowledgerecord_list.php @@ -293,7 +293,7 @@ if (!empty($searchCategoryKnowledgemanagementList)) { if (intval($searchCategoryKnowledgemanagement) == -2) { $searchCategoryKnowledgemanagementSqlList[] = "NOT EXISTS (SELECT ck.fk_knowledgemanagement FROM ".MAIN_DB_PREFIX."categorie_knowledgemanagement as ck WHERE t.rowid = ck.fk_knowledgemanagement)"; } elseif (intval($searchCategoryKnowledgemanagement) > 0) { - if ($searchCategoryKnowledgemanagementOperator == 0) { + if (empty($searchCategoryKnowledgemanagementOperator)) { $searchCategoryKnowledgemanagementSqlList[] = " EXISTS (SELECT ck.fk_knowledgemanagement FROM ".MAIN_DB_PREFIX."categorie_knowledgemanagement as ck WHERE t.rowid = ck.fk_knowledgemanagement AND ck.fk_categorie = ".((int) $searchCategoryKnowledgemanagement).")"; } else { $listofcategoryid .= ($listofcategoryid ? ', ' : '') .((int) $searchCategoryKnowledgemanagement); From 3d9aa470783c5bf0060004f4b89e2171d2310b3c Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 5 Apr 2023 12:47:14 +0200 Subject: [PATCH 037/417] Copyright --- htdocs/knowledgemanagement/knowledgerecord_list.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/knowledgemanagement/knowledgerecord_list.php b/htdocs/knowledgemanagement/knowledgerecord_list.php index c4b6eb7eaa6..706f103a13d 100644 --- a/htdocs/knowledgemanagement/knowledgerecord_list.php +++ b/htdocs/knowledgemanagement/knowledgerecord_list.php @@ -1,6 +1,7 @@ - * Copyright (C) 2021 Frédéric France +/* Copyright (C) 2007-2017 Laurent Destailleur + * Copyright (C) 2021 Frédéric France + * Copyright (C) 2023 Anthony Berton * * 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 From fbf12f8a756019510a9fcff63a5169bece6ba4be Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 14:15:44 +0200 Subject: [PATCH 038/417] fix : Warning: Undefined array key padding in /home/httpd/vhosts/aflac.fr/domains/dev.aflac.fr/httpdocs/core/class/commondocgenerator.class.php on line 1208 --- htdocs/core/class/commondocgenerator.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 127584e3f9f..a8f07e071dd 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -1236,7 +1236,7 @@ abstract class CommonDocGenerator // save curent cell padding $curentCellPaddinds = $pdf->getCellPaddings(); // set cell padding with column content definition - $pdf->setCellPaddings($colDef['content']['padding'][3], $colDef['content']['padding'][0], $colDef['content']['padding'][1], $colDef['content']['padding'][2]); + $pdf->setCellPaddings(isset($colDef['content']['padding'][3]) ? $colDef['content']['padding'][3] : 0, isset($colDef['content']['padding'][0]) ? $colDef['content']['padding'][0] : 0, isset($colDef['content']['padding'][1]) ? $colDef['content']['padding'][1] : 0, isset($colDef['content']['padding'][2]) ? $colDef['content']['padding'][2] : 0); $pdf->writeHTMLCell($colDef['width'], 2, $colDef['xStartPos'], $curY, $columnText, 0, 1, 0, true, $colDef['content']['align']); // restore cell padding From 0bdde72873171a17c2f63e022a65c1eedb098e8c Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 14:19:35 +0200 Subject: [PATCH 039/417] fix : Warning: Undefined array key xStartPos in /home/httpd/vhosts/aflac.fr/domains/dev.aflac.fr/httpdocs/core/class/commondocgenerator.class.php on line 1209 --- htdocs/core/class/commondocgenerator.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index a8f07e071dd..64e4d690308 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -1237,7 +1237,7 @@ abstract class CommonDocGenerator $curentCellPaddinds = $pdf->getCellPaddings(); // set cell padding with column content definition $pdf->setCellPaddings(isset($colDef['content']['padding'][3]) ? $colDef['content']['padding'][3] : 0, isset($colDef['content']['padding'][0]) ? $colDef['content']['padding'][0] : 0, isset($colDef['content']['padding'][1]) ? $colDef['content']['padding'][1] : 0, isset($colDef['content']['padding'][2]) ? $colDef['content']['padding'][2] : 0); - $pdf->writeHTMLCell($colDef['width'], 2, $colDef['xStartPos'], $curY, $columnText, 0, 1, 0, true, $colDef['content']['align']); + $pdf->writeHTMLCell($colDef['width'], 2, isset($colDef['xStartPos']) ? $colDef['xStartPos'] : 0, $curY, $columnText, 0, 1, 0, true, $colDef['content']['align']); // restore cell padding $pdf->setCellPaddings($curentCellPaddinds['L'], $curentCellPaddinds['T'], $curentCellPaddinds['R'], $curentCellPaddinds['B']); From 14560c1de818f45c86f82baac72aff2eb5931ba2 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Wed, 5 Apr 2023 15:37:35 +0200 Subject: [PATCH 040/417] FIX : Travis --- htdocs/mrp/class/mo.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 5d971c0e440..ecb82507738 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -639,7 +639,7 @@ class Mo extends CommonObject $oldQty = $this->oldQty; $newQty = $this->qty; if ($newQty != $oldQty && !empty($this->oldQty)) { - $sql = 'SELECT rowid FROM ' . MAIN_DB_PREFIX . 'mrp_production WHERE fk_mo = ' . (int) $this->id; + $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "mrp_production WHERE fk_mo = " . (int) $this->id; $resql = $this->db->query($sql); if ($resql) { while ($obj = $this->db->fetch_object($resql)) { From 0df02e314198a56c7f65d1596f2227242d364cd6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 15:59:40 +0200 Subject: [PATCH 041/417] Fix var no defined --- htdocs/core/lib/functions.lib.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 942473a362b..f592b20ceea 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7944,6 +7944,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, // Set the online payment url link into __ONLINE_PAYMENT_URL__ key require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; $outputlangs->loadLangs(array('paypal', 'other')); + + $amounttouse = 0; $typeforonlinepayment = 'free'; if (is_object($object) && $object->element == 'commande') { $typeforonlinepayment = 'order'; @@ -7953,7 +7955,6 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, } if (is_object($object) && $object->element == 'member') { $typeforonlinepayment = 'member'; - $amounttouse = 0; if (!empty($object->last_subscription_amount)) { $amounttouse = $object->last_subscription_amount; } From 8af81ff89b25dc6af9f2d176b40a365cdede6a63 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 16:03:14 +0200 Subject: [PATCH 042/417] Fix php 8 --- htdocs/core/lib/payments.lib.php | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 29947dda57c..3942f5cbaa8 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -187,12 +187,12 @@ function getValidOnlinePaymentMethods($paymentmethod = '') /** * Return string with full online payment Url * - * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member' ...) - * @param string $ref Ref of object - * @param int $amount Amount of money to request for - * @return string Url string + * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member' ...) + * @param string $ref Ref of object + * @param int|float $amount Amount of money to request for + * @return string Url string */ -function showOnlinePaymentUrl($type, $ref, $amount = '9.99') +function showOnlinePaymentUrl($type, $ref, $amount = 0) { global $langs; @@ -213,13 +213,13 @@ function showOnlinePaymentUrl($type, $ref, $amount = '9.99') /** * Return string with HTML link for online payment * - * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member' ...) - * @param string $ref Ref of object - * @param string $label Text or HTML tag to display, if empty it display the URL - * @param int $amount Amount of money to request for - * @return string Url string + * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member' ...) + * @param string $ref Ref of object + * @param string $label Text or HTML tag to display, if empty it display the URL + * @param int|float $amount Amount of money to request for + * @return string Url string */ -function getHtmlOnlinePaymentLink($type, $ref, $label = '', $amount = '9.99') +function getHtmlOnlinePaymentLink($type, $ref, $label = '', $amount = 0) { $url = getOnlinePaymentUrl(0, $type, $ref, $amount); $label = $label ? $label : $url; @@ -230,15 +230,15 @@ function getHtmlOnlinePaymentLink($type, $ref, $label = '', $amount = '9.99') /** * Return string with full Url * - * @param int $mode 0=True url, 1=Url formated with colors - * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member', 'boothlocation', ...) - * @param string $ref Ref of object - * @param int $amount Amount of money to request for - * @param string $freetag Free tag (required and used for $type='free' only) - * @param string $localorexternal 0=Url for browser, 1=Url for external access - * @return string Url string + * @param int $mode 0=True url, 1=Url formated with colors + * @param string $type Type of URL ('free', 'order', 'invoice', 'contractline', 'member', 'boothlocation', ...) + * @param string $ref Ref of object + * @param int|float $amount Amount of money to request for + * @param string $freetag Free tag (required and used for $type='free' only) + * @param string $localorexternal 0=Url for browser, 1=Url for external access + * @return string Url string */ -function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_tag', $localorexternal = 1) +function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = 0, $freetag = 'your_tag', $localorexternal = 1) { global $conf, $dolibarr_main_url_root; From b6d5f80d28d76fcef84bbe953c66edbd889f511e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 16:32:35 +0200 Subject: [PATCH 043/417] FIX #24429 --- htdocs/core/js/lib_head.js.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index d721ec78873..4424a65eb07 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -1292,4 +1292,22 @@ $(document).ready(function() { }); +/* + * Hacky fix for a bug in select2 with jQuery 3.6.0's new nested-focus "protection" + * see: https://github.com/select2/select2/issues/5993 + * see: https://github.com/jquery/jquery/issues/4382 + * + * TODO: Recheck with the select2 GH issue and remove once this is fixed on their side + */ + +$(document).on('select2:open', (e) => { + console.log("Execute the focus (click on combo or use space when on component"); + const target = $(e.target); + if (target && target.length) { + const id = target[0].id || target[0].name; + document.querySelector(`input[aria-controls*='${id}']`).focus(); + } +}); + + // End of lib_head.js.php From 849c4fa57a06c7ec022a51c10042aff3a59ac743 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 16:54:49 +0200 Subject: [PATCH 044/417] Look and feel v18 --- htdocs/fourn/commande/dispatch.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 50508f171df..7083897e25a 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -751,9 +751,9 @@ if ($id > 0 || !empty($ref)) { // Select warehouse to force it everywhere if (count($listwarehouses) > 1) { - print '
'.$langs->trans("ForceTo").' '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 1, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1); + print '
'.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans("ForceTo"), 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1); } elseif (count($listwarehouses) == 1) { - print '
'.$langs->trans("ForceTo").' '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1); + print '
'.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1); } print ''; @@ -838,7 +838,7 @@ if ($id > 0 || !empty($ref)) { print $linktoprod; print ""; print ''; - print $langs->trans("ProductDoesNotUseBatchSerial"); + print ''.$langs->trans("ProductDoesNotUseBatchSerial").''; print ''; if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { print ''; From 24262f58acf0dd40f4834356d0a6315dcbe1b95a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Fali=C3=A8re?= Date: Wed, 5 Apr 2023 17:23:58 +0200 Subject: [PATCH 045/417] NEW Send an email when ticket assigned --- ...terface_50_modTicket_TicketEmail.class.php | 130 +++++++++++------- htdocs/langs/en_US/ticket.lang | 2 + htdocs/langs/fr_FR/ticket.lang | 2 + 3 files changed, 88 insertions(+), 46 deletions(-) diff --git a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php index 99b8210644c..6df15dcf492 100644 --- a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php +++ b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php @@ -2,6 +2,7 @@ /* * Copyright (C) 2014-2016 Jean-François Ferry * 2016 Christophe Battarel + * Copyright (C) 2023 Benjamin Falière * * 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 @@ -69,62 +70,99 @@ class InterfaceTicketEmail extends DolibarrTriggers case 'TICKET_ASSIGNED': dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); - if ($object->fk_user_assign > 0 && $object->fk_user_assign != $user->id) { - $userstat = new User($this->db); - $res = $userstat->fetch($object->fk_user_assign); - if ($res > 0) { - // Send email to notification email - - if (empty($conf->global->TICKET_DISABLE_ALL_MAILS)) { - // Init to avoid errors - $filepath = array(); - $filename = array(); - $mimetype = array(); - - // Send email to assigned user - $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketAssignedToYou'); - $message = '

'.$langs->transnoentities('TicketAssignedEmailBody', $object->track_id, dolGetFirstLastname($user->firstname, $user->lastname))."

"; - $message .= '
  • '.$langs->trans('Title').' : '.$object->subject.'
  • '; - $message .= '
  • '.$langs->trans('Type').' : '.$object->type_label.'
  • '; - $message .= '
  • '.$langs->trans('Category').' : '.$object->category_label.'
  • '; - $message .= '
  • '.$langs->trans('Severity').' : '.$object->severity_label.'
  • '; - // Extrafields - if (is_array($object->array_options) && count($object->array_options) > 0) { - foreach ($object->array_options as $key => $value) { - $message .= '
  • '.$langs->trans($key).' : '.$value.'
  • '; + if ($object->fk_user_assign > 0) { + if ($object->fk_user_assign != $user->id) { + $userstat = new User($this->db); + $res = $userstat->fetch($object->fk_user_assign); + if ($res > 0) { + // Send email to notification email + if (empty($conf->global->TICKET_DISABLE_ALL_MAILS)) { + // Init to avoid errors + $filepath = array(); + $filename = array(); + $mimetype = array(); + + // Send email to assigned user + $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketAssignedToYou'); + $message = '

    '.$langs->transnoentities('TicketAssignedEmailBody', $object->track_id, dolGetFirstLastname($user->firstname, $user->lastname))."

    "; + $message .= '
    • '.$langs->trans('Title').' : '.$object->subject.'
    • '; + $message .= '
    • '.$langs->trans('Type').' : '.$object->type_label.'
    • '; + $message .= '
    • '.$langs->trans('Category').' : '.$object->category_label.'
    • '; + $message .= '
    • '.$langs->trans('Severity').' : '.$object->severity_label.'
    • '; + // Extrafields + if (is_array($object->array_options) && count($object->array_options) > 0) { + foreach ($object->array_options as $key => $value) { + $message .= '
    • '.$langs->trans($key).' : '.$value.'
    • '; + } + } + + $message .= '
    '; + $message .= '

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

    '; + $message .= '

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

    '; + + $sendto = $userstat->email; + $from = dolGetFirstLastname($user->firstname, $user->lastname).'<'.$user->email.'>'; + + $message = dol_nl2br($message); + + if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) { + $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO; + $conf->global->MAIN_MAIL_AUTOCOPY_TO = ''; + } + include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; + $mailfile = new CMailFile($subject, $sendto, $from, $message, $filepath, $mimetype, $filename, '', '', 0, -1); + if ($mailfile->error) { + setEventMessages($mailfile->error, $mailfile->errors, 'errors'); + } else { + $result = $mailfile->sendfile(); + } + if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) { + $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO; } } + } else { + $this->error = $userstat->error; + $this->errors = $userstat->errors; + } + } - $message .= '
'; - $message .= '

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

'; - $message .= '

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

'; + // Send an email to the Customer to inform him that his ticket has been taken in charge. + if(!empty($conf->global->TICKET_NOTIFY_CUSTOMER_TICKET_ASSIGNED) && empty($object->oldcopy->fk_user_assign)) { + $langs->load('ticket'); - $sendto = $userstat->email; - $from = dolGetFirstLastname($user->firstname, $user->lastname).'<'.$user->email.'>'; + $subject_customer = 'TicketAssignedCustomerEmail'; + $body_customer = 'TicketAssignedCustomerBody'; + $see_ticket_customer = 'TicketNewEmailBodyInfosTrackUrlCustomer'; - $message = dol_nl2br($message); + // Get all external contacts linked to the ticket + $linked_contacts = $object->listeContact(-1, 'thirdparty'); - if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) { - $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO; - $conf->global->MAIN_MAIL_AUTOCOPY_TO = ''; - } - include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; - $mailfile = new CMailFile($subject, $sendto, $from, $message, $filepath, $mimetype, $filename, '', '', 0, -1); - if ($mailfile->error) { - setEventMessages($mailfile->error, $mailfile->errors, 'errors'); - } else { - $result = $mailfile->sendfile(); - } - if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) { - $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO; + // Initialize and fill recipient addresses at least with origin_email + $sendto = ''; + $temp_emails = []; + if ($object->origin_email) { + $temp_emails[] = $object->origin_email; + } + + if (!empty($linked_contacts)) { + foreach ($linked_contacts as $contact) { + // Avoid the email from being sent twice in case of duplicated contact + if (!in_array($contact['email'], $temp_emails)) { + $temp_emails[] = $contact['email']; + } } } - $ok = 1; - } else { - $this->error = $userstat->error; - $this->errors = $userstat->errors; + $sendto = implode(", ", $temp_emails); + unset($temp_emails); + unset($linked_contacts); + + // If recipients, we send the email + if ($sendto) { + $this->composeAndSendCustomerMessage($sendto, $subject_customer, $body_customer, $see_ticket_customer, $object, $langs); + } } + $ok = 1; } break; diff --git a/htdocs/langs/en_US/ticket.lang b/htdocs/langs/en_US/ticket.lang index cb261bbc378..dd773116e35 100644 --- a/htdocs/langs/en_US/ticket.lang +++ b/htdocs/langs/en_US/ticket.lang @@ -246,6 +246,8 @@ ConfirmReOpenTicket=Confirm reopen this ticket ? TicketMessageMailIntroAutoNewPublicMessage=A new message was posted on the ticket with the subject %s: TicketAssignedToYou=Ticket assigned TicketAssignedEmailBody=You have been assigned the ticket #%s by %s +TicketAssignedCustomerEmail=Your ticket has been taken in charge +TicketAssignedCustomerBody=This is an automatic email to confirm your ticket has been taken in charge. MarkMessageAsPrivate=Mark message as private TicketMessageSendEmailHelp=An email will be sent to all assigned contact (internal contacts, but also external contacts except if the option "%s" is checked) TicketMessagePrivateHelp=This message will not display to external users diff --git a/htdocs/langs/fr_FR/ticket.lang b/htdocs/langs/fr_FR/ticket.lang index 6e09597b26e..f7e92aa7066 100644 --- a/htdocs/langs/fr_FR/ticket.lang +++ b/htdocs/langs/fr_FR/ticket.lang @@ -244,6 +244,8 @@ ConfirmReOpenTicket=Voulez-vous ré-ouvrir ce ticket ? TicketMessageMailIntroAutoNewPublicMessage=Un nouveau message a été posté sur le ticket avec le sujet %s: TicketAssignedToYou=Ticket attribué TicketAssignedEmailBody=Vous avez été assigné au ticket #%s par %s +TicketAssignedCustomerEmail=Votre ticket a été pris en charge +TicketAssignedCustomerBody=Ceci est un email automatique pour confirmer que votre ticket a été pris en charge. MarkMessageAsPrivate=Marquer message comme privé TicketMessageSendEmailHelp=Un email sera envoyé à tous les contacts assignés (contacts internes, mais aussi contacts externes sauf si l'option "%s" est cochée) TicketMessagePrivateHelp=Ce message ne s'affichera pas pour les utilisateurs externes From ab6a6b87f68f9740f74845911d06959f76e17aed Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 17:31:58 +0200 Subject: [PATCH 046/417] Debug v18 --- htdocs/projet/tasks/time.php | 112 ++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 36 deletions(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 12eb7c573ce..3dc22b5a589 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -149,7 +149,6 @@ if ($object->fk_project > 0) { } - /* * Actions */ @@ -875,9 +874,11 @@ if ($action == 'confirm_generateinter') { } } + /* * View */ + $form = new Form($db); $formother = new FormOther($db); $formproject = new FormProjets($db); @@ -1304,7 +1305,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($search_year > 0) { $param .= '&search_year='.urlencode($search_year); } - if ($search_user > 0) { + if (!empty($search_user)) { // We keep param if -1 because default value is forced to user id if not set $param .= '&search_user='.urlencode($search_user); } if ($search_task_ref != '') { @@ -1564,6 +1565,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $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 fields to remove for count total + $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as il ON il.rowid = t.invoice_line_id"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture as inv ON inv.rowid = il.fk_facture"; @@ -1657,39 +1661,42 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; - $sql .= $db->order($sortfield, $sortorder); // Count total nb of records $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $resql = $db->query($sql); - - if (! $resql) { + /* 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); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + } else { dol_print_error($db); - exit; } - $nbtotalofrecords = $db->num_rows($resql); - if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } + $db->free($resql); } - // if total of record found is smaller than limit, no need to do paging and to restart another select with limits set. - if (is_numeric($nbtotalofrecords) && $limit > $nbtotalofrecords) { - $num = $nbtotalofrecords; - } else { + + // Complete request and execute it with limit + $sql .= $db->order($sortfield, $sortorder); + if ($limit) { $sql .= $db->plimit($limit + 1, $offset); - - $resql = $db->query($sql); - if (!$resql) { - dol_print_error($db); - exit; - } - - $num = $db->num_rows($resql); } + $resql = $db->query($sql); + if (!$resql) { + dol_print_error($db); + exit; + } + + $num = $db->num_rows($resql); + if ($num >= 0) { if (!empty($projectidforalltimes)) { print ''."\n"; @@ -1870,6 +1877,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''."\n"; // Fields title search + // -------------------------------------------------------------------- print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { @@ -1918,7 +1926,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } // Author if (!empty($arrayfields['author']['checked'])) { - print ''; + print ''; } // Note if (!empty($arrayfields['t.note']['checked'])) { @@ -1977,54 +1985,72 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } print ''."\n"; + $totalarray = array(); + $totalarray['nbfield'] = 0; + + // Fields title label + // -------------------------------------------------------------------- print ''; if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'width="80"', $sortfield, $sortorder, 'center maxwidthsearch '); + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); + $totalarray['nbfield']++; } if (!empty($arrayfields['t.element_date']['checked'])) { print_liste_field_titre($arrayfields['t.element_date']['label'], $_SERVER['PHP_SELF'], 't.element_date,t.element_datehour,t.rowid', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } - if (!empty($arrayfields['p.fk_soc']['checked'])) { print_liste_field_titre($arrayfields['p.fk_soc']['label'], $_SERVER['PHP_SELF'], 't.element_date,t.element_datehour,t.rowid', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['s.name_alias']['checked'])) { print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER['PHP_SELF'], 's.name_alias', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($allprojectforuser)) { if (!empty($arrayfields['p.project_ref']['checked'])) { print_liste_field_titre("Project", $_SERVER['PHP_SELF'], 'p.ref', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['p.project_label']['checked'])) { print_liste_field_titre("ProjectLabel", $_SERVER['PHP_SELF'], 'p.title', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } } if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task if (!empty($arrayfields['t.element_ref']['checked'])) { print_liste_field_titre($arrayfields['t.element_ref']['label'], $_SERVER['PHP_SELF'], 'pt.ref', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['t.element_label']['checked'])) { print_liste_field_titre($arrayfields['t.element_label']['label'], $_SERVER['PHP_SELF'], 'pt.label', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } } if (!empty($arrayfields['author']['checked'])) { print_liste_field_titre($arrayfields['author']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['t.note']['checked'])) { print_liste_field_titre($arrayfields['t.note']['label'], $_SERVER['PHP_SELF'], 't.note', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['t.element_duration']['checked'])) { print_liste_field_titre($arrayfields['t.element_duration']['label'], $_SERVER['PHP_SELF'], 't.element_duration', '', $param, '', $sortfield, $sortorder, 'right '); + $totalarray['nbfield']++; } if (!empty($arrayfields['t.fk_product']['checked'])) { print_liste_field_titre($arrayfields['t.fk_product']['label'], $_SERVER['PHP_SELF'], 't.fk_product', '', $param, '', $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['value']['checked'])) { print_liste_field_titre($arrayfields['value']['label'], $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, 'right '); + $totalarray['nbfield']++; } if (!empty($arrayfields['valuebilled']['checked'])) { print_liste_field_titre($arrayfields['valuebilled']['label'], $_SERVER['PHP_SELF'], 'il.total_ht', '', $param, '', $sortfield, $sortorder, 'center ', $langs->trans("SelectLinesOfTimeSpentToInvoice")); + $totalarray['nbfield']++; } /* // Extra fields @@ -2036,6 +2062,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print $hookmanager->resPrint; if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', 'width="80"', $sortfield, $sortorder, 'center maxwidthsearch '); + $totalarray['nbfield']++; } print "\n"; @@ -2043,10 +2070,13 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $tmpinvoice = new Facture($db); $i = 0; - $total = 0; $totalvalue = 0; - $totalarray = array('nbfield'=>0); + + $savnbfield = $totalarray['nbfield']; + $totalarray = array(); + $totalarray['nbfield'] = 0; + //$imaxinloop = ($limit ? min($num, $limit) : $num); foreach ($tasks as $task_time) { if ($i >= $limit) { break; @@ -2055,11 +2085,13 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $date1 = $db->jdate($task_time->element_date); $date2 = $db->jdate($task_time->element_datehour); - print ''; + // Show here line of result + $j = 0; + print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; + if (!$i) { + $totalarray['nbfield']++; + } } // Date if (!empty($arrayfields['t.element_date']['checked'])) { @@ -2113,7 +2149,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // Thirdparty if (!empty($arrayfields['p.fk_soc']['checked'])) { - print ''; if (!$i) { $totalarray['nbfield']++; @@ -2309,6 +2346,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } } print ''; + if (!$i) { + $totalarray['nbfield']++; + } } // Value spent @@ -2422,10 +2462,10 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } } } - } - print ''; - if (!$i) { - $totalarray['nbfield']++; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } print "\n"; @@ -2724,7 +2764,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($num < $limit && empty($offset)) { print ''; } else { - print ''; + print ''; } } elseif ($totalarray['totaldurationfield'] == $i) { print ''; From 011013fd87b5f4090fbd747f9145e612dce7f2c1 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 5 Apr 2023 15:33:46 +0000 Subject: [PATCH 047/417] Fixing style errors. --- .../interface_50_modTicket_TicketEmail.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php index 6df15dcf492..f18526a9d19 100644 --- a/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php +++ b/htdocs/core/triggers/interface_50_modTicket_TicketEmail.class.php @@ -81,7 +81,7 @@ class InterfaceTicketEmail extends DolibarrTriggers $filepath = array(); $filename = array(); $mimetype = array(); - + // Send email to assigned user $subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketAssignedToYou'); $message = '

'.$langs->transnoentities('TicketAssignedEmailBody', $object->track_id, dolGetFirstLastname($user->firstname, $user->lastname))."

"; @@ -95,16 +95,16 @@ class InterfaceTicketEmail extends DolibarrTriggers $message .= '
  • '.$langs->trans($key).' : '.$value.'
  • '; } } - + $message .= ''; $message .= '

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

    '; $message .= '

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

    '; - + $sendto = $userstat->email; $from = dolGetFirstLastname($user->firstname, $user->lastname).'<'.$user->email.'>'; - + $message = dol_nl2br($message); - + if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) { $old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO; $conf->global->MAIN_MAIL_AUTOCOPY_TO = ''; @@ -127,7 +127,7 @@ class InterfaceTicketEmail extends DolibarrTriggers } // Send an email to the Customer to inform him that his ticket has been taken in charge. - if(!empty($conf->global->TICKET_NOTIFY_CUSTOMER_TICKET_ASSIGNED) && empty($object->oldcopy->fk_user_assign)) { + if (!empty($conf->global->TICKET_NOTIFY_CUSTOMER_TICKET_ASSIGNED) && empty($object->oldcopy->fk_user_assign)) { $langs->load('ticket'); $subject_customer = 'TicketAssignedCustomerEmail'; From 424c53109f8a128f0b5514c368ade04580fc7ace Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 17:56:03 +0200 Subject: [PATCH 048/417] FIX Better support for option MAIN_NO_INPUT_PRICE_WITH_TAX --- htdocs/core/tpl/objectline_create.tpl.php | 2 +- htdocs/master.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 5974daa0573..51ae07640e6 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -761,7 +761,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) { jQuery('#date_end').removeClass('inputmandatory'); } - if ( == 1 && data.pricebasetype == 'TTC') { + if ( == 1 && data.pricebasetype == 'TTC' && ) { console.log("objectline_create.tpl set content of price_ttc"); jQuery("#price_ttc").val(data.price_ttc); } else { diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index 39c6128435b..8478e5279a8 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -219,7 +219,7 @@ if (!defined('NOREQUIREDB') && !defined('NOREQUIRESOC')) { $conf->global->MAIN_PROFID1_IN_ADDRESS = 1; } - if ($mysoc->localtax1_assuj || $mysoc->localtax2_assuj) { + 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. $conf->global->MAIN_NO_INPUT_PRICE_WITH_TAX = 1; From ae8bcfa6caa0227c6ea4e409e78f2dc6fd711e47 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 17:57:05 +0200 Subject: [PATCH 049/417] Prepare 17.0.2 --- htdocs/filefunc.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index 3a2e7d227eb..1ee519e38ee 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -34,7 +34,7 @@ if (!defined('DOL_APPLICATION_TITLE')) { define('DOL_APPLICATION_TITLE', 'Dolibarr'); } if (!defined('DOL_VERSION')) { - define('DOL_VERSION', '17.0.1'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c + define('DOL_VERSION', '17.0.2'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c } if (!defined('EURO')) { From 5252b6804c73dc30b8a48da220a9c1edf3a0f3f2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 18:43:59 +0200 Subject: [PATCH 050/417] Fix css --- htdocs/user/card.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 124c61dc737..cafb1ae847b 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -2378,25 +2378,25 @@ if ($action == 'create' || $action == 'adduserldap') { } if ($object->socid > 0 && !($object->contact_id > 0)) { // external user but no link to a contact - print img_picto('', 'company').$form->select_company($object->socid, 'socid', '', ' '); + print img_picto('', 'company').$form->select_company($object->socid, 'socid', '', ' ', 0, 0, null, 0, 'maxwidth300'); print img_picto('', 'contact').$form->selectcontacts(0, 0, 'contactid', 1, '', '', 1, 'maxwidth300', false, 1); if ($object->ldap_sid) { print ' ('.$langs->trans("DomainUser").')'; } } elseif ($object->socid > 0 && $object->contact_id > 0) { // external user with a link to a contact - print img_picto('', 'company').$form->select_company($object->socid, 'socid', '', ' '); // We keep thirdparty empty, contact is already set + print img_picto('', 'company').$form->select_company($object->socid, 'socid', '', ' ', 0, 0, null, 0, 'maxwidth300'); // We keep thirdparty empty, contact is already set print img_picto('', 'contact').$form->selectcontacts(0, $object->contact_id, 'contactid', 1, '', '', 1, 'maxwidth300', false, 1); if ($object->ldap_sid) { print ' ('.$langs->trans("DomainUser").')'; } } elseif (!($object->socid > 0) && $object->contact_id > 0) { // internal user with a link to a contact - print img_picto('', 'company').$form->select_company(0, 'socid', '', ' '); // We keep thirdparty empty, contact is already set + print img_picto('', 'company').$form->select_company(0, 'socid', '', ' ', 0, 0, null, 0, 'maxwidth300'); // We keep thirdparty empty, contact is already set print img_picto('', 'contact').$form->selectcontacts(0, $object->contact_id, 'contactid', 1, '', '', 1, 'maxwidth300', false, 1); if ($object->ldap_sid) { print ' ('.$langs->trans("DomainUser").')'; } } else { // $object->socid is not > 0 here - print img_picto('', 'company').$form->select_company(0, 'socid', '', ' '); // We keep thirdparty empty, contact is already set + print img_picto('', 'company').$form->select_company(0, 'socid', '', ' ', 0, 0, null, 0, 'maxwidth300'); // We keep thirdparty empty, contact is already set print img_picto('', 'contact').$form->selectcontacts(0, 0, 'contactid', 1, '', '', 1, 'maxwidth300', false, 1); } } From 4d504b3f985528457d3bd24dbb112f1c645296c0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 18:43:59 +0200 Subject: [PATCH 051/417] Fix css --- htdocs/user/card.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 2a6b8a813be..c4029951b87 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -2338,25 +2338,25 @@ if ($action == 'create' || $action == 'adduserldap') { } if ($object->socid > 0 && !($object->contact_id > 0)) { // external user but no link to a contact - print img_picto('', 'company').$form->select_company($object->socid, 'socid', '', ' '); + print img_picto('', 'company').$form->select_company($object->socid, 'socid', '', ' ', 0, 0, null, 0, 'maxwidth300'); print img_picto('', 'contact').$form->selectcontacts(0, 0, 'contactid', 1, '', '', 1, 'maxwidth300', false, 1); if ($object->ldap_sid) { print ' ('.$langs->trans("DomainUser").')'; } } elseif ($object->socid > 0 && $object->contact_id > 0) { // external user with a link to a contact - print img_picto('', 'company').$form->select_company($object->socid, 'socid', '', ' '); // We keep thirdparty empty, contact is already set + print img_picto('', 'company').$form->select_company($object->socid, 'socid', '', ' ', 0, 0, null, 0, 'maxwidth300'); // We keep thirdparty empty, contact is already set print img_picto('', 'contact').$form->selectcontacts(0, $object->contact_id, 'contactid', 1, '', '', 1, 'maxwidth300', false, 1); if ($object->ldap_sid) { print ' ('.$langs->trans("DomainUser").')'; } } elseif (!($object->socid > 0) && $object->contact_id > 0) { // internal user with a link to a contact - print img_picto('', 'company').$form->select_company(0, 'socid', '', ' '); // We keep thirdparty empty, contact is already set + print img_picto('', 'company').$form->select_company(0, 'socid', '', ' ', 0, 0, null, 0, 'maxwidth300'); // We keep thirdparty empty, contact is already set print img_picto('', 'contact').$form->selectcontacts(0, $object->contact_id, 'contactid', 1, '', '', 1, 'maxwidth300', false, 1); if ($object->ldap_sid) { print ' ('.$langs->trans("DomainUser").')'; } } else { // $object->socid is not > 0 here - print img_picto('', 'company').$form->select_company(0, 'socid', '', ' '); // We keep thirdparty empty, contact is already set + print img_picto('', 'company').$form->select_company(0, 'socid', '', ' ', 0, 0, null, 0, 'maxwidth300'); // We keep thirdparty empty, contact is already set print img_picto('', 'contact').$form->selectcontacts(0, 0, 'contactid', 1, '', '', 1, 'maxwidth300', false, 1); } } From 4e78108d86dc2b942cf8d53bd09b67210efd4c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20de=20Grandpr=C3=A9?= Date: Wed, 5 Apr 2023 15:50:03 -0400 Subject: [PATCH 052/417] Allow virtual stock to show on a line in product stocks list when no physical stock present. --- htdocs/product/reassort.php | 39 ++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index f22e688327a..a1e2cb1ab6f 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -172,7 +172,44 @@ if (!empty($search_categ) && $search_categ != '-1') { } $sql .= ")"; } -$sql .= " AND EXISTS (SELECT e.rowid FROM ".MAIN_DB_PREFIX."entrepot as e WHERE e.rowid = s.fk_entrepot AND e.entity IN (".getEntity('stock')."))"; +if (empty($conf->global->PRODUCT_STOCK_LIST_SHOW_VIRTUAL_WITH_NO_PHYSICAL)) { + $sql .= " AND EXISTS (SELECT e.rowid FROM ".MAIN_DB_PREFIX."entrepot as e WHERE e.rowid = s.fk_entrepot AND e.entity IN (".getEntity('stock')."))"; +} else { + $sql .= " AND + ( + EXISTS + (SELECT e.rowid + FROM ".MAIN_DB_PREFIX."entrepot as e + WHERE e.rowid = s.fk_entrepot AND e.entity IN (".getEntity('stock').")) + OR ( + SELECT SUM(cd1.qty) as qty + FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd1 + LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseur as c1 + ON c1.rowid = cd1.fk_commande + WHERE c1.entity IN (1) AND cd1.fk_product = p.rowid AND c1.fk_statut in (3,4) AND cd1.qty <> 0 + ) IS NOT NULL + OR ( + SELECT SUM(cd2.qty) as qty + FROM ".MAIN_DB_PREFIX."commandedet as cd2 + LEFT JOIN ".MAIN_DB_PREFIX."commande as c2 ON c2.rowid = cd2.fk_commande + WHERE c2.entity IN (1) AND cd2.fk_product = p.rowid AND c2.fk_statut in (1,2) AND cd2.qty <> 0 + ) IS NOT NULL + OR ( + SELECT SUM(ed3.qty) as qty + FROM llx_expeditiondet as ed3 + LEFT JOIN ".MAIN_DB_PREFIX."expedition as e3 ON e3.rowid = ed3.fk_expedition + LEFT JOIN ".MAIN_DB_PREFIX."commandedet as cd3 ON ed3.fk_origin_line = cd3.rowid + LEFT JOIN ".MAIN_DB_PREFIX."commande as c3 ON c3.rowid = cd3.fk_commande + WHERE e3.entity IN (1) AND cd3.fk_product = p.rowid AND c3.fk_statut IN (1,2) AND e3.fk_statut IN (1,2) AND ed3.qty <> 0 + ) IS NOT NULL + OR ( + SELECT SUM(mp4.qty) as qty + FROM ".MAIN_DB_PREFIX."mrp_production as mp4 + LEFT JOIN ".MAIN_DB_PREFIX."mrp_mo as m4 ON m4.rowid = mp4.fk_mo AND m4.entity IN (1) AND mp4.fk_product = p.rowid AND m4.status IN (1,2) + WHERE mp4.qty <> 0 + ) IS NOT NULL + ) "; +} if ($sall) { $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall); } From 01d17d42d390b476e5ec41a4397c227ff6ad6fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20de=20Grandpr=C3=A9?= Date: Wed, 5 Apr 2023 16:13:13 -0400 Subject: [PATCH 053/417] corrected DB_PREFIX for one subquery --- htdocs/product/reassort.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index a1e2cb1ab6f..a1b27fd8dde 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -196,7 +196,7 @@ if (empty($conf->global->PRODUCT_STOCK_LIST_SHOW_VIRTUAL_WITH_NO_PHYSICAL)) { ) IS NOT NULL OR ( SELECT SUM(ed3.qty) as qty - FROM llx_expeditiondet as ed3 + FROM ".MAIN_DB_PREFIX."expeditiondet as ed3 LEFT JOIN ".MAIN_DB_PREFIX."expedition as e3 ON e3.rowid = ed3.fk_expedition LEFT JOIN ".MAIN_DB_PREFIX."commandedet as cd3 ON ed3.fk_origin_line = cd3.rowid LEFT JOIN ".MAIN_DB_PREFIX."commande as c3 ON c3.rowid = cd3.fk_commande From 1f472acb74fe146e0c62ee651d0d841b9d131cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20de=20Grandpr=C3=A9?= Date: Wed, 5 Apr 2023 18:10:03 -0400 Subject: [PATCH 054/417] Added copyright --- htdocs/product/reassort.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index a1b27fd8dde..f4b28ccbb78 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -5,6 +5,7 @@ * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2019 Juanjo Menent + * Copyright (C) 2023 Vincent de Grandpré * * 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 From 5d45e1ca3a98efcce32fa1f8cc9961b5650a217d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20de=20Grandpr=C3=A9?= Date: Wed, 5 Apr 2023 18:28:48 -0400 Subject: [PATCH 055/417] #24447 added defaulting to manufacturing warehouse --- htdocs/mrp/mo_production.php | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index 8d3d11d167d..2250f4d8a05 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -1,6 +1,7 @@ -/* Copyright (C) 2023 Christian Humpel + * Copyright (C) 2023 Christian Humpel + * Copyright (C) 2023 Vincent de Grandpré * * 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 @@ -442,6 +443,11 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $res = $object->fetch_thirdparty(); $res = $object->fetch_optionals(); + if(!empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) && $object->fk_warehouse > 0){ + $tmpwarehouse->fetch($object->fk_warehouse); + $fk_default_warehouse = $object->fk_warehouse; + } + $head = moPrepareHead($object); print dol_get_fiche_head($head, 'production', $langs->trans("ManufacturingOrder"), -1, $object->picto); @@ -924,6 +930,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; // Warehouse print '
    '; // Stock if (isModEnabled('stock')) { @@ -932,7 +941,18 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) { print img_warning($langs->trans('StockTooLow')) . ' '; } - print price2num($tmpproduct->stock_reel, 'MS'); // Available + if(empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) || empty($tmpwarehouse->id)) { + print price2num($tmpproduct->stock_reel, 'MS'); // Available + } else { + // Print only the stock in the selected warehouse + $tmpproduct->load_stock(); + $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id]; + if(!empty($wh_stock)){ + print price2num($wh_stock->real, 'MS'); + } else { + print "0"; + } + } } print ''; } @@ -1123,6 +1143,12 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea }); '; + if (in_array($action, array('consumeorproduce', 'consumeandproduceall')) && + !empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE)) { + print ''; + } // Lines to produce From 7a60c57fc5ba34f8817f18d59bec922ef0aec4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20de=20Grandpr=C3=A9?= Date: Wed, 5 Apr 2023 18:30:34 -0400 Subject: [PATCH 056/417] Aligned copyrights --- htdocs/mrp/mo_production.php | 2 +- htdocs/product/reassort.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index 2250f4d8a05..0f8a1f708eb 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -1,6 +1,6 @@ - * Copyright (C) 2023 Christian Humpel + * Copyright (C) 2023 Christian Humpel * Copyright (C) 2023 Vincent de Grandpré * * This program is free software; you can redistribute it and/or modify diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index f4b28ccbb78..db1c0538aa6 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -5,7 +5,7 @@ * Copyright (C) 2013 Cédric Salvador * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2019 Juanjo Menent - * Copyright (C) 2023 Vincent de Grandpré + * Copyright (C) 2023 Vincent de Grandpré * * 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 From eb27a81bfda92ab323ce89ae9b4a57af7ff8526c Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 5 Apr 2023 22:34:51 +0000 Subject: [PATCH 057/417] Fixing style errors. --- htdocs/mrp/mo_production.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index 0f8a1f708eb..ac0aa60a647 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -443,7 +443,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $res = $object->fetch_thirdparty(); $res = $object->fetch_optionals(); - if(!empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) && $object->fk_warehouse > 0){ + if (!empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) && $object->fk_warehouse > 0) { $tmpwarehouse->fetch($object->fk_warehouse); $fk_default_warehouse = $object->fk_warehouse; } @@ -930,7 +930,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; // Warehouse print ''; @@ -941,17 +941,17 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) { print img_warning($langs->trans('StockTooLow')) . ' '; } - if(empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) || empty($tmpwarehouse->id)) { + if (empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) || empty($tmpwarehouse->id)) { print price2num($tmpproduct->stock_reel, 'MS'); // Available } else { // Print only the stock in the selected warehouse $tmpproduct->load_stock(); $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id]; - if(!empty($wh_stock)){ + if (!empty($wh_stock)) { print price2num($wh_stock->real, 'MS'); } else { print "0"; - } + } } } print ''; @@ -1143,7 +1143,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea }); '; - if (in_array($action, array('consumeorproduce', 'consumeandproduceall')) && + if (in_array($action, array('consumeorproduce', 'consumeandproduceall')) && !empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE)) { print ''; + } $switchon = 'switch_on'; $switchoff = 'switch_off'; + $cssswitchon = ''; + $cssswitchoff = ''; $tmparray = explode(':', $text_on); if (!empty($tmparray[1])) { $text_on = $tmparray[0]; $switchon = $tmparray[1]; + if (!empty($tmparray[2])) { + $cssswitchon = $tmparray[2]; + } } $tmparray = explode(':', $text_off); if (!empty($tmparray[1])) { $text_off = $tmparray[0]; $switchoff = $tmparray[1]; + if (!empty($tmparray[2])) { + $cssswitchoff = $tmparray[2]; + } } - $out .= ''.img_picto($langs->trans($text_off), $switchoff).''; - $out .= ''.img_picto($langs->trans($text_on), $switchon).''; + if (empty($conf->use_javascript_ajax) || $forcenojs) { + $out .= ''.img_picto($langs->trans($text_off), $switchoff, '', false, 0, 0, '', $cssswitchoff).''; + $out .= ''.img_picto($langs->trans($text_on), $switchon, '', false, 0, 0, '', $cssswitchon).''; + } else { + $out .= ''.img_picto($langs->trans($text_off), $switchoff, '', false, 0, 0, '', $cssswitchoff).''; + $out .= ''.img_picto($langs->trans($text_on), $switchon, '', false, 0, 0, '', $cssswitchon).''; + } return $out; } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index d3276916747..c3fdbf377a3 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -11328,6 +11328,12 @@ function getElementProperties($element_type) $classpath = 'contrat/class'; $module = 'contrat'; $subelement = 'contrat'; + } elseif ($element_type == 'mailing') { + $classpath = 'comm/mailing/class'; + $module = 'mailing'; + $classfile = 'mailing'; + $classname = 'Mailing'; + $subelement = ''; } elseif ($element_type == 'member') { $classpath = 'adherents/class'; $module = 'adherent'; @@ -11424,7 +11430,6 @@ function fetchObjectByElement($element_id, $element_type, $element_ref = '') $ret = 0; $element_prop = getElementProperties($element_type); - //var_dump($element_prop); if (is_array($element_prop) && isModEnabled($element_prop['module'])) { dol_include_once('/'.$element_prop['classpath'].'/'.$element_prop['classfile'].'.class.php'); diff --git a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql index a5b1406cfdb..f8c48e6c3ee 100644 --- a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql +++ b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql @@ -388,5 +388,6 @@ ALTER TABLE llx_bordereau_cheque ADD COLUMN label varchar(255) AFTER ref; ALTER TABLE llx_c_email_templates add COLUMN defaultfortype smallint DEFAULT 0; +ALTER TABLE llx_mailing ADD COLUMN fk_user_modif integer AFTER fk_user_creat; ALTER TABLE llx_mailing ADD COLUMN evenunsubscribe smallint DEFAULT 0; diff --git a/htdocs/install/mysql/tables/llx_mailing-mailing.sql b/htdocs/install/mysql/tables/llx_mailing-mailing.sql index 39392502053..fa97a3944aa 100644 --- a/htdocs/install/mysql/tables/llx_mailing-mailing.sql +++ b/htdocs/install/mysql/tables/llx_mailing-mailing.sql @@ -46,6 +46,7 @@ create table llx_mailing date_envoi datetime, -- date d'envoi tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, fk_user_creat integer, -- user creator + fk_user_modif integer, -- user of last modification fk_user_valid integer, -- user validator fk_user_appro integer, -- not used extraparams varchar(255), -- for stock other parameters with json format From f4d60d0b702a69d6c990b8d950e0bddb2e488643 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 13:04:37 +0200 Subject: [PATCH 115/417] Add field name_from --- htdocs/install/mysql/migration/17.0.0-18.0.0.sql | 1 + htdocs/install/mysql/tables/llx_mailing-mailing.sql | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql index f8c48e6c3ee..ace06434949 100644 --- a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql +++ b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql @@ -390,4 +390,5 @@ ALTER TABLE llx_c_email_templates add COLUMN defaultfortype smallint DEFAULT 0; ALTER TABLE llx_mailing ADD COLUMN fk_user_modif integer AFTER fk_user_creat; ALTER TABLE llx_mailing ADD COLUMN evenunsubscribe smallint DEFAULT 0; +ALTER TABLE llx_mailing ADD COLUMN name_from varchar(128) AFTER email_from; diff --git a/htdocs/install/mysql/tables/llx_mailing-mailing.sql b/htdocs/install/mysql/tables/llx_mailing-mailing.sql index fa97a3944aa..f8ee1c567b9 100644 --- a/htdocs/install/mysql/tables/llx_mailing-mailing.sql +++ b/htdocs/install/mysql/tables/llx_mailing-mailing.sql @@ -18,10 +18,10 @@ -- ======================================================================== --- redaction : 0 --- valide : 1 --- approuve : 2 --- envoye : 3 +-- draft : 0 +-- valid : 1 +-- approved : 2 +-- sent : 3 create table llx_mailing ( @@ -37,6 +37,7 @@ create table llx_mailing cible varchar(60), nbemail integer, email_from varchar(160), -- Email address of sender + name_from varchar(128), -- Name to show of sender email_replyto varchar(160), -- Email address for reply email_errorsto varchar(160), -- Email addresse for errors tag varchar(128) NULL, From b9e08dafab422654c79cf3c0e8d2dfb2d89cd451 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 13:09:39 +0200 Subject: [PATCH 116/417] css --- htdocs/comm/mailing/card.php | 4 ++-- htdocs/comm/mailing/cibles.php | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index baa4fd9a711..f77833c0e37 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -981,9 +981,9 @@ if ($action == 'create') { print '
    '.$form->select_dolusers(($search_user > 0 ? $search_user : -1), 'search_user', 1, null, 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth250').''.$form->select_dolusers(($search_user > 0 ? $search_user : -1), 'search_user', 1, null, 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth150').'
    '; + print ''; if (($action == 'editline' || $action == 'splitline') && GETPOST('lineid', 'int') == $task_time->rowid) { print ''; print ''; @@ -2092,6 +2124,10 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } } } + print ''; + print ''; if ($task_time->fk_soc > 0) { if (empty($conf->cache['thridparty'][$task_time->fk_soc])) { $tmpsociete = new Societe($db); @@ -2132,7 +2168,6 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // Thirdparty alias if (!empty($arrayfields['s.name_alias']['checked'])) { - print ''; if ($task_time->fk_soc > 0) { if (empty($conf->cache['thridparty'][$task_time->fk_soc])) { $tmpsociete = new Societe($db); @@ -2141,8 +2176,10 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } else { $tmpsociete = $conf->cache['thridparty'][$task_time->fk_soc]; } - print $tmpsociete->name_alias; + $valtoshow = $tmpsociete->name_alias; } + print ''; + print $valtoshow; print '
    '.$langs->trans("Total").''.$langs->trans("Totalforthispage").''.$form->textwithpicto($langs->trans("Total"), $langs->trans("Totalforthispage")).''.convertSecondToTime($totalarray['totalduration'], 'allhourmin').''; + if(!empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) && $tmpwarehouse->id > 0) { + print img_picto('', $tmpwarehouse->picto)." ".$tmpwarehouse->label; + } print ''; - if(!empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) && $tmpwarehouse->id > 0) { + if (!empty($conf->global->STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE) && $tmpwarehouse->id > 0) { print img_picto('', $tmpwarehouse->picto)." ".$tmpwarehouse->label; } print '
    '; // Number of distinct emails - print ''; print ''; print '"; print '"; print ""; + + $i++; } } @@ -1336,6 +1338,8 @@ if (empty($action) || $action == 'view') { print '"; print ""; + + $i++; } } } else { // Waiting account @@ -1373,11 +1377,18 @@ if (empty($action) || $action == 'view') { print '"; print '"; print ""; + + $i++; } } } } + if (!$i) { + $colspan = 8; + print ''; + } + print "
    '; + print '
    '; print $langs->trans("TotalNbOfDistinctRecipients"); - print ''; + print ''; $nbemail = ($object->nbemail ? $object->nbemail : 0); if (is_numeric($nbemail)) { $text = ''; diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index caa371ac59e..38550b62422 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -285,9 +285,7 @@ if ($object->fetch($id) >= 0) { print ''; - //print ''; - - print ''; // Errors to - print ''; print ''; print "\n"; -// TO DO Mutualize code for yes/no constants -print ''; -print ''; -if (!empty($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO)) { - print ''; -} else { - print ''; -} -print ''; - -print ''; -print ''; -if (!empty($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE)) { - print ''; -} else { - print ''; -} -print ''; - // Param a user $user->rights->accounting->chartofaccount can access foreach ($list_binding as $key) { print ''; diff --git a/htdocs/accountancy/customer/lines.php b/htdocs/accountancy/customer/lines.php index a0488793ebf..0e5ecd25563 100644 --- a/htdocs/accountancy/customer/lines.php +++ b/htdocs/accountancy/customer/lines.php @@ -65,10 +65,10 @@ $search_country = GETPOST('search_country', 'alpha'); $search_tvaintra = GETPOST('search_tvaintra', 'alpha'); // Load variable for pagination -$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); -$page = GETPOSTISSET('pageplusonPour le détail de la facture ref…e') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page < 0) { $page = 0; } @@ -81,6 +81,8 @@ if (!$sortfield) { if (!$sortorder) { if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE > 0) { $sortorder = "DESC"; + } else { + $sortorder = "ASC"; } } @@ -159,6 +161,12 @@ if (is_array($changeaccount) && count($changeaccount) > 0 && $user->hasRight('ac } } +if (GETPOST('sortfield') == 'f.datef, f.ref, fd.rowid') { + $value = (GETPOST('sortorder') == 'asc,asc,asc' ? 0 : 1); + require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + $res = dolibarr_set_const($db, "ACCOUNTING_LIST_SORT_VENTILATION_DONE", $value, 'yesno', 0, '', $conf->entity); +} + /* * View diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index 753ad06a503..509e131f766 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -91,6 +91,8 @@ if (!$sortfield) { if (!$sortorder) { if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO > 0) { $sortorder = "DESC"; + } else { + $sortorder = "ASC"; } } @@ -208,6 +210,11 @@ if ($massaction == 'ventil' && $user->rights->accounting->bind->write) { } } +if (GETPOST('sortfield') == 'f.datef, f.ref, l.rowid') { + $value = (GETPOST('sortorder') == 'asc,asc,asc' ? 0 : 1); + require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + $res = dolibarr_set_const($db, "ACCOUNTING_LIST_SORT_VENTILATION_TODO", $value, 'yesno', 0, '', $conf->entity); +} /* diff --git a/htdocs/accountancy/expensereport/lines.php b/htdocs/accountancy/expensereport/lines.php index f38b617509e..fbb92ebb18e 100644 --- a/htdocs/accountancy/expensereport/lines.php +++ b/htdocs/accountancy/expensereport/lines.php @@ -75,6 +75,8 @@ if (!$sortfield) { if (!$sortorder) { if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE > 0) { $sortorder = "DESC"; + } else { + $sortorder = "ASC"; } } @@ -149,6 +151,12 @@ if (is_array($changeaccount) && count($changeaccount) > 0 && $user->rights->acco } } +if (GETPOST('sortfield') == 'erd.date, erd.rowid') { + $value = (GETPOST('sortorder') == 'asc,asc' ? 0 : 1); + require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + $res = dolibarr_set_const($db, "ACCOUNTING_LIST_SORT_VENTILATION_DONE", $value, 'yesno', 0, '', $conf->entity); +} + /* * View diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index 0eb84e6d77b..e8822f2f669 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -84,6 +84,8 @@ if (!$sortfield) { if (!$sortorder) { if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO > 0) { $sortorder = "DESC"; + } else { + $sortorder = "ASC"; } } @@ -199,6 +201,11 @@ if ($massaction == 'ventil' && $user->rights->accounting->bind->write) { } } +if (GETPOST('sortfield') == 'erd.date, erd.rowid') { + $value = (GETPOST('sortorder') == 'asc,asc' ? 0 : 1); + require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + $res = dolibarr_set_const($db, "ACCOUNTING_LIST_SORT_VENTILATION_TODO", $value, 'yesno', 0, '', $conf->entity); +} /* diff --git a/htdocs/accountancy/supplier/lines.php b/htdocs/accountancy/supplier/lines.php index 1eef199894d..11c4bf290fd 100644 --- a/htdocs/accountancy/supplier/lines.php +++ b/htdocs/accountancy/supplier/lines.php @@ -83,6 +83,8 @@ if (!$sortfield) { if (!$sortorder) { if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_DONE > 0) { $sortorder = "DESC"; + } else { + $sortorder = "ASC"; } } @@ -164,6 +166,12 @@ if (is_array($changeaccount) && count($changeaccount) > 0 && $user->rights->acco } } +if (GETPOST('sortfield') == 'f.datef, f.ref, l.rowid') { + $value = (GETPOST('sortorder') == 'asc,asc,asc' ? 0 : 1); + require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + $res = dolibarr_set_const($db, "ACCOUNTING_LIST_SORT_VENTILATION_DONE", $value, 'yesno', 0, '', $conf->entity); +} + /* * View diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index 03b3fb8eeec..9c9ee109383 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -93,6 +93,8 @@ if (!$sortfield) { if (!$sortorder) { if ($conf->global->ACCOUNTING_LIST_SORT_VENTILATION_TODO > 0) { $sortorder = "DESC"; + } else { + $sortorder = "ASC"; } } @@ -210,6 +212,11 @@ if ($massaction == 'ventil' && $user->rights->accounting->bind->write) { } } +if (GETPOST('sortfield') == 'f.datef, f.ref, l.rowid') { + $value = (GETPOST('sortorder') == 'asc,asc,asc' ? 0 : 1); + require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + $res = dolibarr_set_const($db, "ACCOUNTING_LIST_SORT_VENTILATION_TODO", $value, 'yesno', 0, '', $conf->entity); +} /* diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index c3fdbf377a3..a839daf86d5 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5329,7 +5329,7 @@ function getTitleFieldOfList($name, $thead = 0, $file = "", $field = "", $begin $options = '&'.$options; } - if (!$sortorder || $field1 != $sortfield1) { + if (!$sortorder || ($field1 != $sortfield1)) { //$out.= ''.img_down("A-Z",0).''; //$out.= ''.img_up("Z-A",0).''; } else { diff --git a/htdocs/core/modules/modAccounting.class.php b/htdocs/core/modules/modAccounting.class.php index 8aa1b0ec9ef..7a4ffabd4ab 100644 --- a/htdocs/core/modules/modAccounting.class.php +++ b/htdocs/core/modules/modAccounting.class.php @@ -124,18 +124,6 @@ class modAccounting extends DolibarrModules "", "", 0, 'current', 0 ); - $this->const[9] = array( - "ACCOUNTING_LIST_SORT_VENTILATION_TODO", - "yesno", - "1", - "", 0, 'current', 0 - ); - $this->const[10] = array( - "ACCOUNTING_LIST_SORT_VENTILATION_DONE", - "yesno", - "1", - "", 0, 'current', 0 - ); $this->const[11] = array( "ACCOUNTING_EXPORT_DATE", "chaine", From 976c2d76f260d73cd5508fe837e487675228d156 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 22:10:56 +0200 Subject: [PATCH 124/417] Try fix MS OAuth2 Imap (from feedback at dolibarr.org/forum/t/emailcollectors-with-microsoft-365-oauth2) --- htdocs/core/lib/oauth.lib.php | 2 +- htdocs/includes/OAuth/OAuth2/Service/Microsoft.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/oauth.lib.php b/htdocs/core/lib/oauth.lib.php index 8a81d9a80e5..aaac40a525f 100644 --- a/htdocs/core/lib/oauth.lib.php +++ b/htdocs/core/lib/oauth.lib.php @@ -32,7 +32,7 @@ if (isModEnabled('stripe')) { $supportedoauth2array['OAUTH_STRIPE_LIVE_NAME'] = array('callbackfile' => 'stripelive', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeLive', 'urlforcredentials'=>'', 'availablescopes'=>'read_write', 'returnurl'=>'/core/modules/oauth/stripelive_oauthcallback.php'); } $supportedoauth2array['OAUTH_GITHUB_NAME'] = array('callbackfile' => 'github', 'picto' => 'github', 'urlforapp' => 'OAUTH_GITHUB_DESC', 'name'=>'GitHub', 'urlforcredentials'=>'https://github.com/settings/developers', 'availablescopes'=>'user,public_repo', 'returnurl'=>'/core/modules/oauth/github_oauthcallback.php'); -$supportedoauth2array['OAUTH_MICROSOFT_NAME'] = array('callbackfile' => 'microsoft', 'picto' => 'microsoft', 'urlforapp' => 'OAUTH_MICROSOFT_DESC', 'name'=>'Microsoft', 'urlforcredentials'=>'https://portal.azure.com/', 'availablescopes'=>'openid,offline_access,profile,email,User.Read,https://outlook.office365.com/IMAP.AccessAsUser.All,https://outlook.office365.com/SMTP.Send', 'returnurl'=>'/core/modules/oauth/microsoft_oauthcallback.php'); +$supportedoauth2array['OAUTH_MICROSOFT_NAME'] = array('callbackfile' => 'microsoft', 'picto' => 'microsoft', 'urlforapp' => 'OAUTH_MICROSOFT_DESC', 'name'=>'Microsoft', 'urlforcredentials'=>'https://portal.azure.com/', 'availablescopes'=>'openid,offline_access,profile,email,User.Read,https://outlook.office.com/IMAP.AccessAsUser.All,https://outlook.office.com/SMTP.Send', 'returnurl'=>'/core/modules/oauth/microsoft_oauthcallback.php'); if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { $supportedoauth2array['OAUTH_OTHER_NAME'] = array('callbackfile' => 'generic', 'picto' => 'generic', 'urlforapp' => 'OAUTH_OTHER_DESC', 'name'=>'Other', 'urlforcredentials'=>'', 'availablescopes'=>'Standard', 'returnurl'=>'/core/modules/oauth/generic_oauthcallback.php'); // See https://learn.microsoft.com/fr-fr/azure/active-directory/develop/quickstart-register-app#register-an-application diff --git a/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php b/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php index 6c3b18b3c0f..90c20405e6b 100644 --- a/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php +++ b/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php @@ -38,8 +38,8 @@ class Microsoft extends AbstractService const SCOPE_APPLICATIONS = 'applications'; const SCOPE_APPLICATIONS_CREATE = 'applications_create'; const SCOPE_IMAP = 'imap'; - const SOCPE_IMAP_ACCESSASUSERALL = 'https://outlook.office365.com/IMAP.AccessAsUser.All'; - const SOCPE_SMTPSEND = 'https://outlook.office365.com/SMTP.Send'; + const SOCPE_IMAP_ACCESSASUSERALL = 'https://outlook.office.com/IMAP.AccessAsUser.All'; + const SOCPE_SMTPSEND = 'https://outlook.office.com/SMTP.Send'; const SOCPE_USERREAD = 'User.Read'; const SOCPE_MAILREAD = 'Mail.Read'; const SOCPE_MAILSEND = 'Mail.Send'; From 74d41c3d11cc99b553ee1db65b87d4c99401e5f4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 22:44:55 +0200 Subject: [PATCH 125/417] Add support for keyboard shortcut ALT + S to open search box --- htdocs/core/class/html.form.class.php | 2 +- htdocs/main.inc.php | 28 +++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index c45ab42fec0..eea1047bc51 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8401,7 +8401,7 @@ class Form return ''; } - $out = ''; + $out = ''; $formattedarrayresult = array(); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index bfcb5dab7ce..ce7a7a9ec8d 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2544,7 +2544,7 @@ function top_menu_user($hideloginname = 0, $urllogout = '') */ function top_menu_quickadd() { - global $langs; + global $conf, $langs; $html = ''; @@ -2846,7 +2846,6 @@ function top_menu_bookmark() } }); - var openBookMarkDropDown = function() { event.preventDefault(); jQuery("#topmenu-bookmark-dropdown").toggleClass("open"); @@ -2991,13 +2990,16 @@ function top_menu_search() // Key map shortcut jQuery(document).keydown(function(e){ - if( e.which === 70 && e.ctrlKey && e.shiftKey ){ + if ( e.which === 70 && e.ctrlKey && e.shiftKey ) { console.log(\'control + shift + f : trigger open global-search dropdown\'); openGlobalSearchDropDown(); } + if ( e.which === 70 && e.alKey ) { + console.log(\'alt + f : trigger open global-search dropdown\'); + openGlobalSearchDropDown(); + } }); - var openGlobalSearchDropDown = function() { jQuery("#topmenu-global-search-dropdown").toggleClass("open"); jQuery("#top-global-search-input").focus(); @@ -3091,6 +3093,24 @@ function left_menu($menu_array_before, $helppagename = '', $notused = '', $menu_ ' . "\n"; $searchform .= ''; } + + // Key map shortcut + $searchform .= ''; } // Left column From d5bc5a5d4f946e3c61aaa72b43a88af8d82c8f05 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 00:28:29 +0200 Subject: [PATCH 126/417] Try a better implementation of ajax tooltip to avoid all on fast hover --- htdocs/core/js/lib_foot.js.php | 58 ++++++++++++++++++-------- htdocs/societe/class/societe.class.php | 2 +- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/htdocs/core/js/lib_foot.js.php b/htdocs/core/js/lib_foot.js.php index 7e300ddebc0..d8f1450d025 100644 --- a/htdocs/core/js/lib_foot.js.php +++ b/htdocs/core/js/lib_foot.js.php @@ -79,26 +79,48 @@ if (empty($conf->dol_no_mouse_hover)) { return $(this).prop("title"); /* To force to get title as is */ } }); - jQuery(".classforajaxtooltip").tooltip({ - show: { collision: "flipfit", effect:"toggle", delay:50, duration: 20 }, - hide: { delay: 250, duration: 20 }, + + var opendelay = 80; + var elemtostoretooltiptimer = jQuery("#dialogforpopup"); + + target = jQuery(".classforajaxtooltip"); + target.tooltip({ tooltipClass: "mytooltip", - open: function (event, ui) { - var elem = $(this); - var params = JSON.parse($(this).attr("data-params")); - var currenttoken = jQuery("meta[name=anti-csrf-currenttoken]").attr("content"); - params.token = currenttoken; + show: { collision: "flipfit", effect:"toggle", delay: 0, duration: 20 }, + hide: { delay: 250, duration: 20 } + }); + + target.off("mouseover mouseout"); + target.on("mouseover", function(event) { + console.log("we will create timer for ajax call"); + var params = JSON.parse($(this).attr("data-params")); + var elemfortooltip = $(this); + var currenttoken = jQuery("meta[name=anti-csrf-currenttoken]").attr("content"); + params.token = currenttoken; + + event.stopImmediatePropagation(); + clearTimeout(elemtostoretooltiptimer.data("openTimeoutId")); + elemtostoretooltiptimer.data("openTimeoutId", setTimeout(function() { + target.tooltip("close"); $.ajax({ - url:"'. DOL_URL_ROOT.'/core/ajax/ajaxtooltip.php", - type: "post", - async: false, - data: params, - success: function(response){ - // Setting content option - elem.tooltip("option","content",response); - } - }); - } + url:"'. DOL_URL_ROOT.'/core/ajax/ajaxtooltip.php", + type: "post", + async: true, + data: params, + success: function(response){ + // Setting content option + console.log("ajax success"); + elemfortooltip.tooltip("option","content",response); + elemfortooltip.tooltip("open"); + } + }); + }, opendelay)); + }); + target.on("mouseout", function(event) { + console.log("mouse out"); + event.stopImmediatePropagation(); + clearTimeout(elemtostoretooltiptimer.data("openTimeoutId")); + target.tooltip("close"); }); '; } diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index f85f03cf8d8..402d649b9bb 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -2917,7 +2917,7 @@ class Societe extends CommonObject $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright' : '').'"'), 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { $result .= dol_escape_htmltag($maxlen ? dol_trunc($name, $maxlen) : $name); From 91c8ca1e38818b1584c8796ae6087cfacad4ef6b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 00:48:17 +0200 Subject: [PATCH 127/417] Clean code --- htdocs/adherents/class/adherent.class.php | 3 +-- htdocs/adherents/class/adherent_type.class.php | 2 +- htdocs/core/js/lib_foot.js.php | 5 +++-- htdocs/societe/class/societe.class.php | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 7f9adb32266..5a6853a5f9b 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -2413,8 +2413,7 @@ class Adherent extends CommonObject } // Only picto if ($withpictoimg > 0) { - $picto = ''. - img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : $dataparams.' class="'.$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1).''; + $picto = ''.img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : $dataparams), 0, 0, $notooltip ? 0 : 1).''; } else { // Picto must be a photo $picto = ''; diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 9ee0de6c055..ea7c68bbff8 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -774,7 +774,7 @@ class AdherentType extends CommonObject $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (' class="'.(($withpicto != 2) ? 'paddingright' : '').'"'), 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { $result .= ($maxlen ?dol_trunc($this->label, $maxlen) : $this->label); diff --git a/htdocs/core/js/lib_foot.js.php b/htdocs/core/js/lib_foot.js.php index d8f1450d025..e5041378ef6 100644 --- a/htdocs/core/js/lib_foot.js.php +++ b/htdocs/core/js/lib_foot.js.php @@ -82,6 +82,7 @@ if (empty($conf->dol_no_mouse_hover)) { var opendelay = 80; var elemtostoretooltiptimer = jQuery("#dialogforpopup"); + var currenttoken = jQuery("meta[name=anti-csrf-currenttoken]").attr("content"); target = jQuery(".classforajaxtooltip"); target.tooltip({ @@ -92,11 +93,11 @@ if (empty($conf->dol_no_mouse_hover)) { target.off("mouseover mouseout"); target.on("mouseover", function(event) { +console.log(this); console.log("we will create timer for ajax call"); var params = JSON.parse($(this).attr("data-params")); - var elemfortooltip = $(this); - var currenttoken = jQuery("meta[name=anti-csrf-currenttoken]").attr("content"); params.token = currenttoken; + var elemfortooltip = $(this); event.stopImmediatePropagation(); clearTimeout(elemtostoretooltiptimer.data("openTimeoutId")); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 402d649b9bb..9415901152e 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -2917,7 +2917,7 @@ class Societe extends CommonObject $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright' : '').'"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (' class="'.(($withpicto != 2) ? 'paddingright' : '').'"'), 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { $result .= dol_escape_htmltag($maxlen ? dol_trunc($name, $maxlen) : $name); From aea1f60c678ff7b1696e6a947d90565eb1a62db4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 01:39:47 +0200 Subject: [PATCH 128/417] Debug v18 --- htdocs/bom/class/bom.class.php | 2 +- htdocs/core/js/lib_foot.js.php | 1 - htdocs/core/lib/functions.lib.php | 7 +++++++ htdocs/modulebuilder/template/class/myobject.class.php | 2 +- htdocs/mrp/class/mo.class.php | 2 +- htdocs/product/class/product.class.php | 4 ++-- htdocs/projet/class/project.class.php | 2 +- htdocs/projet/class/task.class.php | 2 +- htdocs/user/class/user.class.php | 2 +- htdocs/workstation/class/workstation.class.php | 2 +- 10 files changed, 16 insertions(+), 10 deletions(-) diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 45cbfdef383..43a40705660 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1168,7 +1168,7 @@ class BOM extends CommonObject $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { $result .= $this->ref; diff --git a/htdocs/core/js/lib_foot.js.php b/htdocs/core/js/lib_foot.js.php index e5041378ef6..fb6f4597c0a 100644 --- a/htdocs/core/js/lib_foot.js.php +++ b/htdocs/core/js/lib_foot.js.php @@ -93,7 +93,6 @@ if (empty($conf->dol_no_mouse_hover)) { target.off("mouseover mouseout"); target.on("mouseover", function(event) { -console.log(this); console.log("we will create timer for ajax call"); var params = JSON.parse($(this).attr("data-params")); params.token = currenttoken; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index a839daf86d5..c0c22a94ec1 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -11338,6 +11338,12 @@ function getElementProperties($element_type) $classpath = 'adherents/class'; $module = 'adherent'; $subelement = 'adherent'; + } elseif ($element_type == 'mo') { + $classpath = 'mrp/class'; + $classfile = 'mo'; + $classname = 'Mo'; + $module = 'mrp'; + $subelement = ''; } elseif ($element_type == 'cabinetmed_cons') { $classpath = 'cabinetmed/class'; $module = 'cabinetmed'; @@ -11430,6 +11436,7 @@ function fetchObjectByElement($element_id, $element_type, $element_ref = '') $ret = 0; $element_prop = getElementProperties($element_type); + //var_dump($element_prop); if (is_array($element_prop) && isModEnabled($element_prop['module'])) { dol_include_once('/'.$element_prop['classpath'].'/'.$element_prop['classfile'].'.class.php'); diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 4a310d51cfb..d57a1fca39f 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -851,7 +851,7 @@ class MyObject extends CommonObject if (empty($this->showphoto_on_popup)) { if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1); } } else { if ($withpicto) { diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index c5b1b061e54..100043ef055 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -1220,7 +1220,7 @@ class Mo extends CommonObject $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { $result .= $this->ref; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index f0e3f8f0b00..67002e48efb 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -5207,10 +5207,10 @@ class Product extends CommonObject $result .= $linkstart; if ($withpicto) { if ($this->type == Product::TYPE_PRODUCT) { - $result .= (img_object(($notooltip ? '' : $label), 'product', ($notooltip ? 'class="paddingright"' : $dataparams.' class="paddingright '.$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1)); + $result .= (img_object(($notooltip ? '' : $label), 'product', 'class="paddingright"', 0, 0, $notooltip ? 0 : 1)); } if ($this->type == Product::TYPE_SERVICE) { - $result .= (img_object(($notooltip ? '' : $label), 'service', ($notooltip ? 'class="paddingright"' : $dataparams.' class="paddingright '.$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1)); + $result .= (img_object(($notooltip ? '' : $label), 'service', 'class="paddingright"', 0, 0, $notooltip ? 0 : 1)); } } $result .= dol_escape_htmltag($newref); diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 9f00d4ce3c0..0b8f48c90e3 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -1383,7 +1383,7 @@ class Project extends CommonObject $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), $picto, ($notooltip ? (($withpicto != 2) ? 'class="pictofixedwidth"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'pictofixedwidth ' : '').$classfortooltip.' pictofixedwidth em088"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), $picto, 'class="pictofixedwidth em088"', 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { $result .= $this->ref; diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 3f4293c1c0e..cf356d070b7 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -796,7 +796,7 @@ class Task extends CommonObjectLine $result .= $linkstart; if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), $picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), $picto, 'class="paddingright"', 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { $result .= $this->ref; diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 70118961c19..3bc86df0225 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2924,7 +2924,7 @@ class User extends CommonObject } // Only picto if ($withpictoimg > 0) { - $picto = ''.img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : $dataparams.' class="paddingright '.$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1).''; + $picto = ''.img_object('', 'user', $paddafterimage.' class="paddingright")', 0, 0, $notooltip ? 0 : 1).''; } else { // Picto must be a photo $picto = ''.Form::showphoto('userphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg == -3 ? 'small' : ''), 'mini', 0, 1).''; diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php index dcdde005130..3a9e4622af8 100644 --- a/htdocs/workstation/class/workstation.class.php +++ b/htdocs/workstation/class/workstation.class.php @@ -649,7 +649,7 @@ class Workstation extends CommonObject if (empty($this->showphoto_on_popup)) { if ($withpicto) { - $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'mrp'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1); + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'mrp'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1); } } else { if ($withpicto) { From 2ebfb1880960ca0c5d41c7f8728ca22c26474c1d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 01:55:31 +0200 Subject: [PATCH 129/417] Debug v18 --- htdocs/accountancy/journal/variousjournal.php | 17 ++++++++++++++--- htdocs/projet/index.php | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/htdocs/accountancy/journal/variousjournal.php b/htdocs/accountancy/journal/variousjournal.php index cf652a29345..621683ea4cb 100644 --- a/htdocs/accountancy/journal/variousjournal.php +++ b/htdocs/accountancy/journal/variousjournal.php @@ -272,9 +272,10 @@ $object_label = $langs->trans("ObjectsRef"); if ($object->nature == 2 || $object->nature == 3) $object_label = $langs->trans("InvoiceRef"); if ($object->nature == 5) $object_label = $langs->trans("ExpenseReportRef"); -/* - * Show result array - */ + +// Show result array +$i = 0; + print '
    '; print '
    '; @@ -304,11 +305,21 @@ if (is_array($journal_data) && !empty($journal_data)) { print '
    '; print ''; print ''; + + $i++; } } } } +if (!$i) { + $colspan = 7; + if ($object->nature == 4) { + $colspan++; + } + print ''; +} + print '
    '.$langs->trans("MailTitle").''.$object->title.'
    '.$langs->trans("MailFrom").''; + print '
    '.$langs->trans("MailFrom").''; $emailarray = CMailFile::getArrayAddress($object->email_from); foreach ($emailarray as $email => $name) { if ($name && $name != $email) { @@ -306,7 +304,7 @@ if ($object->fetch($id) >= 0) { print '
    '.$langs->trans("MailErrorsTo").''; + print '
    '.$langs->trans("MailErrorsTo").''; $emailarray = CMailFile::getArrayAddress($object->email_errorsto); foreach ($emailarray as $email => $name) { if ($name != $email) { @@ -331,10 +329,10 @@ if ($object->fetch($id) >= 0) { print ''; - // Nb of distinct emails - print ''; // Status of recipient sending email (Warning != status of emailing) - if ($obj->statut == 0) { + if ($obj->statut == $object::STATUS_DRAFT) { // Date sent print ''; diff --git a/htdocs/comm/mailing/class/mailing.class.php b/htdocs/comm/mailing/class/mailing.class.php index 9ad466f9671..451478e8058 100644 --- a/htdocs/comm/mailing/class/mailing.class.php +++ b/htdocs/comm/mailing/class/mailing.class.php @@ -905,7 +905,7 @@ class Mailing extends CommonObject /** - * Return the label of a given status of a recipient + * Return the label of a given status of a recipient * TODO Add class mailin_target.class.php * * @param int $status Id status diff --git a/htdocs/core/modules/mailings/modules_mailings.php b/htdocs/core/modules/mailings/modules_mailings.php index b99d012f6a9..8ab6184c9a3 100644 --- a/htdocs/core/modules/mailings/modules_mailings.php +++ b/htdocs/core/modules/mailings/modules_mailings.php @@ -158,7 +158,7 @@ class MailingTargets // This can't be abstract as it is used for some method $nb = $obj->nb; $sql = "UPDATE ".MAIN_DB_PREFIX."mailing"; - $sql .= " SET nbemail = ".$nb." WHERE rowid = ".((int) $mailing_id); + $sql .= " SET nbemail = ".((int) $nb)." WHERE rowid = ".((int) $mailing_id); if (!$this->db->query($sql)) { dol_syslog($this->db->error()); $this->error = $this->db->error(); @@ -171,11 +171,11 @@ class MailingTargets // This can't be abstract as it is used for some method } /** - * Add a list of targets int the database + * Add a list of targets into the database * * @param int $mailing_id Id of emailing * @param array $cibles Array with targets - * @return int < 0 si erreur, nb ajout si ok + * @return int < 0 if error, nb added if OK */ public function addTargetsToDatabase($mailing_id, $cibles) { @@ -241,16 +241,20 @@ class MailingTargets // This can't be abstract as it is used for some method $result=$this->db->query($sql); */ - $sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles"; - $sql .= " SET statut=3"; - $sql .= " WHERE fk_mailing = ".((int) $mailing_id)." AND email IN (SELECT mu.email FROM ".MAIN_DB_PREFIX."mailing_unsubscribe AS mu WHERE mu.entity IN ('".getEntity('mailing')."'))"; + if (empty($this->evenunsubscribe)) { + $sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles"; + $sql .= " SET statut = 3"; + $sql .= " WHERE fk_mailing = ".((int) $mailing_id); + $sql .= " AND EXISTS (SELECT rowid FROM ".MAIN_DB_PREFIX."mailing_unsubscribe as mu WHERE mu.email = email and mu.entity = ".((int) $conf->entity).")"; - dol_syslog(__METHOD__.":mailing update status to display emails that do not want to be contacted anymore", LOG_DEBUG); - $result = $this->db->query($sql); - if (!$result) { - dol_print_error($this->db); + dol_syslog(__METHOD__.":mailing update status to display emails that do not want to be contacted anymore", LOG_DEBUG); + $result = $this->db->query($sql); + if (!$result) { + dol_print_error($this->db); + } } + // Update nb of recipient into emailing record $this->update_nb($mailing_id); $this->db->commit(); From f88910c7865c343ed2077ff28564d8888ad05cf3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 14:44:22 +0200 Subject: [PATCH 120/417] Debug v18 --- htdocs/core/modules/mailings/modules_mailings.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/core/modules/mailings/modules_mailings.php b/htdocs/core/modules/mailings/modules_mailings.php index 8ab6184c9a3..5a99a44dc0f 100644 --- a/htdocs/core/modules/mailings/modules_mailings.php +++ b/htdocs/core/modules/mailings/modules_mailings.php @@ -195,15 +195,15 @@ class MailingTargets // This can't be abstract as it is used for some method $sql .= " lastname, firstname, email, other, source_url, source_id,"; $sql .= " tag,"; $sql .= " source_type)"; - $sql .= " VALUES (".$mailing_id.","; - $sql .= (empty($targetarray['fk_contact']) ? '0' : "'".$this->db->escape($targetarray['fk_contact'])."'").","; + $sql .= " VALUES (".((int) $mailing_id).","; + $sql .= (empty($targetarray['fk_contact']) ? '0' : (int) $targetarray['fk_contact']).","; $sql .= "'".$this->db->escape($targetarray['lastname'])."',"; $sql .= "'".$this->db->escape($targetarray['firstname'])."',"; $sql .= "'".$this->db->escape($targetarray['email'])."',"; $sql .= "'".$this->db->escape($targetarray['other'])."',"; $sql .= "'".$this->db->escape($targetarray['source_url'])."',"; $sql .= (empty($targetarray['source_id']) ? 'null' : "'".$this->db->escape($targetarray['source_id'])."'").","; - $sql .= "'".$this->db->escape(dol_hash($dolibarr_main_instance_unique_id.";".$targetarray['email'].";".$targetarray['lastname'].";".$mailing_id.";".$conf->global->MAILING_EMAIL_UNSUBSCRIBE_KEY, 'md5'))."',"; + $sql .= "'".$this->db->escape(dol_hash($dolibarr_main_instance_unique_id.";".$targetarray['email'].";".$targetarray['lastname'].";".((int) $mailing_id).";".getDolGlobalString('MAILING_EMAIL_UNSUBSCRIBE_KEY'), 'md5'))."',"; $sql .= "'".$this->db->escape($targetarray['source_type'])."')"; dol_syslog(__METHOD__, LOG_DEBUG); $result = $this->db->query($sql); @@ -242,10 +242,10 @@ class MailingTargets // This can't be abstract as it is used for some method */ if (empty($this->evenunsubscribe)) { - $sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles"; - $sql .= " SET statut = 3"; - $sql .= " WHERE fk_mailing = ".((int) $mailing_id); - $sql .= " AND EXISTS (SELECT rowid FROM ".MAIN_DB_PREFIX."mailing_unsubscribe as mu WHERE mu.email = email and mu.entity = ".((int) $conf->entity).")"; + $sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles as mc"; + $sql .= " SET mc.statut = 3"; + $sql .= " WHERE mc.fk_mailing = ".((int) $mailing_id); + $sql .= " AND EXISTS (SELECT rowid FROM ".MAIN_DB_PREFIX."mailing_unsubscribe as mu WHERE mu.email = mc.email and mu.entity = ".((int) $conf->entity).")"; dol_syslog(__METHOD__.":mailing update status to display emails that do not want to be contacted anymore", LOG_DEBUG); $result = $this->db->query($sql); From 3d11afc4e5b5b687d85b60259df264362b80504e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 14:52:36 +0200 Subject: [PATCH 121/417] Look and feel v18 --- htdocs/comm/mailing/cibles.php | 68 ++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index 8586c25b3dd..16b73702be0 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -643,6 +643,14 @@ if ($object->fetch($id) >= 0) { // Ligne des champs de filtres print ''; + + // Action column + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } // EMail print ''; // Action column - print ''; + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } + print ''; if ($page) { @@ -690,6 +701,10 @@ if ($object->fetch($id) >= 0) { } print ''; + // Action column + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'maxwidthsearch '); + } print_liste_field_titre("EMail", $_SERVER["PHP_SELF"], "mc.email", $param, "", "", $sortfield, $sortorder); print_liste_field_titre("Lastname", $_SERVER["PHP_SELF"], "mc.lastname", $param, "", "", $sortfield, $sortorder); print_liste_field_titre("Firstname", $_SERVER["PHP_SELF"], "mc.firstname", $param, "", "", $sortfield, $sortorder); @@ -700,7 +715,10 @@ if ($object->fetch($id) >= 0) { // Date sending print_liste_field_titre("DateSending", $_SERVER["PHP_SELF"], "mc.date_envoi", $param, '', 'align="center"', $sortfield, $sortorder); print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "mc.statut", $param, '', 'class="right"', $sortfield, $sortorder); - print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'maxwidthsearch '); + // Action column + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'maxwidthsearch '); + } print ''; $i = 0; @@ -722,6 +740,22 @@ if ($object->fetch($id) >= 0) { print ''; + // Action column + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } + print ''; } - // Search Icon - print ''; } - /*if ($obj->statut == -1) // Sent with error - { - print ''.$langs->trans("Retry").''; - }*/ - print ''; print ''; $i++; From 0662f2cc91c3cc1fc1151e50e321ba2fb29d19b0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 18:48:08 +0200 Subject: [PATCH 122/417] Try to add tooltips to explain goal of advanced options --- htdocs/accountancy/admin/index.php | 54 +++++++++---------- htdocs/admin/accounting.php | 1 + .../install/mysql/migration/17.0.0-18.0.0.sql | 4 +- htdocs/langs/en_US/accountancy.lang | 8 ++- 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 22d570fd5e7..0e9b9dbbd99 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -508,14 +508,20 @@ print ''; print '
    '; + // Number of distinct emails + print '
    '; print $langs->trans("TotalNbOfDistinctRecipients"); - print ''; + print ''; $nbemail = ($object->nbemail ? $object->nbemail : 0); if (is_numeric($nbemail)) { $text = ''; From f081768baa0ffd7729983acb0833d53971c3bb8e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 13:58:43 +0200 Subject: [PATCH 117/417] Test option MAIL_SMTP_USE_FROM_FOR_HELO to use domain of url --- htdocs/core/class/smtps.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/smtps.class.php b/htdocs/core/class/smtps.class.php index c6eb249be5c..e7b0207595a 100644 --- a/htdocs/core/class/smtps.class.php +++ b/htdocs/core/class/smtps.class.php @@ -476,13 +476,17 @@ class SMTPs if (!is_numeric($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) { // If value of MAIL_SMTP_USE_FROM_FOR_HELO is a string, we use it as domain name $hosth = $conf->global->MAIL_SMTP_USE_FROM_FOR_HELO; - } else { + } elseif ($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO == 1) { // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 1, we use the domain in the from. // So if the from to is 'aaa ', we will keep 'ccc.com' $hosth = $this->getFrom('addr'); $hosth = preg_replace('/^.*.*$/', '', $hosth); $hosth = preg_replace('/.*@/', '', $hosth); + } elseif ($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO == 2) { + // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 2, we use the domain in the $dolibarr_main_url_root. + global $dolibarr_main_url_root; + $hosth = getDomainFromURL($dolibarr_main_url_root, 1); } } From 6e93503898950038d4bf44223cc123e4bf23d5f2 Mon Sep 17 00:00:00 2001 From: Juanjo Menent Date: Sun, 9 Apr 2023 14:18:31 +0200 Subject: [PATCH 118/417] Fix #24355 Update price with discount --- htdocs/contrat/card.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 4e52941063d..7839d8ac241 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -744,12 +744,22 @@ if (empty($reshook)) { $fk_unit = GETPOST('unit', 'alpha'); + // update price_ht with discount + // TODO Use object->updateline instead objedtline->update + + $price_ht = price2num(GETPOST('elprice'), 'MU'); + $remise_percent = price2num(GETPOST('elremise_percent'), 2); + if ($remise_percent > 0) { + $remise = round(($price_ht * $remise_percent / 100), 2); + $price_ht = ($price_ht - $remise); + } + $objectline->fk_product = GETPOST('idprod', 'int'); $objectline->description = GETPOST('product_desc', 'restricthtml'); - $objectline->price_ht = price2num(GETPOST('elprice'), 'MU'); + $objectline->price_ht = $price_ht; $objectline->subprice = price2num(GETPOST('elprice'), 'MU'); $objectline->qty = price2num(GETPOST('elqty'), 'MS'); - $objectline->remise_percent = price2num(GETPOST('elremise_percent'), 2); + $objectline->remise_percent = $remise_percent; $objectline->tva_tx = ($txtva ? $txtva : 0); // Field may be disabled, so we use vat rate 0 $objectline->vat_src_code = $vat_src_code; $objectline->localtax1_tx = is_numeric($localtax1_tx) ? $localtax1_tx : 0; From 4c9e6e19970651ca0b9cd12156f8102e778886aa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 14:33:23 +0200 Subject: [PATCH 119/417] Fix opt-out email --- htdocs/comm/mailing/cibles.php | 4 ++-- htdocs/comm/mailing/class/mailing.class.php | 2 +- .../modules/mailings/modules_mailings.php | 24 +++++++++++-------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index 38550b62422..8586c25b3dd 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -265,7 +265,7 @@ if ($object->fetch($id) >= 0) { $morehtmlright = ''; $nbtry = $nbok = 0; - if ($object->statut == 2 || $object->statut == 3) { + if ($object->statut == $object::STATUS_SENTPARTIALY || $object->statut == $object::STATUS_SENTCOMPLETELY) { $nbtry = $object->countNbOfTargets('alreadysent'); $nbko = $object->countNbOfTargets('alreadysentko'); $nbok = ($nbtry - $nbko); @@ -767,7 +767,7 @@ if ($object->fetch($id) >= 0) { print '
    '; + $searchpicto = $form->showFilterAndCheckAddButtons($massactionbutton ? 1 : 0, 'checkforselect', 1); + print $searchpicto; + print ''; print ''; @@ -679,10 +687,13 @@ if ($object->fetch($id) >= 0) { print $formmailing->selectDestinariesStatus($search_dest_status, 'search_dest_status', 1); print ''; - $searchpicto = $form->showFilterAndCheckAddButtons($massactionbutton ? 1 : 0, 'checkforselect', 1); - print $searchpicto; - print ''; + $searchpicto = $form->showFilterAndCheckAddButtons($massactionbutton ? 1 : 0, 'checkforselect', 1); + print $searchpicto; + print '
    '; + print ''; + if ($obj->statut == $object::STATUS_DRAFT) { // Not sent yet + if (!empty($user->rights->mailing->creer)) { + print ''.img_delete($langs->trans("RemoveRecipient")).''; + } + } + /*if ($obj->statut == -1) // Sent with error + { + print ''.$langs->trans("Retry").''; + }*/ + print ''; print img_picto($obj->email, 'email', 'class="paddingright"'); if ($obj->nb > 0) { @@ -783,19 +817,21 @@ if ($object->fetch($id) >= 0) { print ''; - print ''; - if ($obj->statut == 0) { // Not sent yet - if (!empty($user->rights->mailing->creer)) { - print ''.img_delete($langs->trans("RemoveRecipient")).''; + // Action column + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + print ''; + if ($obj->statut == $object::STATUS_DRAFT) { // Not sent yet + if (!empty($user->rights->mailing->creer)) { + print ''.img_delete($langs->trans("RemoveRecipient")).''; + } } + /*if ($obj->statut == -1) // Sent with error + { + print ''.$langs->trans("Retry").''; + }*/ + print '
    '; print '
    '; -// Lettering params + +// Show advanced options +print '
    '; + + +// Advanced params print ''; print ''; -print ''; +print ''; print "\n"; print ''; -print ''; +print ''; if (!empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { print ''; if (!empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { print ''; - print ''; + print ''; if (!empty($conf->global->ACCOUNTING_ENABLE_AUTOLETTERING)) { print ''; } +print ''; +print ''; +if (!empty($conf->global->ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE)) { + print ''; +} else { + print ''; +} +print ''; + print '
    '.$langs->trans('Options').' '.$langs->trans('Lettering').'' . $langs->trans('OptionsAdvanced') . '
    '.$langs->trans("ACCOUNTING_ENABLE_LETTERING").''; +print $form->textwithpicto($langs->trans("ACCOUNTING_ENABLE_LETTERING"), $langs->trans("ACCOUNTING_ENABLE_LETTERING_DESC", $langs->transnoentitiesnoconv("NumMvts")).'
    '.$langs->trans("EnablingThisFeatureIsNotNecessary")).'
    '; print img_picto($langs->trans("Activated"), 'switch_on'); @@ -529,7 +535,8 @@ print '
    ' . $langs->trans("ACCOUNTING_ENABLE_AUTOLETTERING") . ''; + print $form->textwithpicto($langs->trans("ACCOUNTING_ENABLE_AUTOLETTERING"), $langs->trans("ACCOUNTING_ENABLE_AUTOLETTERING_DESC")) . ''; print img_picto($langs->trans("Activated"), 'switch_on'); @@ -542,33 +549,22 @@ if (!empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { print '
    '; +print $form->textwithpicto($langs->trans("ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE"), $langs->trans("ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE_DESC", $langs->transnoentities("MenuDefaultAccounts"))).''; + print img_picto($langs->trans("Activated"), 'switch_on'); + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print '
    '; -// Show specific accountancy FR option -if ($mysoc->country_code == 'FR') { - print '
    '; - - // Advanced params - print ''; - print ''; - print ''; - print "\n"; - - print ''; - print ''; - if (!empty($conf->global->ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE)) { - print ''; - } else { - print ''; - } - print ''; - - print '
    ' . $langs->trans('OptionsAdvanced') . '
    ' . $langs->trans("ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE") . ''; - print img_picto($langs->trans("Activated"), 'switch_on'); - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); - print '
    '; -} print '
    '; diff --git a/htdocs/admin/accounting.php b/htdocs/admin/accounting.php index fba458936b8..18d383a1b3c 100644 --- a/htdocs/admin/accounting.php +++ b/htdocs/admin/accounting.php @@ -55,6 +55,7 @@ $error = 0; $title = $langs->trans("ConfigAccountingExpert"); $help_url = ''; + llxHeader('', $title, $help_url); $linkback = ''.$langs->trans("BackToModuleList").''; diff --git a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql index a86404b105f..c4735898126 100644 --- a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql +++ b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql @@ -386,8 +386,8 @@ ALTER TABLE llx_product_fournisseur_price_log ADD INDEX idx_product_fournisseur_ ALTER TABLE llx_bordereau_cheque ADD COLUMN label varchar(255) AFTER ref; -ALTER TABLE llx_societe ADD COLUMN vat_reverse_charge smallint DEFAULT 0 AFTER tva_assuj; -ALTER TABLE llx_facture_fourn ADD COLUMN vat_reverse_charge smallint DEFAULT 0 AFTER close_note; +ALTER TABLE llx_societe ADD COLUMN vat_reverse_charge tinyint DEFAULT 0 AFTER tva_assuj; +ALTER TABLE llx_facture_fourn ADD COLUMN vat_reverse_charge tinyint DEFAULT 0 AFTER close_note; ALTER TABLE llx_c_email_templates add COLUMN defaultfortype smallint DEFAULT 0; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 79793817f5f..c3ac42a165d 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -345,9 +345,13 @@ ACCOUNTING_DISABLE_BINDING_ON_SALES=Disable binding & transfer in accountancy on ACCOUNTING_DISABLE_BINDING_ON_PURCHASES=Disable binding & transfer in accountancy on purchases (vendor invoices will not be taken into account in accounting) ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS=Disable binding & transfer in accountancy on expense reports (expense reports will not be taken into account in accounting) ACCOUNTING_ENABLE_LETTERING=Enable the lettering function in the accounting +ACCOUNTING_ENABLE_LETTERING_DESC=When this options is enabled, you can define, on each accounting entry, a code so you can group different accounting movements together. In the past, when different journals was managed independently, this feature was necessary to group movement lines of different journals together. However, with Dolibarr accountancy, such a tracking code, called "%s" is already saved automatically, so an automatic lettering is already done, with no risk of error so this feature has become useless for a common usage. Manual lettering feature is provided for end users that really don't trust the computer engine making the transfer of data in accountancy. +EnablingThisFeatureIsNotNecessary=Enabling this feature is no more necessary for a rigourous accounting management. ACCOUNTING_ENABLE_AUTOLETTERING=Enable the automatic lettering when transferring to accounting +ACCOUNTING_ENABLE_AUTOLETTERING_DESC=The code for the lettering is automatically generated and incremented and not choosed by the end user OptionsAdvanced=Advanced options ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE=Activate the management of VAT reverse charge on supplier purchases +ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE_DESC=When this option is enabled, you can define that a supplier or a given vendor invoice must be transfered into accountancy differently: A additionnal debit and a credit line will generated into the accounting on 2 given accounts from the chart of account defined into the "%s" setup page. ## Export NotExportLettering=Do not export the lettering when generating the file @@ -384,7 +388,7 @@ ChartofaccountsId=Chart of accounts Id ## Tools - Init accounting account on product / service InitAccountancy=Init accountancy InitAccountancyDesc=This page can be used to initialize an accounting account on products and services that does not have accounting account defined for sales and purchases. -DefaultBindingDesc=This page can be used to set a default account to use to link transactions record about payment salaries, donation, taxes and vat when no specific accounting account were already set. +DefaultBindingDesc=This page can be used to set the default accounts (from the chart of account) to use to link business objects with an account, like payment salaries, donation, taxes and VAT, when no specific account were already set. DefaultClosureDesc=This page can be used to set parameters used for accounting closures. Options=Options OptionModeProductSell=Mode sales @@ -436,7 +440,7 @@ ConfirmMassUnletteringAuto=Bulk auto unreconcile confirmation ConfirmMassUnletteringManual=Bulk manual unreconcile confirmation ConfirmMassUnletteringQuestion=Are you sure you want to unreconcile the %s selected record(s)? ConfirmMassDeleteBookkeepingWriting=Bulk Delete confirmation -ConfirmMassDeleteBookkeepingWritingQuestion=This will delete the transaction from the accounting (all lines related to the same transaction will be deleted) Are you sure you want to delete the %s selected record(s)? +ConfirmMassDeleteBookkeepingWritingQuestion=This will delete the transaction from the accounting (all line entries related to the same transaction will be deleted). Are you sure you want to delete the %s selected entries? ## Error SomeMandatoryStepsOfSetupWereNotDone=Some mandatory steps of setup was not done, please complete them From 67ca02e1b31fdb781daf67f357b95cb79a4a3e0b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 9 Apr 2023 19:40:00 +0200 Subject: [PATCH 123/417] Removed 2 options from setup than are now set automatically --- htdocs/accountancy/admin/index.php | 62 +-------------------- htdocs/accountancy/customer/lines.php | 12 +++- htdocs/accountancy/customer/list.php | 7 +++ htdocs/accountancy/expensereport/lines.php | 8 +++ htdocs/accountancy/expensereport/list.php | 7 +++ htdocs/accountancy/supplier/lines.php | 8 +++ htdocs/accountancy/supplier/list.php | 7 +++ htdocs/core/lib/functions.lib.php | 2 +- htdocs/core/modules/modAccounting.class.php | 12 ---- 9 files changed, 49 insertions(+), 76 deletions(-) diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 0e9b9dbbd99..174d8fdf13e 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -66,12 +66,7 @@ $error = 0; * Actions */ -if (in_array($action, array( - 'setBANK_DISABLE_DIRECT_INPUT', - 'setACCOUNTANCY_COMBO_FOR_AUX', - 'setACCOUNTING_MANAGE_ZERO', - 'setACCOUNTING_LIST_SORT_VENTILATION_TODO', - 'setACCOUNTING_LIST_SORT_VENTILATION_DONE'))) { +if (in_array($action, array('setBANK_DISABLE_DIRECT_INPUT', 'setACCOUNTANCY_COMBO_FOR_AUX', 'setACCOUNTING_MANAGE_ZERO'))) { $constname = preg_replace('/^set/', '', $action); $constvalue = GETPOST('value', 'int'); $res = dolibarr_set_const($db, $constname, $constvalue, 'yesno', 0, '', $conf->entity); @@ -121,34 +116,6 @@ if ($action == 'update') { } } -if ($action == 'setlistsorttodo') { - $setlistsorttodo = GETPOST('value', 'int'); - $res = dolibarr_set_const($db, "ACCOUNTING_LIST_SORT_VENTILATION_TODO", $setlistsorttodo, 'yesno', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - - if (!$error) { - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } else { - setEventMessages($langs->trans("Error"), null, 'mesgs'); - } -} - -if ($action == 'setlistsortdone') { - $setlistsortdone = GETPOST('value', 'int'); - $res = dolibarr_set_const($db, "ACCOUNTING_LIST_SORT_VENTILATION_DONE", $setlistsortdone, 'yesno', 0, '', $conf->entity); - if (!($res > 0)) { - $error++; - } - - if (!$error) { - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } else { - setEventMessages($langs->trans("Error"), null, 'mesgs'); - } -} - if ($action == 'setmanagezero') { $setmanagezero = GETPOST('value', 'int'); $res = dolibarr_set_const($db, "ACCOUNTING_MANAGE_ZERO", $setmanagezero, 'yesno', 0, '', $conf->entity); @@ -417,33 +384,6 @@ print '
    '.$langs->trans('BindingOptions').'
    '.$langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_TODO").''; - print img_picto($langs->trans("Activated"), 'switch_on'); - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); - print '
    '.$langs->trans("ACCOUNTING_LIST_SORT_VENTILATION_DONE").''; - print img_picto($langs->trans("Activated"), 'switch_on'); - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); - print '
    ' . $line['debit'] . '' . $line['credit'] . '
    '.$langs->trans("NoRecordFound").'
    '; print ''; diff --git a/htdocs/projet/index.php b/htdocs/projet/index.php index 6e39b629347..d78e3c47f0a 100644 --- a/htdocs/projet/index.php +++ b/htdocs/projet/index.php @@ -394,7 +394,7 @@ if ($resql) { if ($othernb) { print '
    '; - print '...'; + print ''.$langs->trans("More").'...'; print ''; print $othernb; From 8b34b3eb186d151409e8ce672adcd5be3e3ca886 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 02:05:26 +0200 Subject: [PATCH 130/417] Debug v18 --- htdocs/accountancy/journal/bankjournal.php | 11 +++++++++++ htdocs/accountancy/journal/expensereportsjournal.php | 11 +++++++++++ htdocs/index.php | 2 +- htdocs/theme/eldy/global.inc.php | 2 +- htdocs/theme/eldy/info-box.inc.php | 3 ++- htdocs/theme/md/info-box.inc.php | 7 ++++--- htdocs/theme/md/style.css.php | 4 +++- 7 files changed, 33 insertions(+), 7 deletions(-) diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 0137e63406f..89f495a97bc 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -1211,6 +1211,8 @@ if (empty($action) || $action == 'view') { print ''.($mt >= 0 ? price($mt) : '')."'.($mt < 0 ? price(-$mt) : '')."
    '.($mt >= 0 ? price($mt) : '')."
    '.($mt < 0 ? price(-$mt) : '')."'.($mt >= 0 ? price($mt) : '')."
    '.$langs->trans("NoRecordFound").'
    "; print ''; diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index ffffc21a9f9..514edeb4528 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -615,6 +615,8 @@ if (empty($action) || $action == 'view') { print ''.($mt >= 0 ? price($mt) : '').""; print ''.($mt < 0 ? price(-$mt) : '').""; print ""; + + $i++; } } @@ -649,6 +651,8 @@ if (empty($action) || $action == 'view') { print ''.($mt < 0 ? price(-$mt) : '').""; print ''.($mt >= 0 ? price($mt) : '').""; print ""; + + $i++; } // VAT @@ -685,11 +689,18 @@ if (empty($action) || $action == 'view') { print ''.($mt >= 0 ? price($mt) : '').""; print ''.($mt < 0 ? price(-$mt) : '').""; print ""; + + $i++; } } } } + if (!$i) { + $colspan = 7; + print ''.$langs->trans("NoRecordFound").''; + } + print ""; print ''; diff --git a/htdocs/index.php b/htdocs/index.php index dd1e36d04f8..8fe8ffa377e 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -537,7 +537,7 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { $openedDashBoard .= '
    '."\n"; foreach ($boards as $board) { - $openedDashBoard .= '
    '; + $openedDashBoard .= '
    '; if (!empty($board->labelShort)) { $infoName = ''.$board->labelShort.''; diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 6c88f652ea8..5bfc8729301 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1317,7 +1317,7 @@ select.flat.selectlimit { } /* using a tdoverflowxxx make the min-width not working */ .tdnooverflowimp { - text-overflow: none; + text-overflow: unset; } .tdoverflow { max-width: 0; diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index db352d4802d..94a26d7257a 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -135,7 +135,8 @@ if (!defined('ISLOADEDBYSTEELSHEET')) { } a.info-box-text.info-box-text-a { - display: table-cell; + /* display: table-cell; */ + display: contents; } a.info-box-text-a i.fa.fa-exclamation-triangle { font-size: 0.9em; diff --git a/htdocs/theme/md/info-box.inc.php b/htdocs/theme/md/info-box.inc.php index 4755225ea4a..8800ce66eba 100644 --- a/htdocs/theme/md/info-box.inc.php +++ b/htdocs/theme/md/info-box.inc.php @@ -136,7 +136,8 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { } a.info-box-text.info-box-text-a { - display: table-cell; + /* display: table-cell; */ + display: contents; } a.info-box-text-a i.fa.fa-exclamation-triangle { font-size: 0.9em; @@ -197,7 +198,7 @@ a.info-box-text-a i.fa.fa-exclamation-triangle { overflow: hidden; float: left; /* height: 90px; */ - width: 90px; + width: 86px; text-align: center; font-size: 45px; line-height: 90px; @@ -334,7 +335,7 @@ a.info-box-text-a i.fa.fa-exclamation-triangle { width: calc(100% - 20px); } .info-box-text{ - font-size: 0.92em; + font-size: 0.90em; } .info-box-text:first-letter{text-transform: uppercase} a.info-box-text{ text-decoration: none;} diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index c5bd85742dd..86ef00e879f 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1553,7 +1553,7 @@ select.flat.selectlimit { } /* using a tdoverflowxxx make the min-width not working */ .tdnooverflowimp { - text-overflow: none; + text-overflow: unset; } .tdoverflow { max-width: 0; @@ -3431,7 +3431,9 @@ a.vsmenu.addbookmarkpicto { } div.blockvmenufirst { padding-top: 10px; + border-top: 1px solid #e0e0e0; + } div.blockvmenusearch, div.blockvmenubookmarks { From 38bbc1d28d630e1fa22e5442904f65f2bdaf08c3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 02:48:44 +0200 Subject: [PATCH 131/417] css --- htdocs/theme/eldy/info-box.inc.php | 6 +++++- htdocs/theme/md/info-box.inc.php | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index 94a26d7257a..113588d897a 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -142,7 +142,11 @@ a.info-box-text-a i.fa.fa-exclamation-triangle { font-size: 0.9em; } -.info-box-icon-text{ +.info-box-line { + line-height: 1.35em; +} + +.info-box-icon-text { box-sizing: border-box; display: block; position: absolute; diff --git a/htdocs/theme/md/info-box.inc.php b/htdocs/theme/md/info-box.inc.php index 8800ce66eba..c685d13146a 100644 --- a/htdocs/theme/md/info-box.inc.php +++ b/htdocs/theme/md/info-box.inc.php @@ -234,7 +234,11 @@ a.info-box-text-a i.fa.fa-exclamation-triangle { max-width: 55%; } -.info-box-icon-text{ +.info-box-line { + line-height: 1.2em; +} + +.info-box-icon-text { box-sizing: border-box; display: block; position: absolute; From df27824249bb8e9d026f487707f9adb02eaf8e49 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 10:58:49 +0200 Subject: [PATCH 132/417] css --- htdocs/expensereport/card.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index b7a6cb662d6..1f7326ed40a 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -2025,6 +2025,7 @@ if ($action == 'create') { print ''; print ''; print ''; + print ''; print '
    '; print ''; @@ -2043,7 +2044,7 @@ if ($action == 'create') { if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) { print ''; } - print ''; + print ''; print ''; print ''; print ''; @@ -2082,7 +2083,7 @@ if ($action == 'create') { // Project if (isModEnabled('project')) { - print ''; } - print ''; + print ''; print ''; print ''; print ''; @@ -2554,7 +2555,7 @@ if ($action == 'create') { } print ''; print ''; From 3f3e8a84ff552c921c2f427b937437efa45a8d90 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 11:23:18 +0200 Subject: [PATCH 133/417] FIX Report of date of task suggested only if there is tasks --- htdocs/projet/card.php | 16 ++++++++++++---- htdocs/projet/class/project.class.php | 6 +++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 7fddc12b7c9..3b5a0175d03 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1153,11 +1153,14 @@ if ($action == 'create' && $user->rights->projet->creer) { print $form->selectDate($object->date_start ? $object->date_start : -1, 'projectstart', 0, 0, 0, '', 1, 0); print ' '.$langs->trans("to").' '; print $form->selectDate($object->date_end ? $object->date_end : -1, 'projectend', 0, 0, 0, '', 1, 0); - print '     getLinesArray(null, 0); + if (!empty($object->usage_task) && !empty($object->lines)) { + print ' '; } - print '/>'; print ''; if (isModEnabled('eventorganization')) { @@ -1379,6 +1382,11 @@ if ($action == 'create' && $user->rights->projet->creer) { jQuery("#usage_task").prop("checked", true); } }); + + jQuery("#projectstart").change(function() { + console.log("We modify the start date"); + jQuery("#divreportdate").show(); + }); }); '; diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 582e062f68a..1e4c6862c58 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -2305,11 +2305,11 @@ class Project extends CommonObject /** - * Create an array of tasks of current project + * Create an array of tasks of current project * - * @param User $user Object user we want project allowed to + * @param User $user Object user we want project allowed to * @param int $loadRoleMode 1= will test Roles on task; 0 used in delete project action - * @return int >0 if OK, <0 if KO + * @return int >0 if OK, <0 if KO */ public function getLinesArray($user, $loadRoleMode = 1) { From eb187052e8badbcc73694cab3d00f7a0d9dd9821 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 11:44:19 +0200 Subject: [PATCH 134/417] Fix column alignment/balance --- htdocs/core/class/html.formprojet.class.php | 2 +- htdocs/projet/tasks/time.php | 67 +++++++++++++++++---- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index e05931f437d..dfbc2aa65a1 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -378,7 +378,7 @@ class FormProjets include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus); $out .= $comboenhancement; - $morecss .= ' minwidth200 maxwidth500'; + $morecss .= ' minwidth150'; } if (empty($option_only)) { diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index b98e9298732..3f1413ea3f2 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -1750,7 +1750,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($projectstatic->public) { $contactsofproject = array(); } - print $form->select_dolusers((GETPOST('userid', 'int') ? GETPOST('userid', 'int') : $userid), 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToProject"), 'maxwidth250'); + print $form->select_dolusers((GETPOST('userid', 'int') ? GETPOST('userid', 'int') : $userid), 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToProject"), 'maxwidth200'); } else { if ($nboftasks) { print img_error($langs->trans('FirstAddRessourceToAllocateTime')).' '.$langs->trans('FirstAddRessourceToAllocateTime'); @@ -1783,8 +1783,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''; if ($conf->service->enabled && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) { - print ''; } } @@ -1796,7 +1797,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''; @@ -2004,7 +2005,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // Thirdparty if (!empty($arrayfields['p.fk_soc']['checked'])) { - print ''; + if (!$i) { + $totalarray['nbfield']++; + } } // Value spent @@ -2270,9 +2274,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''; // Date @@ -2328,6 +2333,18 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''; } + // Thirdparty + if (!empty($arrayfields['p.fk_soc']['checked'])) { + print ''; + } + + // Thirdparty alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + } + // Project ref if (!empty($allprojectforuser)) { if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task @@ -2359,7 +2376,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // User if (!empty($arrayfields['author']['checked'])) { - print ''; } + // Product + if (!empty($arrayfields['t.fk_product']['checked'])) { + print ''; + } + // Value spent if (!empty($arrayfields['value']['checked'])) { print ''; + print ''; // Date if (!empty($arrayfields['t.task_date']['checked'])) { @@ -2466,6 +2489,18 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''; } + // Thirdparty + if (!empty($arrayfields['p.fk_soc']['checked'])) { + print ''; + } + + // Thirdparty alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + } + // Project ref if (!empty($allprojectforuser)) { if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task @@ -2490,14 +2525,14 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if (!empty($arrayfields['t.task_label']['checked'])) { if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task print ''; } } // User if (!empty($arrayfields['author']['checked'])) { - print ''; } + // Product + if (!empty($arrayfields['t.fk_product']['checked'])) { + print ''; + } + // Value spent if (!empty($arrayfields['value']['checked'])) { print ''; From 6143a1336b7c97bab8d49411a5d9591a608ef72b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 12:31:31 +0200 Subject: [PATCH 137/417] Look and feel v17 --- htdocs/admin/stock.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 8aaf76d310b..ac516b00d8e 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -217,7 +217,7 @@ if (isModEnabled('facture')) { print $form->selectarray("STOCK_CALCULATE_ON_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_BILL); } } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module30Name")); + print ''.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module30Name")).''; } print "\n\n"; $found++; @@ -234,7 +234,7 @@ if (isModEnabled('commande')) { print $form->selectarray("STOCK_CALCULATE_ON_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER); } } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module25Name")); + print ''.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module25Name")).''; } print "\n\n"; $found++; @@ -253,7 +253,7 @@ if (isModEnabled("expedition")) { print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT); } } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")); + print ''.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")).''; } print "\n\n"; $found++; @@ -270,7 +270,7 @@ if (isModEnabled("expedition")) { print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT_CLOSE", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE); } } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")); + print ''.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")).''; } print "\n\n"; $found++; @@ -301,7 +301,7 @@ if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMO print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL); } } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); + print ''.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).''; } print "\n\n"; $found++; @@ -319,7 +319,7 @@ if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMO print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER); } } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); + print ''.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).''; } print "\n\n"; $found++; @@ -364,7 +364,7 @@ if (isModEnabled("reception")) { print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER); } } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); + print ''.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).''; } print "\n\n"; $found++; From 9283b7af7497525723f31ed35d36f5a69412a72c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 13:03:09 +0200 Subject: [PATCH 138/417] Fix better setup tooltip for shipment/reception module --- htdocs/admin/stock.php | 17 +++++++++++++---- htdocs/core/class/conf.class.php | 9 +++++---- htdocs/core/modules/modExpedition.class.php | 6 ++++-- htdocs/core/modules/modReception.class.php | 6 ++++-- htdocs/langs/en_US/productbatch.lang | 2 +- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 7a7e49a3129..2cd4985fdb1 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -181,16 +181,25 @@ $formproduct = new FormProduct($db); $disabled = ''; if (isModEnabled('productbatch')) { + // If module lot/serial enabled, we force the inc/dec mode to STOCK_CALCULATE_ON_SHIPMENT_CLOSE and STOCK_CALCULATE_ON_RECEPTION_CLOSE $langs->load("productbatch"); $disabled = ' disabled'; - print info_admin($langs->trans("WhenProductBatchModuleOnOptionAreForced")); + + // STOCK_CALCULATE_ON_SHIPMENT_CLOSE + $descmode = $langs->trans('DeStockOnShipmentOnClosing'); + if (!isModEnabled('reception')) { + // STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER + $incmode = $langs->trans('ReStockOnDispatchOrder'); + } else { + // STOCK_CALCULATE_ON_RECEPTION_CLOSE + $incmode = $langs->trans('StockOnReceptionOnClosing'); + } + print info_admin($langs->trans("WhenProductBatchModuleOnOptionAreForced", $descmode, $incmode)); } -//if (!empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)) -//{ + print info_admin($langs->trans("IfYouUsePointOfSaleCheckModule")); print '
    '; -//} print '
    '; diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 589d28453fc..756b2771e39 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -635,18 +635,19 @@ class Conf unset($this->global->PROJECT_USE_SEARCH_TO_SELECT); } - if (!empty($this->productbatch->enabled)) { + if (isModEnabled('productbatch')) { + // If module lot/serial enabled, we force the inc/dec mode to STOCK_CALCULATE_ON_SHIPMENT_CLOSE and STOCK_CALCULATE_ON_RECEPTION_CLOSE $this->global->STOCK_CALCULATE_ON_BILL = 0; $this->global->STOCK_CALCULATE_ON_VALIDATE_ORDER = 0; - if (empty($this->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) $this->global->STOCK_CALCULATE_ON_SHIPMENT = 1; if (empty($this->global->STOCK_CALCULATE_ON_SHIPMENT)) $this->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE = 1; + if (empty($this->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) $this->global->STOCK_CALCULATE_ON_SHIPMENT = 1; $this->global->STOCK_CALCULATE_ON_SUPPLIER_BILL = 0; $this->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER = 0; - if (empty($this->reception->enabled)) { + if (!isModEnabled('reception')) { $this->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER = 1; } else { - if (empty($this->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) $this->global->STOCK_CALCULATE_ON_RECEPTION = 1; if (empty($this->global->STOCK_CALCULATE_ON_RECEPTION)) $this->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE = 1; + if (empty($this->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) $this->global->STOCK_CALCULATE_ON_RECEPTION = 1; } } diff --git a/htdocs/core/modules/modExpedition.class.php b/htdocs/core/modules/modExpedition.class.php index 2ff117404ee..590e5b6b488 100644 --- a/htdocs/core/modules/modExpedition.class.php +++ b/htdocs/core/modules/modExpedition.class.php @@ -360,9 +360,11 @@ class modExpedition extends DolibarrModules $sql = array( "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[0][2])."' AND type = 'shipping' AND entity = ".((int) $conf->entity), - "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[0][2])."','shipping',".((int) $conf->entity).")", + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[0][2])."', 'shipping', ".((int) $conf->entity).")", "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[3][2])."' AND type = 'delivery' AND entity = ".((int) $conf->entity), - "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[3][2])."','delivery',".((int) $conf->entity).")", + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[3][2])."', 'delivery', ".((int) $conf->entity).")", + //"DELETE FROM ".MAIN_DB_PREFIX."const WHERE name IN ('STOCK_CALCULATE_ON_BILL', 'STOCK_CALCULATE_ON_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_SHIPMENT', 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') AND entity = ".((int) $conf->entity), + //"INSERT INTO ".MAIN_DB_PREFIX."const (name, value, entity) VALUES ('STOCK_CALCULATE_ON_SHIPMENT_CLOSE', 1, ".((int) $conf->entity).")" ); return $this->_init($sql, $options); diff --git a/htdocs/core/modules/modReception.class.php b/htdocs/core/modules/modReception.class.php index 6e7cba2b053..d6341e6279d 100644 --- a/htdocs/core/modules/modReception.class.php +++ b/htdocs/core/modules/modReception.class.php @@ -282,8 +282,10 @@ class modReception extends DolibarrModules $sql = array(); $sql = array( - "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[0][2])."' AND type = 'reception' AND entity = ".((int) $conf->entity), - "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[0][2])."','reception',".((int) $conf->entity).")", + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[0][2])."' AND type = 'reception' AND entity = ".((int) $conf->entity), + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[0][2])."','reception',".((int) $conf->entity).")", + //"DELETE FROM ".MAIN_DB_PREFIX."const WHERE name IN ('STOCK_CALCULATE_ON_SUPPLIER_BILL', 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER', 'STOCK_CALCULATE_ON_RECEPTION', 'STOCK_CALCULATE_ON_RECEPTION_CLOSE') AND entity = ".((int) $conf->entity), + //"INSERT INTO ".MAIN_DB_PREFIX."const (name, value, entity) VALUES ('STOCK_CALCULATE_ON_RECEPTION_CLOSE', 1, ".((int) $conf->entity).")" ); return $this->_init($sql, $options); diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang index a1039e05e62..c51d94b8acd 100644 --- a/htdocs/langs/en_US/productbatch.lang +++ b/htdocs/langs/en_US/productbatch.lang @@ -19,7 +19,7 @@ printSellby=Sell-by: %s printQty=Qty: %d printPlannedWarehouse=Warehouse: %s AddDispatchBatchLine=Add a line for Shelf Life dispatching -WhenProductBatchModuleOnOptionAreForced=When module Lot/Serial is on, automatic stock decrease is forced to 'Decrease real stocks on shipping validation' and automatic increase mode is forced to 'Increase real stocks on manual dispatching into warehouses' and can't be edited. Other options can be defined as you want. +WhenProductBatchModuleOnOptionAreForced=When module Lot/Serial is on, automatic stock decrease is forced to '%s' and automatic increase mode is forced to '%s'. Some choices may be not available. Other options can be defined as you want. ProductDoesNotUseBatchSerial=This product does not use lot/serial number ProductLotSetup=Setup of module lot/serial ShowCurrentStockOfLot=Show current stock for couple product/lot From e058cceecf18b38065ae45a661e98b5fabcb3d61 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 13:26:04 +0200 Subject: [PATCH 139/417] Update pdf.lib.php --- htdocs/core/lib/pdf.lib.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 12d43e2e162..3b893e39256 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -607,6 +607,8 @@ function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $t // Country if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) { $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code)); + } else { + $stringaddress .= ($stringaddress ? "\n" : ''); } if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || preg_match('/targetwithdetails/', $mode)) { From 569320424b1e3570f24509f3030475e412bebb8b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 13:59:19 +0200 Subject: [PATCH 140/417] Fix sql error --- htdocs/expedition/class/expedition.class.php | 8 ++++---- htdocs/expedition/shipment.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 0f7bedc19d3..8a5a84dbb78 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -2209,8 +2209,8 @@ class Expedition extends CommonObject $sql = "SELECT cd.fk_product, cd.subprice,"; $sql .= " ed.rowid, ed.qty, ed.fk_entrepot,"; $sql .= " e.ref,"; - $sql .= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock"; - $sql .= " ,cd.rowid as cdid, ed.rowid as edid"; + $sql .= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock,"; + $sql .= " cd.rowid as cdid, ed.rowid as edid"; $sql .= " FROM " . MAIN_DB_PREFIX . "commandedet as cd,"; $sql .= " " . MAIN_DB_PREFIX . "expeditiondet as ed"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid"; @@ -2264,8 +2264,8 @@ class Expedition extends CommonObject // If some stock lines are now 0, we can remove entry into llx_product_stock, but only if there is no child lines into llx_product_batch (detail of batch, because we can imagine // having a lot1/qty=X and lot2/qty=-X, so 0 but we must not loose repartition of different lot. - $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_stock WHERE reel = 0 AND rowid NOT IN (SELECT fk_product_stock FROM ".MAIN_DB_PREFIX."product_batch as pb)"; - $resql = $this->db->query($sql); + $sqldelete = "DELETE FROM ".MAIN_DB_PREFIX."product_stock WHERE reel = 0 AND rowid NOT IN (SELECT fk_product_stock FROM ".MAIN_DB_PREFIX."product_batch as pb)"; + $resqldelete = $this->db->query($sqldelete); // We do not test error, it can fails if there is child in batch details } } else { diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index 325559882d8..0470da549e5 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -773,7 +773,7 @@ if ($id > 0 || !empty($ref)) { $toBeShippedTotal += $toBeShipped[$objp->fk_product]; print $toBeShipped[$objp->fk_product]; } else { - print '0 ('.$langs->trans("Service").')'; + print '0 ('.$langs->trans("Service").')'; } print ($objp->unit_order ? ' '.$objp->unit_order : '').''; From f26b5b58c907ccdd87ab5ecfa33c6b66947ed6d6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 14:27:39 +0200 Subject: [PATCH 141/417] Fix error management --- htdocs/expedition/card.php | 3 +++ htdocs/expedition/class/expedition.class.php | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index dcc50eff7dc..ec615119c67 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -161,6 +161,9 @@ if (empty($reshook)) { if ($action == 'reopen' && $user->rights->expedition->creer) { $object->fetch($id); $result = $object->reOpen(); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } } // Set incoterm diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 8a5a84dbb78..4eb81a980bb 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -2388,7 +2388,7 @@ class Expedition extends CommonObject // line without batch detail // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record - $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr", $numref)); + $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr", $this->ref)); if ($result < 0) { $this->error = $mouvS->error; $this->errors = $mouvS->errors; @@ -2399,7 +2399,7 @@ class Expedition extends CommonObject // line with batch detail // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record - $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr", $numref), '', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock); + $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr", $this->ref), '', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock); if ($result < 0) { $this->error = $mouvS->error; $this->errors = $mouvS->errors; From f57dfd14c3bff9571d69d381d0d2838820ca3bd8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 15:00:46 +0200 Subject: [PATCH 142/417] Fix label of warehouse no more visible --- htdocs/expedition/card.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index ec615119c67..81620632772 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -352,6 +352,7 @@ if (empty($reshook)) { if ($totalqty > 0 && !$error) { // There is at least one thing to ship and no error for ($i = 0; $i < $num; $i++) { $qty = "qtyl".$i; + if (!isset($batch_line[$i])) { // not batch mode if (isset($stockLine[$i])) { @@ -403,7 +404,7 @@ if (empty($reshook)) { } if (!$error) { - $ret = $object->create($user); // This create shipment (like Odoo picking) and lines of shipments. Stock movement will be done when validating shipment. + $ret = $object->create($user); // This create shipment (like Odoo picking) and lines of shipments. Stock movement will be done when validating or closing shipment. if ($ret <= 0) { setEventMessages($object->error, $object->errors, 'errors'); $error++; @@ -2393,7 +2394,7 @@ if ($action == 'create') { if ($detail_entrepot->entrepot_id > 0) { $entrepot = new Entrepot($db); $entrepot->fetch($detail_entrepot->entrepot_id); - $detail .= $langs->trans("DetailWarehouseFormat", $entrepot->libelle, $detail_entrepot->qty_shipped).'
    '; + $detail .= $langs->trans("DetailWarehouseFormat", $entrepot->label, $detail_entrepot->qty_shipped).'
    '; } } print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"), $detail); From 8ba802ed5d5b34cef9f441a29b6bfa99587d74bb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 15:34:13 +0200 Subject: [PATCH 143/417] Fix when reverting a shipment validation or closing and stock empty --- htdocs/expedition/card.php | 5 +++++ htdocs/langs/en_US/agenda.lang | 2 +- htdocs/langs/en_US/stocks.lang | 2 ++ htdocs/langs/fr_FR/agenda.lang | 2 +- htdocs/product/stock/class/mouvementstock.class.php | 10 ++++++++-- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 81620632772..dfa33478e66 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -1739,6 +1739,11 @@ if ($action == 'create') { } $text = $langs->trans("ConfirmValidateSending", $numref); + if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) { + $text .= ' '.$langs->trans("StockMovementWillBeRecorded").'.'; + } elseif (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) { + $text .= ' '.$langs->trans("StockMovementNotYetRecorded").'.'; + } if (isModEnabled('notification')) { require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index adc9c4177ad..43718271919 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -62,7 +62,7 @@ MemberSubscriptionAddedInDolibarr=Subscription %s for member %s added MemberSubscriptionModifiedInDolibarr=Subscription %s for member %s modified MemberSubscriptionDeletedInDolibarr=Subscription %s for member %s deleted ShipmentValidatedInDolibarr=Shipment %s validated -ShipmentClassifyClosedInDolibarr=Shipment %s classified billed +ShipmentClassifyClosedInDolibarr=Shipment %s classified closed ShipmentUnClassifyCloseddInDolibarr=Shipment %s classified re-open ShipmentBackToDraftInDolibarr=Shipment %s go back to draft status ShipmentDeletedInDolibarr=Shipment %s deleted diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 6a8821de833..62ebfc53ef9 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -318,3 +318,5 @@ StockTransferRightRead=Read stocks transfers StockTransferRightCreateUpdate=Create/Update stocks transfers StockTransferRightDelete=Delete stocks transfers BatchNotFound=Lot / serial not found for this product +StockMovementWillBeRecorded=Stock movement will be recorded +StockMovementNotYetRecorded=Stock movement will not be affected by this step \ No newline at end of file diff --git a/htdocs/langs/fr_FR/agenda.lang b/htdocs/langs/fr_FR/agenda.lang index 86e97805dd5..33d925ac777 100644 --- a/htdocs/langs/fr_FR/agenda.lang +++ b/htdocs/langs/fr_FR/agenda.lang @@ -62,7 +62,7 @@ MemberSubscriptionAddedInDolibarr=Cotisation %s pour l'adhérent %s ajoutée MemberSubscriptionModifiedInDolibarr=Cotisation %s pour l'adhérent %s modifié MemberSubscriptionDeletedInDolibarr=Cotisation %s pour l'adhérent %s supprimé ShipmentValidatedInDolibarr=Expédition %s validée -ShipmentClassifyClosedInDolibarr=Expédition %s classée payée +ShipmentClassifyClosedInDolibarr=Expédition %s classée close ShipmentUnClassifyCloseddInDolibarr=Expédition %s réouverte ShipmentBackToDraftInDolibarr=Expédition %s remise au statut brouillon ShipmentDeletedInDolibarr=Expédition %s supprimée diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 083ea381015..b596ac551b1 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -301,7 +301,9 @@ class MouvementStock extends CommonObject // If not found, we add record $sql = "SELECT pb.rowid, pb.batch, pb.eatby, pb.sellby FROM ".$this->db->prefix()."product_lot as pb"; $sql .= " WHERE pb.fk_product = ".((int) $fk_product)." AND pb.batch = '".$this->db->escape($batch)."'"; + dol_syslog(get_class($this)."::_create scan serial for this product to check if eatby and sellby match", LOG_DEBUG); + $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); @@ -560,6 +562,10 @@ class MouvementStock extends CommonObject if (!$error && isModEnabled('productbatch') && $product->hasbatch() && !$skip_batch) { if ($id_product_batch > 0) { $result = $this->createBatch($id_product_batch, $qty); + if ($result == -2 && $fk_product_stock > 0) { // The entry for this product batch does not exists anymore, bu we already have a llx_product_stock, so we recreate the batch entry in product_batch + $param_batch = array('fk_product_stock' =>$fk_product_stock, 'batchnumber'=>$batch); + $result = $this->createBatch($param_batch, $qty); + } } else { $param_batch = array('fk_product_stock' =>$fk_product_stock, 'batchnumber'=>$batch); $result = $this->createBatch($param_batch, $qty); @@ -863,10 +869,10 @@ class MouvementStock extends CommonObject * Create or update batch record (update table llx_product_batch). No check is done here, done by parent. * * @param array|int $dluo Could be either - * - int if row id of product_batch table + * - int if row id of product_batch table (for update) * - or complete array('fk_product_stock'=>, 'batchnumber'=>) * @param int $qty Quantity of product with batch number. May be a negative amount. - * @return int <0 if KO, else return productbatch id + * @return int <0 if KO, -2 if we try to update a product_batchid that does not exist, else return productbatch id */ private function createBatch($dluo, $qty) { From 90bca8b4d7dd411cda5de4eb6847839fc45774b5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 15:55:58 +0200 Subject: [PATCH 144/417] NEW Can go back to draft on shipment when stock change not on validate --- htdocs/core/class/commonobject.class.php | 2 +- htdocs/core/class/html.form.class.php | 30 ++++++++--------- htdocs/expedition/card.php | 35 ++++++++++++++------ htdocs/expedition/class/expedition.class.php | 19 ++++++++++- 4 files changed, 59 insertions(+), 27 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index e53cc85c21f..10a85c3a16f 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -9982,7 +9982,7 @@ abstract class CommonObject $this->db->begin(); $statusfield = 'status'; - if ($this->element == 'don' || $this->element == 'donation') { + if (in_array($this->element, array('don', 'donation', 'shipping'))) { $statusfield = 'fk_statut'; } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index eea1047bc51..5484fea6663 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5087,21 +5087,21 @@ class Form * print '});'."\n"; * print ''."\n"; * - * @param string $page Url of page to call if confirmation is OK. Can contains parameters (param 'action' and 'confirm' will be reformated) - * @param string $title Title - * @param string $question Question - * @param string $action Action - * @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...')) - * 'type' can be 'text', 'password', 'checkbox', 'radio', 'date', 'datetime', 'select', 'multiselect', 'morecss', - * 'other', 'onecolumn' or 'hidden'... - * @param int|string $selectedchoice '' or 'no', or 'yes' or '1', 1, '0' or 0 - * @param int|string $useajax 0=No, 1=Yes use Ajax to show the popup, 2=Yes and also submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx - * @param int|string $height Force height of box (0 = auto) - * @param int $width Force width of box ('999' or '90%'). Ignored and forced to 90% on smartphones. - * @param int $disableformtag 1=Disable form tag. Can be used if we are already inside a section. - * @param string $labelbuttonyes Label for Yes - * @param string $labelbuttonno Label for No - * @return string HTML ajax code if a confirm ajax popup is required, Pure HTML code if it's an html form + * @param string $page Url of page to call if confirmation is OK. Can contains parameters (param 'action' and 'confirm' will be reformated) + * @param string $title Title + * @param string $question Question + * @param string $action Action + * @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...')) + * 'type' can be 'text', 'password', 'checkbox', 'radio', 'date', 'datetime', 'select', 'multiselect', 'morecss', + * 'other', 'onecolumn' or 'hidden'... + * @param int|string $selectedchoice '' or 'no', or 'yes' or '1', 1, '0' or 0 + * @param int|string $useajax 0=No, 1=Yes use Ajax to show the popup, 2=Yes and also submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx + * @param int|string $height Force height of box (0 = auto) + * @param int $width Force width of box ('999' or '90%'). Ignored and forced to 90% on smartphones. + * @param int $disableformtag 1=Disable form tag. Can be used if we are already inside a section. + * @param string $labelbuttonyes Label for Yes + * @param string $labelbuttonno Label for No + * @return string HTML ajax code if a confirm ajax popup is required, Pure HTML code if it's an html form */ public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No') { diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index dfa33478e66..34ed7f80f84 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -157,6 +157,14 @@ if (empty($reshook)) { $upload_dir = $conf->expedition->dir_output.'/sending'; include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + // Back to draft + if ($action == 'setdraft' && $user->rights->expedition->creer) { + $object->fetch($id); + $result = $object->setDraft($user, 0); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } + } // Reopen if ($action == 'reopen' && $user->rights->expedition->creer) { $object->fetch($id); @@ -1740,9 +1748,9 @@ if ($action == 'create') { $text = $langs->trans("ConfirmValidateSending", $numref); if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) { - $text .= ' '.$langs->trans("StockMovementWillBeRecorded").'.'; + $text .= '
    '.$langs->trans("StockMovementWillBeRecorded").'.'; } elseif (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) { - $text .= ' '.$langs->trans("StockMovementNotYetRecorded").'.'; + $text .= '
    '.$langs->trans("StockMovementNotYetRecorded").'.'; } if (isModEnabled('notification')) { @@ -1752,7 +1760,7 @@ if ($action == 'create') { $text .= $notify->confirmMessage('SHIPPING_VALIDATE', $object->socid, $object); } - $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateSending'), $text, 'confirm_valid', '', 0, 1); + $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateSending'), $text, 'confirm_valid', '', 0, 1, 250); } // Confirm cancelation if ($action == 'cancel') { @@ -2540,13 +2548,20 @@ if ($action == 'create') { } } - // TODO add alternative status - // 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order) - if ($object->statut == Expedition::STATUS_CLOSED && $user->rights->expedition->creer) { - if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ? - print dolGetButtonAction('', $langs->trans('ClassifyUnbilled'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, ''); - } else { - print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, ''); + // 0=draft, 1=validated/delivered, 2=closed/delivered + // If WORKFLOW_BILL_ON_SHIPMENT: 0=draft, 1=validated, 2=billed (no status delivered) + if ($object->statut == Expedition::STATUS_VALIDATED && !getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) { + if ($user->hasRight('expedition', 'creer')) { + print dolGetButtonAction('', $langs->trans('SetToDraft'), 'default', $_SERVER["PHP_SELF"].'?action=setdraft&token='.newToken().'&id='.$object->id, ''); + } + } + if ($object->statut == Expedition::STATUS_CLOSED) { + if ($user->hasRight('expedition', 'creer')) { + if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ? + print dolGetButtonAction('', $langs->trans('ClassifyUnbilled'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, ''); + } else { + print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, ''); + } } } diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 4eb81a980bb..c3ddf973049 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -2318,6 +2318,23 @@ class Expedition extends CommonObject } } + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDraft($user, $notrigger = 0) + { + // Protection + if ($this->statut <= self::STATUS_DRAFT) { + return 0; + } + + return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'SHIPMENT_UNVALIDATE'); + } + /** * Classify the shipping as validated/opened * @@ -2338,7 +2355,7 @@ class Expedition extends CommonObject $oldbilled = $this->billed; - $sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut=1'; + $sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut = 1'; $sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > 0'; $resql = $this->db->query($sql); From 6914e2bb2abaa796e97edfbd86b8dd13ddcc6df6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 16:58:38 +0200 Subject: [PATCH 145/417] NEW Can receive more than qty ordered on reception --- htdocs/fourn/js/lib_dispatch.js.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/htdocs/fourn/js/lib_dispatch.js.php b/htdocs/fourn/js/lib_dispatch.js.php index ff822543ddb..6bd2d39ce21 100644 --- a/htdocs/fourn/js/lib_dispatch.js.php +++ b/htdocs/fourn/js/lib_dispatch.js.php @@ -69,13 +69,15 @@ function addDispatchLine(index, type, mode) { mode = mode || 'qtymissing' - console.log("fourn/js/lib_dispatch.js.php Split line type="+type+" index="+index+" mode="+mode); var $row0 = $("tr[name='"+type+'_0_'+index+"']"); var $dpopt = $row0.find('.hasDatepicker').first().datepicker('option', 'all'); // get current datepicker options to apply the same to the cloned datepickers var $row = $row0.clone(true); // clone first batch line to jQuery object var nbrTrs = $("tr[name^='"+type+"_'][name$='_"+index+"']").length; // position of line for batch var qtyOrdered = parseFloat($("#qty_ordered_0_"+index).val()); // Qty ordered is same for all rows var qty = parseFloat($("#qty_"+(nbrTrs - 1)+"_"+index).val()); + + console.log("fourn/js/lib_dispatch.js.php Split line type="+type+" index="+index+" mode="+mode+" qtyOrdered="+qtyOrdered+" qty="+qty); + var qtyDispatched; if (mode === 'lessone') @@ -93,9 +95,17 @@ function addDispatchLine(index, type, mode) } console.log("qtyDispatched="+qtyDispatched+" qtyOrdered="+qtyOrdered); - if (qtyDispatched >= qtyOrdered || qtyOrdered <= 1) { + if (qty <= 1) { window.alert("Remain quantity to dispatch is too low to be split"); - } else if (qtyDispatched < qtyOrdered) { + } else { + oldlineqty = qtyDispatched; + newlineqty = qtyOrdered - qtyDispatched; + if (newlineqty <= 0) { + newlineqty = qty - 1; + oldlineqty = 1; + $("#qty_"+(nbrTrs - 1)+"_"+index).val(oldlineqty); + } + //replace tr suffix nbr $row.html($row.html().replace(/_0_/g,"_"+nbrTrs+"_")); @@ -127,7 +137,7 @@ function addDispatchLine(index, type, mode) /* Suffix of lines are: _ trs.length _ index */ $("#qty_"+nbrTrs+"_"+index).focus(); - $("#qty_dispatched_0_"+index).val(qtyDispatched); + $("#qty_dispatched_0_"+index).val(oldlineqty); //hide all buttons then show only the last one $("tr[name^='"+type+"_'][name$='_"+index+"'] .splitbutton").hide(); @@ -138,7 +148,7 @@ function addDispatchLine(index, type, mode) qty = 1; // keep 1 in old line $("#qty_"+(nbrTrs-1)+"_"+index).val(qty); } - $("#qty_"+nbrTrs+"_"+index).val(qtyOrdered - qtyDispatched); + $("#qty_"+nbrTrs+"_"+index).val(newlineqty); // Store arbitrary data for dispatch qty input field change event $("#qty_"+(nbrTrs-1)+"_"+index).data('qty', qty); $("#qty_"+(nbrTrs-1)+"_"+index).data('type', type); From 3e372602d884a31848866a2d4ddc68132cfe8f2f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 17:07:20 +0200 Subject: [PATCH 146/417] Trans --- htdocs/core/modules/modStockTransfer.class.php | 2 +- htdocs/langs/en_US/admin.lang | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/modStockTransfer.class.php b/htdocs/core/modules/modStockTransfer.class.php index 279add98bad..34de040fdb8 100644 --- a/htdocs/core/modules/modStockTransfer.class.php +++ b/htdocs/core/modules/modStockTransfer.class.php @@ -61,7 +61,7 @@ class modStockTransfer extends DolibarrModules // Module description, used if translation string 'ModuleStockTransferDesc' not found (StockTransfer is name of module). $this->description = $langs->trans("ModuleStockTransferDesc"); // Used only if file README.md and README-LL.md not found. - $this->descriptionlong = "StockTransfer description (Long)"; + $this->descriptionlong = "Advanced management of stock transfer orders with generation of stock transfer sheets"; // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' $this->version = 'experimental'; // Url to the file with your last numberversion of this module diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 9fb7a487118..a493b104036 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -573,7 +573,7 @@ Module50Desc=Management of Products Module51Name=Mass mailings Module51Desc=Mass paper mailing management Module52Name=Stocks -Module52Desc=Stock management +Module52Desc=Stock management (stock movement tracking and inventory) Module53Name=Services Module53Desc=Management of Services Module54Name=Contracts/Subscriptions From 18b78d28abfcdb47c0071ddcfd7f5698dd70fcdf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 18:56:33 +0200 Subject: [PATCH 147/417] Clean content of column "Already shipped into other shipment" --- htdocs/expedition/card.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 34ed7f80f84..f2947e9b09f 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -2285,6 +2285,8 @@ if ($action == 'create') { // Qty in other shipments (with shipment and warehouse used) if ($origin && $origin_id > 0) { print '
    '; } From 5184f7c168ff892b4a02356ce90f8a9d89aad8da Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 19:13:41 +0200 Subject: [PATCH 148/417] css --- htdocs/core/tpl/objectline_title.tpl.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/tpl/objectline_title.tpl.php b/htdocs/core/tpl/objectline_title.tpl.php index cbe5d0dee10..f7afa80bf55 100644 --- a/htdocs/core/tpl/objectline_title.tpl.php +++ b/htdocs/core/tpl/objectline_title.tpl.php @@ -134,14 +134,14 @@ if (isset($this->situation_cycle_ref) && $this->situation_cycle_ref) { if ($usemargins && isModEnabled('margin') && empty($user->socid)) { if (!empty($user->rights->margins->creer)) { if ($conf->global->MARGIN_TYPE == "1") { - print ''; + print ''; } else { - print ''; + print ''; } } if (!empty($conf->global->DISPLAY_MARGIN_RATES) && $user->rights->margins->liretous) { - print ''; } if (!empty($conf->global->DISPLAY_MARK_RATES) && $user->rights->margins->liretous) { - print ''; + print ''; } } From 8747cc142349f28dcb94fb22a02535ac4fb5f9be Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 19:17:37 +0200 Subject: [PATCH 149/417] Fix phpunit --- htdocs/product/reassortlot.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index 4346854460a..a25fadede1d 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -532,7 +532,6 @@ print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sort /* if ($search_categ > 0) { - var_dump($search_categ); print "
    "; $c = new Categorie($db); $c->fetch($search_categ); From 6d18cdb062ffc86ec30c9ec5f44876ea26886ace Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 19:22:38 +0200 Subject: [PATCH 150/417] First test with PHP 8.2 --- .travis.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1f4fc328a49..ee378d191dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,6 +53,10 @@ addons: - php8.1-mysqli - php8.1-xml - php8.1-intl + - php8.2-pgsql + - php8.2-mysqli + - php8.2-xml + - php8.2-intl env: global: @@ -73,8 +77,8 @@ jobs: php: '8.1' env: DB=mysql - stage: PHP Dev - if: type = push AND branch = 17.0 - php: nightly + if: type = push AND branch = develop + php: '8.2' env: DB=mysql notifications: @@ -120,7 +124,7 @@ install: squizlabs/php_codesniffer ^3 fi # phpunit 9 is required for php 8 - if [ "$TRAVIS_PHP_VERSION" = '8.0' ] || [ "$TRAVIS_PHP_VERSION" = '8.1' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then + if [ "$TRAVIS_PHP_VERSION" = '8.0' ] || [ "$TRAVIS_PHP_VERSION" = '8.1' ] || [ "$TRAVIS_PHP_VERSION" = '8.2' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then composer self-update 2.4.4 composer -n require --ignore-platform-reqs phpunit/phpunit ^8 \ php-parallel-lint/php-parallel-lint ^1.2 \ @@ -260,7 +264,7 @@ before_script: # enable php-fpm - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf - | - if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ] || [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = '8.0' ] || [ "$TRAVIS_PHP_VERSION" = '8.1' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then + if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ] || [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = '8.0' ] || [ "$TRAVIS_PHP_VERSION" = '8.1' ] || [ "$TRAVIS_PHP_VERSION" = '8.2' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then # Copy the included pool sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf fi From 1964a020aa3696a991a53af6921ff1f2e8945b21 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 19:35:58 +0200 Subject: [PATCH 151/417] Look and feel v18 --- htdocs/product/stock/movement_list.php | 413 +++++++++++++++---------- 1 file changed, 257 insertions(+), 156 deletions(-) diff --git a/htdocs/product/stock/movement_list.php b/htdocs/product/stock/movement_list.php index 56d39ae0e88..72f36220185 100644 --- a/htdocs/product/stock/movement_list.php +++ b/htdocs/product/stock/movement_list.php @@ -50,20 +50,23 @@ if (isModEnabled('productbatch')) { $langs->load("productbatch"); } -$id = GETPOST('id', 'int'); -$ref = GETPOST('ref', 'alpha'); -$msid = GETPOST('msid', 'int'); -$product_id = GETPOST("product_id", 'int'); $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation $cancel = GETPOST('cancel', 'alpha'); -$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'movementlist'; +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list $backtopage = GETPOST("backtopage", "alpha"); +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') +$mode = GETPOST('mode', 'aZ'); // The output mode ('list', 'kanban', 'hierarchy', 'calendar', ...) +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$msid = GETPOST('msid', 'int'); $idproduct = GETPOST('idproduct', 'int'); -$sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); +$product_id = GETPOST("product_id", 'int'); + +$search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $search_date_startday = GETPOST('search_date_startday', 'int'); $search_date_startmonth = GETPOST('search_date_startmonth', 'int'); $search_date_startyear = GETPOST('search_date_startyear', 'int'); @@ -83,7 +86,7 @@ $search_batch = trim(GETPOST("search_batch")); $search_qty = trim(GETPOST("search_qty")); $search_type_mouvement = GETPOST('search_type_mouvement', 'int'); $search_fk_projet=GETPOST("search_fk_projet", 'int'); -$optioncss = GETPOST('optioncss', 'alpha'); + $type = GETPOST("type", "int"); // Load variable for pagination @@ -108,15 +111,15 @@ if (!$sortorder) { $pdluoid = GETPOST('pdluoid', 'int'); -// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +// Initialize technical objects $object = new MouvementStock($db); $extrafields = new ExtraFields($db); $diroutputmassaction = $conf->stock->dir_output.'/temp/massgeneration/'.$user->id; -$hookmanager->initHooks(array('movementlist')); +$hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array of activated contexes $formfile = new FormFile($db); -// fetch optionals attributes and labels +// Fetch optionals attributes and labels $extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); @@ -224,7 +227,7 @@ if (empty($reshook)) { $search_batch = ""; $search_qty = ''; $search_fk_projet=0; - $sall = ""; + $search_all = ""; $toselect = array(); $search_array_options = array(); } @@ -588,18 +591,21 @@ if ($action == "transfert_stock" && !$cancel) { * View */ -$productlot = new ProductLot($db); -$productstatic = new Product($db); -$warehousestatic = new Entrepot($db); -$movement = new MouvementStock($db); -$userstatic = new User($db); $form = new Form($db); $formproduct = new FormProduct($db); if (!empty($conf->project->enabled)) { $formproject = new FormProjets($db); } +$productlot = new ProductLot($db); +$productstatic = new Product($db); +$warehousestatic = new Entrepot($db); +$movement = new MouvementStock($db); +$userstatic = new User($db); + +$now = dol_now(); // Build and execute select +// -------------------------------------------------------------------- $sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tosell, p.tobuy, p.tobatch, p.fk_product_type as type, p.entity,"; $sql .= " e.ref as warehouse_ref, e.rowid as entrepot_id, e.lieu, e.fk_parent, e.statut,"; $sql .= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,"; @@ -616,7 +622,7 @@ if (!empty($extrafields->attributes[$object->table_element]['label'])) { } // Add fields from hooks $parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook +$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); @@ -697,7 +703,7 @@ if ($search_type_mouvement != '' && $search_type_mouvement != '-1') { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; // Add where from hooks $parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; // Count total nb of records @@ -714,7 +720,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { dol_print_error($db); } - if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } @@ -733,6 +739,9 @@ if (!$resql) { exit; } +$num = $db->num_rows($resql); + + $product = new Product($db); $object = new Entrepot($db); @@ -746,8 +755,6 @@ if ($id > 0 || $ref) { } } -$num = $db->num_rows($resql); - // Output page // -------------------------------------------------------------------- @@ -767,9 +774,11 @@ if ($msid) { } } -llxHeader('', $title, $help_url); -$arrayofselected = is_array($toselect) ? $toselect : array(); +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title, $help_url); /* * Show tab only if we ask a particular warehouse @@ -939,7 +948,12 @@ if ((empty($action) || $action == 'list') && $id > 0) { print '

    '; } +$arrayofselected = is_array($toselect) ? $toselect : array(); + $param = ''; +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -996,6 +1010,10 @@ if ($idproduct > 0) { } // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; +// Add $param from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$param .= $hookmanager->resPrint; // List of mass actions available $arrayofmassactions = array(); @@ -1023,10 +1041,15 @@ print ''; print ''; print ''; print ''; +print ''; +print ''; if ($id > 0) { print ''; } + +$newcardbutton = ''; + if ($id > 0) { print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1); } else { @@ -1040,17 +1063,20 @@ $objecttmp = new MouvementStock($db); $trackid = 'mov'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; -if ($sall) { +if ($search_all) { + $setupstring = ''; foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); + $setupstring .= $key."=".$val.";"; } - print '
    '.$langs->trans("FilterOnInto", $sall).join(', ', $fieldstosearchall).'
    '; + print ''."\n"; + print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } $moreforfilter = ''; $parameters = array('arrayfields'=>&$arrayfields); -$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $moreforfilter .= $hookmanager->resPrint; } else { @@ -1064,7 +1090,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); print '
    '; // You can use div-table-responsive-no-min if you dont need reserved height for your table @@ -1073,6 +1099,13 @@ print '
    '.$langs->trans('CarCategory').''.$langs->trans('Description').''.$langs->trans('Description').''.$langs->trans('VAT').''.$langs->trans('PriceUHT').''.$langs->trans('PriceUTTC').''; + print ''; if ($line->fk_project > 0) { $projecttmp->id = $line->fk_project; $projecttmp->ref = $line->projet_ref; @@ -2475,7 +2476,7 @@ if ($action == 'create') { if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) { print ''.$langs->trans('CarCategory').''.$langs->trans('Description').''.$langs->trans('Description').''.$langs->trans('VAT').''.$langs->trans('PriceUHT').''.$langs->trans('PriceUTTC').''; - print $form->buttonsSaveCancel("Add", '', '', 1); + print $form->buttonsSaveCancel("Add", '', '', 1, 'reposition'); print '
    '; - print $form->select_produits('', 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); + print ''; + print img_picto('', 'product'); + print $form->select_produits('', 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth150', 0, '', null, 1); print ''; $form->buttonsSaveCancel(); - print ''; + print ''; print ''; print '
    '; + print ''; if ($task_time->fk_soc > 0) { if (empty($conf->cache['thridparty'][$task_time->fk_soc])) { $tmpsociete = new Societe($db); @@ -2185,9 +2186,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } } - //Product + // Product if (!empty($arrayfields['t.fk_product']['checked'])) { - print ''; + print ''; if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) { $form->select_produits($task_time->fk_product, 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); } elseif (!empty($task_time->fk_product)) { @@ -2200,6 +2201,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } } print ''; if (($action == 'editline' || $action == 'splitline') && GETPOST('lineid', 'int') == $task_time->rowid) { print ''; - print ''; + print ''; print ' '; - print ''; + print ''; } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) { if (getDolGlobalString('MAIN_FEATURES_LEVEL') >= 2) { @@ -2311,6 +2315,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // Add line to split if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) { + print ''; print '
    '; + print ''; + print ''; + print ''; if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) { if (empty($object->id)) { $object->fetch($id); @@ -2410,6 +2427,12 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''; + print ''; @@ -2449,7 +2472,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser // Line for second dispatching - print '
    '; + print ''; + print ''; - print $task_time->label; + print dol_escape_htmltag($task_time->label); print ''; + print ''; if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) { if (empty($object->id)) { $object->fetch($id); @@ -2548,6 +2583,12 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser print ''; + print ''; From ecb2492675bbeaf5846fb9074b47790a55990b2f Mon Sep 17 00:00:00 2001 From: Erik van Berkum Date: Mon, 10 Apr 2023 18:59:24 +0900 Subject: [PATCH 135/417] fix: Format thirdparty address label on pdf. Currently, an extra blank line is displayed between city/state and before country --- htdocs/core/lib/pdf.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 03e816a63f9..12d43e2e162 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -603,7 +603,7 @@ function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $t } } else { if (is_object($targetcompany)) { - $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany))."\n"; + $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany)); // Country if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) { $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code)); From 89f69068515f04d023b2e86226e5d026ee710534 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 12:09:52 +0200 Subject: [PATCH 136/417] Trans --- htdocs/langs/en_US/commercial.lang | 4 ++-- htdocs/projet/card.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/langs/en_US/commercial.lang b/htdocs/langs/en_US/commercial.lang index eba95a8aabb..a2f5c6d21ce 100644 --- a/htdocs/langs/en_US/commercial.lang +++ b/htdocs/langs/en_US/commercial.lang @@ -65,8 +65,8 @@ ActionAC_SUP_ORD=Send purchase order by mail ActionAC_SUP_INV=Send vendor invoice by mail ActionAC_OTH=Other ActionAC_OTH_AUTO=Other auto -ActionAC_MANUAL=Manually inserted events -ActionAC_AUTO=Automatically inserted events +ActionAC_MANUAL=Events inserted manually (by a user) +ActionAC_AUTO=Events inserted automatically ActionAC_OTH_AUTOShort=Other ActionAC_EVENTORGANIZATION=Event organization events Stats=Sales statistics diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 3b5a0175d03..040b3ea2772 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1157,9 +1157,9 @@ if ($action == 'create' && $user->rights->projet->creer) { if (!empty($object->usage_task) && !empty($object->lines)) { print ' '; + print '/>'; } print '
    '; + $htmltooltip = ''; + $qtyalreadysent = 0; foreach ($alreadysent as $key => $val) { if ($lines[$i]->fk_origin_line == $key) { $j = 0; @@ -2295,20 +2297,23 @@ if ($action == 'create') { $j++; if ($j > 1) { - print '
    '; + $htmltooltip .= '
    '; } $shipment_static->fetch($shipmentline_var['shipment_id']); - print $shipment_static->getNomUrl(1); - print ' - '.$shipmentline_var['qty_shipped']; - $htmltext = $langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($shipmentline_var['date_valid'], 'dayhour')); - if (isModEnabled('stock') && $shipmentline_var['warehouse'] > 0) { + $htmltooltip .= $shipment_static->getNomUrl(1, '', 0, 0, 1); + $htmltooltip .= ' - '.$shipmentline_var['qty_shipped']; + $htmltooltip .= ' - '.$langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($shipmentline_var['date_valid'], 'dayhour')); + /*if (isModEnabled('stock') && $shipmentline_var['warehouse'] > 0) { $warehousestatic->fetch($shipmentline_var['warehouse']); $htmltext .= '
    '.$langs->trans("FromLocation").' : '.$warehousestatic->getNomUrl(1, '', 0, 1); - } - print ' '.$form->textwithpicto('', $htmltext, 1); + }*/ + //print ' '.$form->textwithpicto('', $htmltext, 1); + + $qtyalreadysent += $shipmentline_var['qty_shipped']; } } } + print $form->textwithpicto($qtyalreadysent, $htmltooltip, 1, 'info', '', 0, 3, 'tooltip'.$lines[$i]->id); print '
    '.$langs->trans('BuyingPrice').''.$langs->trans('BuyingPrice').''.$langs->trans('CostPrice').''.$langs->trans('CostPrice').''.$langs->trans('MarginRate'); + print ''.$langs->trans('MarginRate'); if ($user->hasRight("propal", "creer")) { print 'id.'">'.img_edit($langs->trans("UpdateForAllLines"), 0, 'class="clickmarginforalllines opacitymedium paddingleft cursorpointer"').''; if (GETPOST('mode', 'aZ09') == 'marginforalllines') { @@ -154,7 +154,7 @@ if ($usemargins && isModEnabled('margin') && empty($user->socid)) { print ''.$langs->trans('MarkRate').''.$langs->trans('MarkRate').'
    '; +// Action column +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; +} if (!empty($arrayfields['m.rowid']['checked'])) { // Ref print ''; } // Action column -print ''; +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; +} print ''."\n"; +$totalarray = array(); +$totalarray['nbfield'] = 0; // Fields title label // -------------------------------------------------------------------- print ''; +// Action column +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; + $totalarray['nbfield']++; +} if (!empty($arrayfields['m.rowid']['checked'])) { print_liste_field_titre($arrayfields['m.rowid']['label'], $_SERVER["PHP_SELF"], 'm.rowid', '', $param, '', $sortfield, $sortorder); } @@ -1262,8 +1304,8 @@ if (!empty($arrayfields['m.price']['checked'])) { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; // Hook fields -$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); -$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; if (!empty($arrayfields['m.datec']['checked'])) { print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap '); @@ -1272,7 +1314,10 @@ if (!empty($arrayfields['m.tms']['checked'])) { print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap '); } // Action column -print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; + $totalarray['nbfield']++; +} print ''."\n"; @@ -1282,9 +1327,11 @@ $arrayofuniqueproduct = array(); // Loop on record // -------------------------------------------------------------------- $i = 0; +$savnbfield = $totalarray['nbfield']; $totalarray = array(); $totalarray['nbfield'] = 0; -while ($i < ($limit ? min($num, $limit) : $num)) { +$imaxinloop = ($limit ? min($num, $limit) : $num); +while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); if (empty($obj)) { break; // Should not happen @@ -1346,139 +1393,193 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $origin = ''; } - print ''; - // Id movement - if (!empty($arrayfields['m.rowid']['checked'])) { - print ''; // This is primary not movement id - } - if (!empty($arrayfields['m.datem']['checked'])) { - // Date - print ''; - } - if (!empty($arrayfields['p.ref']['checked'])) { - // Product ref - print '\n"; - } - if (!empty($arrayfields['p.label']['checked'])) { - // Product label - print '\n"; - } - if (!empty($arrayfields['m.batch']['checked'])) { - print ''; - } - if (!empty($arrayfields['pl.eatby']['checked'])) { - print ''; - } - if (!empty($arrayfields['pl.sellby']['checked'])) { - print ''; - } - // Warehouse - if (!empty($arrayfields['e.ref']['checked'])) { - print '\n"; - } - // Author - if (!empty($arrayfields['m.fk_user_author']['checked'])) { - print '\n"; - } - if (!empty($arrayfields['m.inventorycode']['checked'])) { - // Inventory code - print ''; - } - if (!empty($arrayfields['m.label']['checked'])) { - // Label of movement - print ''; - } - if (!empty($arrayfields['origin']['checked'])) { - // Origin of movement - print ''; - } - if (!empty($arrayfields['m.fk_projet']['checked'])) { - // fk_project - print ''; - } - if (!empty($arrayfields['m.type_mouvement']['checked'])) { - // Type of movement - print ''; - } - if (!empty($arrayfields['m.value']['checked'])) { - // Qty - print ''; } - print ''; - } - if (!empty($arrayfields['m.price']['checked'])) { - // Price - print ''; + // Action column + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Id movement + if (!empty($arrayfields['m.rowid']['checked'])) { + print ''; // This is primary not movement id + } + if (!empty($arrayfields['m.datem']['checked'])) { + // Date + print ''; + } + if (!empty($arrayfields['p.ref']['checked'])) { + // Product ref + print '\n"; + } + if (!empty($arrayfields['p.label']['checked'])) { + // Product label + print '\n"; + } + if (!empty($arrayfields['m.batch']['checked'])) { + print ''; + } + if (!empty($arrayfields['pl.eatby']['checked'])) { + print ''; + } + if (!empty($arrayfields['pl.sellby']['checked'])) { + print ''; + } + // Warehouse + if (!empty($arrayfields['e.ref']['checked'])) { + print '\n"; + } + // Author + if (!empty($arrayfields['m.fk_user_author']['checked'])) { + print '\n"; + } + if (!empty($arrayfields['m.inventorycode']['checked'])) { + // Inventory code + print ''; + } + if (!empty($arrayfields['m.label']['checked'])) { + // Label of movement + print ''; + } + if (!empty($arrayfields['origin']['checked'])) { + // Origin of movement + print ''; + } + if (!empty($arrayfields['m.fk_projet']['checked'])) { + // fk_project + print ''; + } + if (!empty($arrayfields['m.type_mouvement']['checked'])) { + // Type of movement + print ''; + } + if (!empty($arrayfields['m.value']['checked'])) { + // Qty + print ''; + } + if (!empty($arrayfields['m.price']['checked'])) { + // Price + print ''; } - print ''; - } - // Extra fields - $object = $movement; - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; + // Extra fields + $object = $movement; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; - // Action column - print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - print ''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - print ''."\n"; + print ''."\n"; + } $i++; } +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} + $db->free($resql); -print "
    '; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; @@ -1185,7 +1218,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; // Fields from hook $parameters = array('arrayfields'=>$arrayfields); -$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Date creation if (!empty($arrayfields['m.datec']['checked'])) { @@ -1198,16 +1231,25 @@ if (!empty($arrayfields['m.tms']['checked'])) { print ''; -$searchpicto = $form->showFilterButtons(); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
    '; - print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"'); - print $obj->mid; - print ''.dol_print_date($db->jdate($obj->datem), 'dayhour', 'tzuserrel').''; - print $productstatic->getNomUrl(1, 'stock', 16); - print "'; - print $productstatic->label; - print "'; - if ($productlot->id > 0) { - print $productlot->getNomUrl(1); - } 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. + if ($mode == 'kanban') { + if ($i == 0) { + print '
    '; + print '
    '; } - print '
    '.dol_print_date($obj->eatby, 'day').''.dol_print_date($obj->sellby, 'day').''; - print $warehousestatic->getNomUrl(1); - print "'; - print $userstatic->getNomUrl(-1); - print "inventorycode.'$').'&search_type_mouvement='.urlencode($obj->type_mouvement).'">'.$obj->inventorycode.''.$obj->label.''.$origin.''; - if ($obj->fk_project != 0) { - print $movement->get_origin($obj->fk_project, 'project'); + // Output Kanban + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($object->id, $arrayofselected)) { + $selected = 1; + } } - print ''; - print $movement->getTypeMovement(); - print ''; - if ($obj->qty > 0) { - print ''; - print '+'; - print $obj->qty; - print ''; - } else { - print ''; - print $obj->qty; - print ''; + print $object->getKanbanView(''); + if ($i == ($imaxinloop - 1)) { + print ''; + print '
    '; - if ($obj->price != 0) { - print price($obj->price); + } else { + // Show here line of result + $j = 0; + print '
    '; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->mid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"'); + print $obj->mid; + print ''.dol_print_date($db->jdate($obj->datem), 'dayhour', 'tzuserrel').''; + print $productstatic->getNomUrl(1, 'stock', 16); + print "'; + print $productstatic->label; + print "'; + if ($productlot->id > 0) { + print $productlot->getNomUrl(1); + } 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_print_date($obj->eatby, 'day').''.dol_print_date($obj->sellby, 'day').''; + print $warehousestatic->getNomUrl(1); + print "'; + print $userstatic->getNomUrl(-1); + print "inventorycode.'$').'&search_type_mouvement='.urlencode($obj->type_mouvement).'">'.$obj->inventorycode.''.$obj->label.''.$origin.''; + if ($obj->fk_project != 0) { + print $movement->get_origin($obj->fk_project, 'project'); + } + print ''; + print $movement->getTypeMovement(); + print ''; + if ($obj->qty > 0) { + print ''; + print '+'; + print $obj->qty; + print ''; + } else { + print ''; + print $obj->qty; + print ''; + } + print ''; + if ($obj->price != 0) { + print price($obj->price); + } + print ''; - if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->mid, $arrayofselected)) { - $selected = 1; + // Action column + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->mid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
    '.$langs->trans("NoRecordFound").'
    "; -print '
    '; -print ""; +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print ''."\n"; +print '
    '."\n"; + +print ''."\n"; // Add number of product when there is a filter on period if (count($arrayofuniqueproduct) == 1 && !empty($year) && is_numeric($year)) { @@ -1527,7 +1628,7 @@ if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $n $genallowed = $permissiontoread; $delallowed = $permissiontoadd; - print $formfile->showdocuments('massfilesarea_mymodule', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); + print $formfile->showdocuments('massfilesarea_'.$object->module, '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); } // End of page From 84a81fde360cc83608b59c18bdc0791cd29ed88e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 10 Apr 2023 19:39:56 +0200 Subject: [PATCH 152/417] Debug v18 --- htdocs/product/reassortlot.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index a25fadede1d..8c655df44ff 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -38,7 +38,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; // Load translation files required by the page -$langs->loadLangs(array('products', 'stocks', 'productbatch')); +$langs->loadLangs(array('products', 'stocks', 'productbatch', 'categories')); $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) @@ -545,7 +545,7 @@ if ($search_categ > 0) { $moreforfilter = ''; if (isModEnabled('categorie')) { $moreforfilter .= '
    '; - $moreforfilter .= img_picto($langs->trans('ProductsCategoryShort'), 'category', 'class="pictofixedwidth"'); + $moreforfilter .= img_picto($langs->trans('ProductsCategoriesShort'), 'category', 'class="pictofixedwidth"'); $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1, $langs->trans("ProductsCategoryShort"), 'maxwidth400'); $moreforfilter .= '
    '; } From 7fc2b2e8b1f252d2ec624d1cb2e7828ac324e57d Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 10 Apr 2023 22:30:16 +0200 Subject: [PATCH 153/417] Fix error on call function print_liste_field_titre --- htdocs/societe/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 3362755d962..007d4f232cc 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -1510,7 +1510,7 @@ if (!empty($arrayfields['s.import_key']['checked'])) { } // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print_liste_field_titre(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch actioncolumn '); + print_liste_field_titre(($mode != 'kanban' ? $selectedfields : ''), $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch actioncolumn '); $totalarray['nbfield']++; // For the column action } print ''."\n"; From 0f58368d5d8215387e28bc8d6456baa47a6da8b5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 10:13:15 +0200 Subject: [PATCH 154/417] Fix do imap expunge only if no error --- htdocs/emailcollector/class/emailcollector.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 7da3da4e83a..1b7c7ef2f27 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2888,7 +2888,7 @@ class EmailCollector extends CommonObject if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { $client->disconnect(); } else { - if (empty($mode)) { + if (empty($mode) && empty($error)) { imap_expunge($connection); // To validate any move } imap_close($connection); From a1e6fe7f5050500ab580ac969b2d27cba9adcfef Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 10:34:03 +0200 Subject: [PATCH 155/417] Revert "Try fix MS OAuth2 Imap (from feedback at dolibarr.org/forum/t/emailcollectors-with-microsoft-365-oauth2)" This reverts commit 976c2d76f260d73cd5508fe837e487675228d156. --- htdocs/core/lib/oauth.lib.php | 2 +- htdocs/includes/OAuth/OAuth2/Service/Microsoft.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/oauth.lib.php b/htdocs/core/lib/oauth.lib.php index aaac40a525f..8a81d9a80e5 100644 --- a/htdocs/core/lib/oauth.lib.php +++ b/htdocs/core/lib/oauth.lib.php @@ -32,7 +32,7 @@ if (isModEnabled('stripe')) { $supportedoauth2array['OAUTH_STRIPE_LIVE_NAME'] = array('callbackfile' => 'stripelive', 'picto' => 'stripe', 'urlforapp' => '', 'name'=>'StripeLive', 'urlforcredentials'=>'', 'availablescopes'=>'read_write', 'returnurl'=>'/core/modules/oauth/stripelive_oauthcallback.php'); } $supportedoauth2array['OAUTH_GITHUB_NAME'] = array('callbackfile' => 'github', 'picto' => 'github', 'urlforapp' => 'OAUTH_GITHUB_DESC', 'name'=>'GitHub', 'urlforcredentials'=>'https://github.com/settings/developers', 'availablescopes'=>'user,public_repo', 'returnurl'=>'/core/modules/oauth/github_oauthcallback.php'); -$supportedoauth2array['OAUTH_MICROSOFT_NAME'] = array('callbackfile' => 'microsoft', 'picto' => 'microsoft', 'urlforapp' => 'OAUTH_MICROSOFT_DESC', 'name'=>'Microsoft', 'urlforcredentials'=>'https://portal.azure.com/', 'availablescopes'=>'openid,offline_access,profile,email,User.Read,https://outlook.office.com/IMAP.AccessAsUser.All,https://outlook.office.com/SMTP.Send', 'returnurl'=>'/core/modules/oauth/microsoft_oauthcallback.php'); +$supportedoauth2array['OAUTH_MICROSOFT_NAME'] = array('callbackfile' => 'microsoft', 'picto' => 'microsoft', 'urlforapp' => 'OAUTH_MICROSOFT_DESC', 'name'=>'Microsoft', 'urlforcredentials'=>'https://portal.azure.com/', 'availablescopes'=>'openid,offline_access,profile,email,User.Read,https://outlook.office365.com/IMAP.AccessAsUser.All,https://outlook.office365.com/SMTP.Send', 'returnurl'=>'/core/modules/oauth/microsoft_oauthcallback.php'); if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { $supportedoauth2array['OAUTH_OTHER_NAME'] = array('callbackfile' => 'generic', 'picto' => 'generic', 'urlforapp' => 'OAUTH_OTHER_DESC', 'name'=>'Other', 'urlforcredentials'=>'', 'availablescopes'=>'Standard', 'returnurl'=>'/core/modules/oauth/generic_oauthcallback.php'); // See https://learn.microsoft.com/fr-fr/azure/active-directory/develop/quickstart-register-app#register-an-application diff --git a/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php b/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php index 90c20405e6b..6c3b18b3c0f 100644 --- a/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php +++ b/htdocs/includes/OAuth/OAuth2/Service/Microsoft.php @@ -38,8 +38,8 @@ class Microsoft extends AbstractService const SCOPE_APPLICATIONS = 'applications'; const SCOPE_APPLICATIONS_CREATE = 'applications_create'; const SCOPE_IMAP = 'imap'; - const SOCPE_IMAP_ACCESSASUSERALL = 'https://outlook.office.com/IMAP.AccessAsUser.All'; - const SOCPE_SMTPSEND = 'https://outlook.office.com/SMTP.Send'; + const SOCPE_IMAP_ACCESSASUSERALL = 'https://outlook.office365.com/IMAP.AccessAsUser.All'; + const SOCPE_SMTPSEND = 'https://outlook.office365.com/SMTP.Send'; const SOCPE_USERREAD = 'User.Read'; const SOCPE_MAILREAD = 'Mail.Read'; const SOCPE_MAILSEND = 'Mail.Send'; From c14471e41980d0ff5fa03244cd914d4cd450c533 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 15:39:38 +0200 Subject: [PATCH 156/417] css --- htdocs/projet/list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 26119927fda..e7e8cc40b68 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -1858,8 +1858,8 @@ while ($i < $imaxinloop) { } // Email MsgID if (!empty($arrayfields['p.email_msgid']['checked'])) { - print ''; - print $obj->email_msgid; + print ''; + print dol_escape_htmltag($obj->email_msgid); print ''; if (!$i) $totalarray['nbfield']++; } From ce8a8c617c750ef4f66843eb725325d1b901289d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 17:24:19 +0200 Subject: [PATCH 157/417] Fix Move of message with PHP-IMAP, Fix substitution for fetch thirdparty Fix php8 compatibility --- .../class/emailcollector.class.php | 130 +++++++++++++++--- 1 file changed, 111 insertions(+), 19 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 1b7c7ef2f27..ac1f1cf4cab 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -868,7 +868,7 @@ class EmailCollector extends CommonObject /** * overwitePropertiesOfObject * - * @param object $object Current object + * @param object $object Current object we will set ->properties * @param string $actionparam Action parameters * @param string $messagetext Body * @param string $subject Subject @@ -883,8 +883,13 @@ class EmailCollector extends CommonObject // Overwrite values with values extracted from source email // $this->actionparam = 'opportunity_status=123;abc=EXTRACT:BODY:....' $arrayvaluetouse = dolExplodeIntoArray($actionparam, ';', '='); + + $tmp = array(); + + // Loop on each property set into actionparam foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) { - $tmpclass = ''; $tmpproperty = ''; + $tmpclass = ''; + $tmpproperty = ''; $tmparray = explode('.', $propertytooverwrite); if (count($tmparray) == 2) { $tmpclass = $tmparray[0]; @@ -939,13 +944,21 @@ class EmailCollector extends CommonObject if (preg_match('/^options_/', $tmpproperty)) { $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $this->decodeSMTPSubject($valueextracted); } else { - $object->$tmpproperty = $this->decodeSMTPSubject($valueextracted); + if (property_exists($object, $tmpproperty)) { + $object->$tmpproperty = $this->decodeSMTPSubject($valueextracted); + } else { + $tmp[$tmpproperty] = $this->decodeSMTPSubject($valueextracted); + } } } else { // extract from BODY if (preg_match('/^options_/', $tmpproperty)) { $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $this->decodeSMTPSubject($valueextracted); } else { - $object->$tmpproperty = $this->decodeSMTPSubject($valueextracted); + if (property_exists($object, $tmpproperty)) { + $object->$tmpproperty = $this->decodeSMTPSubject($valueextracted); + } else { + $tmp[$tmpproperty] = $this->decodeSMTPSubject($valueextracted); + } } } if (preg_match('/^options_/', $tmpproperty)) { @@ -955,7 +968,11 @@ class EmailCollector extends CommonObject } } else { // Regex not found - $object->$tmpproperty = null; + if (property_exists($object, $tmpproperty)) { + $object->$tmpproperty = null; + } else { + $tmp[$tmpproperty] = null; + } $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> not found, so property '.dol_escape_htmltag($tmpproperty).' is set to null.'; } @@ -970,7 +987,11 @@ class EmailCollector extends CommonObject if (preg_match('/^options_/', $tmpproperty)) { $valuecurrent = $object->array_options[preg_replace('/^options_/', '', $tmpproperty)]; } else { - $valuecurrent = $object->$tmpproperty; + if (property_exists($object, $tmpproperty)) { + $valuecurrent = $object->$tmpproperty; + } else { + $valuecurrent = $tmp[$tmpproperty]; + } } if ($regforregex[1] == 'SET' || empty($valuecurrent)) { @@ -979,24 +1000,38 @@ class EmailCollector extends CommonObject $matcharray = array(); preg_match_all('/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray); //var_dump($tmpproperty.' - '.$object->$tmpproperty.' - '.$valuetouse); var_dump($matcharray); - if (is_array($matcharray[1])) { // $matcharray[1] is array with list of substitution key found without the __ + if (is_array($matcharray[1])) { // $matcharray[1] is an array with the list of substitution key found without the __X__ syntax into the SET entry foreach ($matcharray[1] as $keytoreplace) { - if ($keytoreplace && isset($object->$keytoreplace)) { - $substitutionarray['__'.$keytoreplace.'__'] = $object->$keytoreplace; + if ($keytoreplace) { + if (preg_match('/^options_/', $keytoreplace)) { + $substitutionarray['__'.$keytoreplace.'__'] = $object->array_options[preg_replace('/^options_/', '', $keytoreplace)]; + } else { + if (property_exists($object, $keytoreplace)) { + $substitutionarray['__'.$keytoreplace.'__'] = $object->$keytoreplace; + } else { + $substitutionarray['__'.$keytoreplace.'__'] = $tmp[$keytoreplace]; + } + } } } } //var_dump($substitutionarray); - dol_syslog(var_export($substitutionarray, true)); + dol_syslog('substitutionarray='.var_export($substitutionarray, true)); //var_dump($substitutionarray); $valuetouse = make_substitutions($valuetouse, $substitutionarray); if (preg_match('/^options_/', $tmpproperty)) { $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $valuetouse; - } else { - $object->$tmpproperty = $valuetouse; - } - $operationslog .= '
    Set value '.dol_escape_htmltag($valuetouse).' into variable '.dol_escape_htmltag($tmpproperty); + $operationslog .= '
    Set value '.dol_escape_htmltag($valuetouse).' into object->array_options['.dol_escape_htmltag(preg_replace('/^options_/', '', $tmpproperty)).']'; + } else { + if (property_exists($object, $tmpproperty)) { + $object->$tmpproperty = $valuetouse; + } else { + $tmp[$tmpproperty] = $valuetouse; + } + + $operationslog .= '
    Set value '.dol_escape_htmltag($valuetouse).' into object->'.dol_escape_htmltag($tmpproperty); + } } } else { $errorforthisaction++; @@ -1411,6 +1446,9 @@ class EmailCollector extends CommonObject try { //var_dump($Query->count()); + if ($mode > 0) { + $Query->leaveUnread(); + } $arrayofemail = $Query->limit($this->maxemailpercollect)->setFetchOrder("asc")->get(); //var_dump($arrayofemail); } catch (Exception $e) { @@ -1957,6 +1995,7 @@ class EmailCollector extends CommonObject $result = $contactstatic->fetch(0, null, '', $from); if ($result > 0) { + dol_syslog("We found a contact with the email ".$from); $contactid = $contactstatic->id; $contactfoundby = 'email of contact ('.$from.')'; if (empty($thirdpartyid) && $contactstatic->socid > 0) { @@ -1972,12 +2011,44 @@ class EmailCollector extends CommonObject if (empty($thirdpartyid)) { // Try to find thirdparty using email $result = $thirdpartystatic->fetch(0, '', '', '', '', '', '', '', '', '', $from); if ($result > 0) { + dol_syslog("We found a thirdparty with the email ".$from); + $thirdpartyid = $thirdpartystatic->id;; $thirdpartyfoundby = 'email ('.$from.')'; } } - // Do operations - if ($mode < 2) { + /* + if ($replyto) { + if (empty($contactid)) { // Try to find contact using email + $result = $contactstatic->fetch(0, null, '', $replyto); + + if ($result > 0) { + dol_syslog("We found a contact with the email ".$replyto); + $contactid = $contactstatic->id; + $contactfoundby = 'email of contact ('.$replyto.')'; + if (empty($thirdpartyid) && $contactstatic->socid > 0) { + $result = $thirdpartystatic->fetch($contactstatic->socid); + if ($result > 0) { + $thirdpartyid = $thirdpartystatic->id; + $thirdpartyfoundby = 'email of contact ('.$replyto.')'; + } + } + } + } + + if (empty($thirdpartyid)) { // Try to find thirdparty using email + $result = $thirdpartystatic->fetch(0, '', '', '', '', '', '', '', '', '', $replyto); + if ($result > 0) { + dol_syslog("We found a thirdparty with the email ".$replyto); + $thirdpartyid = $thirdpartystatic->id;; + $thirdpartyfoundby = 'email ('.$replyto.')'; + } + } + } + */ + + // Do operations (extract variables and creating data) + if ($mode < 2) { // 0=Mode production, 1=Mode test (read IMAP and try SQL update then rollback), 2=Mode test with no SQL updates foreach ($this->actions as $operation) { $errorforthisaction = 0; @@ -2118,6 +2189,23 @@ class EmailCollector extends CommonObject } if (!$errorforactions && ($idtouseforthirdparty || $emailtouseforthirdparty || $nametouseforthirdparty || $namealiastouseforthirdparty)) { + // We make another search on thirdparty + //$namealiastouseforthirdparty + + $tmpobject = new stdClass(); + $tmpobject->element == 'generic'; + $tmpobject->id = $idtouseforthirdparty; + $tmpobject->name = $nametouseforthirdparty; + $tmpobject->name_alias = $namealiastouseforthirdparty; + $tmpobject->email = $emailtouseforthirdparty; + + $this->overwritePropertiesOfObject($tmpobject, $operation['actionparam'], $messagetext, $subject, $header, $operationslog); + + $idtouseforthirdparty = $tmpobject->id; + $nametouseforthirdparty = $tmpobject->name; + $namealiastouseforthirdparty = $tmpobject->name_alias; + $emailtouseforthirdparty = $tmpobject->name_alias; + $result = $thirdpartystatic->fetch($idtouseforthirdparty, $nametouseforthirdparty, '', '', '', '', '', '', '', '', $emailtouseforthirdparty, $namealiastouseforthirdparty); if ($result < 0) { $errorforactions++; @@ -2555,6 +2643,8 @@ class EmailCollector extends CommonObject } } } else { + dol_syslog("Project already exists for msgid = ".dol_escape_htmltag($msgid).", so we do not recreate it."); + $operationslog .= '
    Project already exists for msgid ='.dol_escape_htmltag($msgid); } } elseif ($operation['type'] == 'ticket') { @@ -2824,9 +2914,9 @@ class EmailCollector extends CommonObject // Error for email or not ? if (!$errorforactions) { - if ($targetdir && empty($mode)) { + if (!empty($targetdir) && empty($mode)) { if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { - dol_syslog("EmailCollector::doCollectOneCollector move message ".$imapemail." to ".$connectstringtarget, LOG_DEBUG); + dol_syslog("EmailCollector::doCollectOneCollector move message ".((string) $imapemail)." to ".$connectstringtarget, LOG_DEBUG); $res = imap_mail_move($connection, $imapemail, $targetdir, 0); if ($res == false) { $errorforemail++; @@ -2835,7 +2925,9 @@ class EmailCollector extends CommonObject dol_syslog(imap_last_error()); } } else { - // TODO Move mail using PHP-IMAP + // Move mail using PHP-IMAP + dol_syslog("EmailCollector::doCollectOneCollector move message ".($imapemail->getHeader()->get('subject'))." to ".$targetdir, LOG_DEBUG); + $imapemail->move($targetdir); } } else { if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { From 1b19a30386a38e23c0520f313408a3771ea6af33 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 18:00:46 +0200 Subject: [PATCH 158/417] Debug email collector --- .../class/emailcollector.class.php | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index ac1f1cf4cab..97dbc20551d 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -964,7 +964,11 @@ class EmailCollector extends CommonObject if (preg_match('/^options_/', $tmpproperty)) { $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($object->array_options[preg_replace('/^options_/', '', $tmpproperty)], 128)); } else { - $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($object->$tmpproperty, 128)); + if (property_exists($object, $tmpproperty)) { + $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($object->$tmpproperty, 128)); + } else { + $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($tmp[$tmpproperty], 128)); + } } } else { // Regex not found @@ -2059,6 +2063,8 @@ class EmailCollector extends CommonObject continue; } + $operationslog .= '
    * Process operation '.$operation['type']; + // Make Operation dol_syslog("Execute action ".$operation['type']." actionparam=".$operation['actionparam'].' thirdpartystatic->id='.$thirdpartystatic->id.' contactstatic->id='.$contactstatic->id.' projectstatic->id='.$projectstatic->id); dol_syslog("Execute action fk_element_id=".$fk_element_id." fk_element_type=".$fk_element_type); // If a Dolibarr tracker id is found, we should now the id of object @@ -2096,6 +2102,8 @@ class EmailCollector extends CommonObject $emailtouseforthirdparty = ''; $namealiastouseforthirdparty = ''; + $operationslog .= '
    Loop on each property to set into actionparam'; + // $actionparam = 'param=SET:aaa' or 'param=EXTRACT:BODY:....' $arrayvaluetouse = dolExplodeIntoArray($actionparam, ';', '='); foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) { @@ -2127,21 +2135,21 @@ class EmailCollector extends CommonObject if ($propertytooverwrite == 'id') { $idtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; - $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found idtouseforthirdparty='.dol_escape_htmltag($idtouseforthirdparty); + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found idtouseforthirdparty='.dol_escape_htmltag($idtouseforthirdparty); } elseif ($propertytooverwrite == 'email') { $emailtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; - $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found emailtouseforthirdparty='.dol_escape_htmltag($emailtouseforthirdparty); + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found emailtouseforthirdparty='.dol_escape_htmltag($emailtouseforthirdparty); } elseif ($propertytooverwrite == 'name') { $nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; - $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty); + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty); } elseif ($propertytooverwrite == 'name_alias') { - $nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; + $namealiastouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; - $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty); + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty); } else { - $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> We discard this, not used to search existing thirdparty'; + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> We discard this, not used to search existing thirdparty'; } } else { // Regex not found @@ -2150,7 +2158,7 @@ class EmailCollector extends CommonObject $emailtouseforthirdparty = null; $namealiastouseforthirdparty = null; - $operationslog .= '
    Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Not found'; + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Not found'; } //var_dump($object->$tmpproperty);exit; } else { @@ -2166,19 +2174,19 @@ class EmailCollector extends CommonObject if ($propertytooverwrite == 'id') { $idtouseforthirdparty = $reg[2]; - $operationslog .= '
    We set property idtouseforthrdparty='.dol_escape_htmltag($idtouseforthirdparty); + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.'We set property idtouseforthrdparty='.dol_escape_htmltag($idtouseforthirdparty); } elseif ($propertytooverwrite == 'email') { $emailtouseforthirdparty = $reg[2]; - $operationslog .= '
    We set property emailtouseforthrdparty='.dol_escape_htmltag($emailtouseforthirdparty); + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.'We set property emailtouseforthrdparty='.dol_escape_htmltag($emailtouseforthirdparty); } elseif ($propertytooverwrite == 'name') { $nametouseforthirdparty = $reg[2]; - $operationslog .= '
    We set property nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty); + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.'We set property nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty); } elseif ($propertytooverwrite == 'name_alias') { $namealiastouseforthirdparty = $reg[2]; - $operationslog .= '
    We set property namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty); + $operationslog .= '
    propertytooverwrite='.$propertytooverwrite.'We set property namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty); } } else { $errorforactions++; @@ -2190,7 +2198,7 @@ class EmailCollector extends CommonObject if (!$errorforactions && ($idtouseforthirdparty || $emailtouseforthirdparty || $nametouseforthirdparty || $namealiastouseforthirdparty)) { // We make another search on thirdparty - //$namealiastouseforthirdparty + $operationslog .= '
    We have this data to search thirdparty: '.$idtouseforthirdparty.' '.$emailtouseforthirdparty.' '.$nametouseforthirdparty.' '.$namealiastouseforthirdparty; $tmpobject = new stdClass(); $tmpobject->element == 'generic'; @@ -2204,7 +2212,9 @@ class EmailCollector extends CommonObject $idtouseforthirdparty = $tmpobject->id; $nametouseforthirdparty = $tmpobject->name; $namealiastouseforthirdparty = $tmpobject->name_alias; - $emailtouseforthirdparty = $tmpobject->name_alias; + $emailtouseforthirdparty = $tmpobject->email; + + $operationslog .= '
    We try to search existing thirdparty with '.$idtouseforthirdparty.' '.$emailtouseforthirdparty.' '.$nametouseforthirdparty.' '.$namealiastouseforthirdparty; $result = $thirdpartystatic->fetch($idtouseforthirdparty, $nametouseforthirdparty, '', '', '', '', '', '', '', '', $emailtouseforthirdparty, $namealiastouseforthirdparty); if ($result < 0) { @@ -2224,6 +2234,7 @@ class EmailCollector extends CommonObject dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." name_alias=".$namealiastouseforthirdparty." was not found. We try to create it."); // Create thirdparty + $thirdpartystatic = new Societe($db); $thirdpartystatic->name = $nametouseforthirdparty; if (!empty($namealiastouseforthirdparty)) { if ($namealiastouseforthirdparty != $nametouseforthirdparty) { @@ -2259,6 +2270,8 @@ class EmailCollector extends CommonObject } } else { dol_syslog("One and only one existing third party has been found"); + + $operationslog .= '
    Thirdparty already exists with id = '.dol_escape_htmltag($thirdpartystatic->id); } } } From 5f1503d7eacfae0691c3b135d8d5e9ffb1e6d21c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 18:05:47 +0200 Subject: [PATCH 159/417] Log --- htdocs/emailcollector/class/emailcollector.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 97dbc20551d..7391d6e6acd 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1066,7 +1066,7 @@ class EmailCollector extends CommonObject require_once DOL_DOCUMENT_ROOT.'/includes/webklex/php-imap/vendor/autoload.php'; } - dol_syslog("EmailCollector::doCollectOneCollector start for id=".$this->id." - ".$this->ref, LOG_DEBUG); + dol_syslog("EmailCollector::doCollectOneCollector start for id=".$this->id." - ".$this->ref, LOG_INFO); $langs->loadLangs(array("project", "companies", "mails", "errors", "ticket", "agenda", "commercial")); @@ -2994,6 +2994,7 @@ class EmailCollector extends CommonObject $client->disconnect(); } else { if (empty($mode) && empty($error)) { + dol_syslog("Expunge", LOG_DEBUG); imap_expunge($connection); // To validate any move } imap_close($connection); @@ -3022,7 +3023,7 @@ class EmailCollector extends CommonObject $this->update($user); } - dol_syslog("EmailCollector::doCollectOneCollector end", LOG_DEBUG); + dol_syslog("EmailCollector::doCollectOneCollector end", LOG_INFO); return $error ? -1 : 1; } From 66923ccf8c609cd3ec1ab32fd0b43cdee386abbd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 18:47:54 +0200 Subject: [PATCH 160/417] Code comment --- htdocs/includes/webklex/php-imap/vendor/autoload.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/htdocs/includes/webklex/php-imap/vendor/autoload.php b/htdocs/includes/webklex/php-imap/vendor/autoload.php index 298bedf9b9c..12f2cb6cb45 100644 --- a/htdocs/includes/webklex/php-imap/vendor/autoload.php +++ b/htdocs/includes/webklex/php-imap/vendor/autoload.php @@ -17,6 +17,13 @@ return ComposerAutoloaderInit4da13270269c89a28e472e1f7324e6d1::getLoader(); // Add class/method of PHP8 for compatibility with older versions of PHP require_once(__DIR__.'/symfony/polyfill-php80/bootstrap.php'); +//'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', +//'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', +//'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php', +//'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', +//'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', +require_once(__DIR__.'/illuminate/collections/helpers.php'); + spl_autoload_register(function ($class_name) { // Enable this to detect what we need for require_once From 9ffc86a8726974001f33f631b076aa686b8d1882 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 18:49:15 +0200 Subject: [PATCH 161/417] Remove warning 8.2 --- htdocs/core/class/conf.class.php | 19 ++++++++++++++++++- test/phpunit/AllTests.php | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 756b2771e39..b3991ecfcf2 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -109,6 +109,24 @@ class Conf public $tzuserinputkey = 'tzserver'; // Use 'tzuserrel' to always store date in GMT and show date in time zone of user. + // TODO Remove this part. + public $fournisseur; + public $product; + public $service; + public $contrat; + public $actions; + public $agenda; + public $commande; + public $propal; + public $facture; + public $user; + public $adherent; + public $bank; + public $notification; + public $expensereport; + public $productbatch; + + /** * Constructor @@ -165,7 +183,6 @@ class Conf $this->commande = new stdClass(); $this->propal = new stdClass(); $this->facture = new stdClass(); - $this->contrat = new stdClass(); $this->user = new stdClass(); $this->adherent = new stdClass(); $this->bank = new stdClass(); diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index ba4d743f603..84ea7a42a6e 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -24,7 +24,7 @@ * \remarks To run this script as CLI: phpunit filename.php */ print "PHP Version: ".phpversion()."\n"; -print "Memory: ". ini_get('memory_limit')."\n"; +print "Memory limit: ". ini_get('memory_limit')."\n"; global $conf,$user,$langs,$db; //define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver From 45d79232d20c5275696132d9829ae0d66d381d90 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 19:36:19 +0200 Subject: [PATCH 162/417] Clean code --- htdocs/product/class/product.class.php | 1 + test/phpunit/MouvementStockTest.php | 35 ++++++++++++++------------ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 67002e48efb..db5ebf7bf4c 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -871,6 +871,7 @@ class Product extends CommonObject $langs->load("products"); $error++; $this->error = "ErrorProductAlreadyExists"; + dol_syslog(get_class($this)."::Create fails, ref ".$this->ref." already exists"); } } else { $error++; diff --git a/test/phpunit/MouvementStockTest.php b/test/phpunit/MouvementStockTest.php index a781ea78e12..d084f50d6e0 100644 --- a/test/phpunit/MouvementStockTest.php +++ b/test/phpunit/MouvementStockTest.php @@ -146,41 +146,44 @@ class MouvementStockTest extends PHPUnit\Framework\TestCase // We create a product for tests $product0=new Product($db); $product0->initAsSpecimen(); - $product0->ref.=' 0'; - $product0->label.=' 0'; + $product0->ref.=' phpunit 0'; + $product0->label.=' phpunit 0'; $product0->status_batch = 1; $product0id=$product0->create($user); + print __METHOD__." product0id=".$product0id."\n"; + $this->assertGreaterThan(0, $product0id, 'Failed to create product'); + $product1=new Product($db); $product1->initAsSpecimen(); - $product1->ref.=' 1'; - $product1->label.=' 1'; + $product1->ref.=' phpunit 1'; + $product1->label.=' phpunit 1'; $product1id=$product1->create($user); $product2=new Product($db); $product2->initAsSpecimen(); - $product2->ref.=' 2'; - $product2->label.=' 2'; + $product2->ref.=' phpunit 2'; + $product2->label.=' phpunit 2'; $product2id=$product2->create($user); // We create a product for tests $warehouse0=new Entrepot($db); $warehouse0->initAsSpecimen(); - $warehouse0->label.=' 0'; - $warehouse0->description.=' 0'; + $warehouse0->label.=' phpunit 0'; + $warehouse0->description.=' phpunit 0'; $warehouse0->statut = 0; $warehouse0id=$warehouse0->create($user); $warehouse1=new Entrepot($db); $warehouse1->initAsSpecimen(); - $warehouse1->label.=' 1'; - $warehouse1->description.=' 1'; + $warehouse1->label.=' phpunit 1'; + $warehouse1->description.=' phpunit 1'; $warehouse1id=$warehouse1->create($user); $warehouse2=new Entrepot($db); $warehouse2->initAsSpecimen(); - $warehouse2->label.=' 2'; - $warehouse2->description.=' 2'; + $warehouse2->label.=' phpunit 2'; + $warehouse2->description.=' phpunit 2'; $warehouse2id=$warehouse2->create($user); $localobject=new MouvementStock($this->savdb); @@ -188,10 +191,10 @@ class MouvementStockTest extends PHPUnit\Framework\TestCase $datetest1 = dol_mktime(0, 0, 0, 1, 1, 2000); $datetest2 = dol_mktime(0, 0, 0, 1, 2, 2000); - // Create an input movement movement (type = 3) with value for eatby date and a lot + // Create an input movement movement (type = 3) with value for eatby date and a lot $datetest1 $result=$localobject->reception($user, $product0id, $warehouse0id, 5, 999, 'Movement for unit test with batch', $datetest1, $datetest1, 'anotyetuselotnumberA', '', 0, 'Inventory Code Test with batch'); print __METHOD__." result=".$result."\n"; - $this->assertGreaterThan(0, $result, 'Failed to create a movement with a lot number of product with status_batch=1'); + $this->assertGreaterThan(0, $result, 'Failed to create a movement with a lot number '.$datetest1.' for product id='.$product0id.' with status_batch=1'); $result=$localobject->reception($user, $product0id, $warehouse0id, 5, 999, 'Movement for unit test with batch', $datetest1, $datetest1, 'anotyetuselotnumberB', '', 0, 'Inventory Code Test with batch'); print __METHOD__." result=".$result."\n"; @@ -250,12 +253,12 @@ class MouvementStockTest extends PHPUnit\Framework\TestCase // Create an output movement (type = 1) of price 9.7 -> should update PMP to 9.9/9.7 = 9.8 $result=$localobject->_create($user, $product1id, $warehouse2id, 1, 0, 0, 'Input from transfer wh 2', 'Transfert X 2'); print __METHOD__." result=".$result."\n"; - $this->assertGreaterThan(0, $result); + $this->assertGreaterThan(0, $result, 'Test create A'); // Create an output movement (type = 1) of price 9.7 -> should update PMP to 9.9/9.7 = 9.8 $result=$localobject->_create($user, $product1id, $warehouse2id, -2, 1, 0, 'Output from transfer wh 2', 'Transfert Y 2'); print __METHOD__." result=".$result."\n"; - $this->assertGreaterThan(0, $result); + $this->assertGreaterThan(0, $result, 'Test create B'); return $localobject; } From a8cd44cafccff61845b15f335840865a31bacc59 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 22:17:15 +0200 Subject: [PATCH 163/417] Clean code --- test/phpunit/CategorieTest.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/phpunit/CategorieTest.php b/test/phpunit/CategorieTest.php index 3bd870914e3..1faab723bb2 100644 --- a/test/phpunit/CategorieTest.php +++ b/test/phpunit/CategorieTest.php @@ -259,11 +259,12 @@ class CategorieTest extends PHPUnit\Framework\TestCase $langs=$this->savlangs; $db=$this->savdb; - $localobject->note='New note after update'; + $localobject->note_private ='New note after update'; $result=$localobject->update($user); print __METHOD__." id=".$localobject->id." result=".$result."\n"; $this->assertGreaterThan(0, $result); + return $localobject; } @@ -288,8 +289,6 @@ class CategorieTest extends PHPUnit\Framework\TestCase print __METHOD__." id=".$localobject->id." result=".$result."\n"; $this->assertLessThan($result, 0); */ - $localobject2=new Categorie($db); - $localobject2->initAsSpecimen(); $retarray=$localobject->liste_photos('/'); print __METHOD__." retarray size=".count($retarray)."\n"; From bc711b05040315220a359cbb0bcc772cae49ff02 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 22:20:54 +0200 Subject: [PATCH 164/417] FIX Deployment of external module failed with copy dir error. --- htdocs/admin/modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index ac8ff6161a9..f6e281f5e2d 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -231,7 +231,7 @@ if ($action == 'install') { if (!$error) { @dol_delete_dir_recursive($dirins.'/'.$modulenameval); // delete the target directory $submodulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/'.$modulenameval; - if (!dol_is_dir($modulenamedir)) { + if (!dol_is_dir($submodulenamedir)) { $submodulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulenameval; } dol_syslog("We copy now directory ".$submodulenamedir." into target dir ".$dirins.'/'.$modulenameval); From c552633095140f68ece17b3d6a6b715a15e1964a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 12 Apr 2023 00:13:06 +0200 Subject: [PATCH 165/417] Log --- htdocs/admin/modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index f6e281f5e2d..226ab6d70b3 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -443,7 +443,7 @@ foreach ($modulesdir as $dir) { dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR); } } else { - print "Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)
    "; + print "admin/modules.php Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)
    "; } } catch (Exception $e) { dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR); From ed848753201930e0450facaa26f3f5e14dc19cf4 Mon Sep 17 00:00:00 2001 From: sonikf <93765174+sonikf@users.noreply.github.com> Date: Wed, 12 Apr 2023 01:38:38 +0300 Subject: [PATCH 166/417] Update master.inc.php --- htdocs/master.inc.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index 0f10300ea98..a400b35106b 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -233,7 +233,14 @@ if (!defined('NOREQUIREDB') && !defined('NOREQUIRESOC')) { // This is very problematic during a fiscal control. $conf->global->INVOICE_DISABLE_REPLACEMENT = 1; } - + if ($mysoc->country_code == 'GR' && !isset($conf->global->INVOICE_DISABLE_REPLACEMENT)) { + // The replacement invoice type is not allowed in Greece. + $conf->global->INVOICE_DISABLE_REPLACEMENT = 1; + } + if ($mysoc->country_code == 'GR' && !isset($conf->global->INVOICE_DISABLE_DEPOSIT)) { + // The deposit invoice type is not allowed in Greece. + $conf->global->INVOICE_DISABLE_DEPOSIT = 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. From f5ac52bd01762cb0f88dbc5ea21f8c9177240fbc Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 11 Apr 2023 23:37:03 +0000 Subject: [PATCH 167/417] Fixing style errors. --- htdocs/master.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index a400b35106b..17fcc123a2b 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -236,11 +236,11 @@ if (!defined('NOREQUIREDB') && !defined('NOREQUIRESOC')) { if ($mysoc->country_code == 'GR' && !isset($conf->global->INVOICE_DISABLE_REPLACEMENT)) { // The replacement invoice type is not allowed in Greece. $conf->global->INVOICE_DISABLE_REPLACEMENT = 1; - } + } if ($mysoc->country_code == 'GR' && !isset($conf->global->INVOICE_DISABLE_DEPOSIT)) { // The deposit invoice type is not allowed in Greece. $conf->global->INVOICE_DISABLE_DEPOSIT = 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. From 28c625dc6b286835c09e5660e1b83232131c3fbf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 12 Apr 2023 03:38:25 +0200 Subject: [PATCH 168/417] NEW Show main currency in company info user tooltip --- htdocs/main.inc.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index ce7a7a9ec8d..8ca8d5e06af 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2312,7 +2312,9 @@ function top_menu_user($hideloginname = 0, $urllogout = '') } $dropdownBody .= '
    '.$langs->trans("VATIntraShort").': '.dol_print_profids(getDolGlobalString("MAIN_INFO_TVAINTRA"), 'VAT').''; $dropdownBody .= '
    '.$langs->trans("Country").': '.($mysoc->country_code ? $langs->trans("Country".$mysoc->country_code) : '').''; - + if (isModEnabled('multicurrency')) { + $dropdownBody .= '
    '.$langs->trans("Currency").': '.$conf->currency.''; + } $dropdownBody .= '
    '; $dropdownBody .= '
    '; From 8e63baeeab889e7f5c93152ef251566af1c28935 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 12 Apr 2023 04:50:40 +0200 Subject: [PATCH 169/417] Debug v18 --- htdocs/compta/bank/transfer.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/htdocs/compta/bank/transfer.php b/htdocs/compta/bank/transfer.php index 724e09554db..62e85558ed1 100644 --- a/htdocs/compta/bank/transfer.php +++ b/htdocs/compta/bank/transfer.php @@ -114,13 +114,13 @@ if ($action == 'add') { if (!$errori[$n]) { require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; - $accountfrom = new Account($db); - $accountfrom->fetch(GETPOST($n.'_account_from', 'int')); + $tmpaccountfrom = new Account($db); + $tmpaccountfrom->fetch(GETPOST($n.'_account_from', 'int')); - $accountto = new Account($db); - $accountto->fetch(GETPOST($n.'_account_to', 'int')); + $tmpaccountto = new Account($db); + $tmpaccountto->fetch(GETPOST($n.'_account_to', 'int')); - if ($accountto->currency_code == $accountfrom->currency_code) { + if ($tmpaccountto->currency_code == $tmpaccountfrom->currency_code) { $amountto[$n] = $amount[$n]; } else { if (!$amountto[$n]) { @@ -133,7 +133,7 @@ if ($action == 'add') { setEventMessages($langs->trans("AmountMustBePositive").' #'.$n, null, 'errors'); } - if ($accountto->id == $accountfrom->id) { + if ($tmpaccountto->id == $tmpaccountfrom->id) { $errori[$n]++; setEventMessages($langs->trans("ErrorFromToAccountsMustDiffers").' #'.$n, null, 'errors'); } @@ -149,45 +149,45 @@ if ($action == 'add') { // By default, electronic transfert from bank to bank $typefrom = $type[$n]; $typeto = $type[$n]; - if ($accountto->courant == Account::TYPE_CASH || $accountfrom->courant == Account::TYPE_CASH) { + if ($tmpaccountto->courant == Account::TYPE_CASH || $tmpaccountfrom->courant == Account::TYPE_CASH) { // This is transfer of change $typefrom = 'LIQ'; $typeto = 'LIQ'; } if (!$errori[$n]) { - $bank_line_id_from = $accountfrom->addline($dateo[$n], $typefrom, $label[$n], price2num(-1 * $amount[$n]), '', '', $user); + $bank_line_id_from = $tmpaccountfrom->addline($dateo[$n], $typefrom, $label[$n], price2num(-1 * $amount[$n]), '', '', $user); } if (!($bank_line_id_from > 0)) { $errori[$n]++; } if (!$errori[$n]) { - $bank_line_id_to = $accountto->addline($dateo[$n], $typeto, $label[$n], $amountto[$n], '', '', $user); + $bank_line_id_to = $tmpaccountto->addline($dateo[$n], $typeto, $label[$n], $amountto[$n], '', '', $user); } if (!($bank_line_id_to > 0)) { $errori[$n]++; } if (!$errori[$n]) { - $result = $accountfrom->add_url_line($bank_line_id_from, $bank_line_id_to, DOL_URL_ROOT.'/compta/bank/line.php?rowid=', '(banktransfert)', 'banktransfert'); + $result = $tmpaccountfrom->add_url_line($bank_line_id_from, $bank_line_id_to, DOL_URL_ROOT.'/compta/bank/line.php?rowid=', '(banktransfert)', 'banktransfert'); } if (!($result > 0)) { $errori++; } if (!$errori[$n]) { - $result = $accountto->add_url_line($bank_line_id_to, $bank_line_id_from, DOL_URL_ROOT.'/compta/bank/line.php?rowid=', '(banktransfert)', 'banktransfert'); + $result = $tmpaccountto->add_url_line($bank_line_id_to, $bank_line_id_from, DOL_URL_ROOT.'/compta/bank/line.php?rowid=', '(banktransfert)', 'banktransfert'); } if (!($result > 0)) { $errori[$n]++; } if (!$errori[$n]) { $mesgs = $langs->trans("TransferFromToDone", '{s1}', '{s2}', $amount[$n], $langs->transnoentitiesnoconv("Currency".$conf->currency)); - $mesgs = str_replace('{s1}', ''.$accountfrom->label.'', $mesgs); - $mesgs = str_replace('{s2}', ''.$accountto->label.'', $mesgs); + $mesgs = str_replace('{s1}', ''.$tmpaccountfrom->label.'', $mesgs); + $mesgs = str_replace('{s2}', ''.$tmpaccountto->label.'', $mesgs); setEventMessages($mesgs, null, 'mesgs'); $db->commit(); } else { - setEventMessages($accountfrom->error.' '.$accountto->error, null, 'errors'); + setEventMessages($tmpaccountfrom->error.' '.$tmpaccountto->error, null, 'errors'); $db->rollback(); } } From 0d8d2528b040008c1767a13b0b07a5ce8a37de9e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 12 Apr 2023 06:08:06 +0200 Subject: [PATCH 170/417] Clean code --- htdocs/compta/bank/transfer.php | 93 +++++++++---------------- htdocs/core/ajax/getaccountcurrency.php | 66 ------------------ 2 files changed, 34 insertions(+), 125 deletions(-) delete mode 100644 htdocs/core/ajax/getaccountcurrency.php diff --git a/htdocs/compta/bank/transfer.php b/htdocs/compta/bank/transfer.php index 62e85558ed1..2e7425dca98 100644 --- a/htdocs/compta/bank/transfer.php +++ b/htdocs/compta/bank/transfer.php @@ -76,7 +76,7 @@ if ($action == 'add') { $errori[$i] = 0; $tabnum[$i] = 0; - if (!empty($label[$i]) || !empty($type[$i]) || !($amount[$i] <= 0) || !($accountfrom[$i] < 0) || !($accountto[$i] < 0)) { + if (!empty($label[$i]) || !($amount[$i] <= 0) || !($accountfrom[$i] < 0) || !($accountto[$i] < 0)) { $tabnum[$i] = 1; } $i++; @@ -124,7 +124,7 @@ if ($action == 'add') { $amountto[$n] = $amount[$n]; } else { if (!$amountto[$n]) { - $error[$n]++; + $errori[$n]++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AmountTo")).' #'.$n, null, 'errors'); } } @@ -172,7 +172,7 @@ if ($action == 'add') { $result = $tmpaccountfrom->add_url_line($bank_line_id_from, $bank_line_id_to, DOL_URL_ROOT.'/compta/bank/line.php?rowid=', '(banktransfert)', 'banktransfert'); } if (!($result > 0)) { - $errori++; + $errori[$n]++; } if (!$errori[$n]) { $result = $tmpaccountto->add_url_line($bank_line_id_to, $bank_line_id_from, DOL_URL_ROOT.'/compta/bank/line.php?rowid=', '(banktransfert)', 'banktransfert'); @@ -211,68 +211,38 @@ llxHeader('', $title, $help_url); print ' '; @@ -298,16 +268,18 @@ print ''.$langs->trans("Type").''; print ''.$langs->trans("Date").''; print ''.$langs->trans("Description").''; print ''.$langs->trans("Amount").''; -//print ''.$langs->trans("AmountToOthercurrency").''; +print ''.$langs->trans("AmountToOthercurrency").''; print ''; for ($i = 1 ; $i < $MAXLINES; $i++) { $label = ''; $amount = ''; + $amounto = ''; if ($errori[$i]) { $label = GETPOST($i.'_label', 'alpha'); $amount = GETPOST($i.'_amount', 'alpha'); + $amountto = GETPOST($i.'_amountto', 'alpha'); } if ($i == 1) { @@ -339,11 +311,14 @@ for ($i = 1 ; $i < $MAXLINES; $i++) { print $form->selectDate((!empty($dateo[$i]) ? $dateo[$i] : ''), $i.'_', '', '', '', 'add'); print "\n"; + // Description print ''; + // Amount print ''; - print ''; + // AmountToOthercurrency + print ''; print ''; } @@ -352,7 +327,7 @@ print ''; print '
    '; print ''; print '
    '; -print ' +print ' '; diff --git a/htdocs/core/ajax/getaccountcurrency.php b/htdocs/core/ajax/getaccountcurrency.php deleted file mode 100644 index 20061dcdf2b..00000000000 --- a/htdocs/core/ajax/getaccountcurrency.php +++ /dev/null @@ -1,66 +0,0 @@ - - * - * 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 - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * \file htdocs/core/ajax/getaccountcurrency.php - * \brief File to load currency rates - */ - -if (!defined('NOTOKENRENEWAL')) { - define('NOTOKENRENEWAL', '1'); // Disables token renewal -} -if (!defined('NOREQUIREMENU')) { - define('NOREQUIREMENU', '1'); -} -if (!defined('NOREQUIREAJAX')) { - define('NOREQUIREAJAX', '1'); -} - -// Load Dolibarr environment -require '../../main.inc.php'; - -$id = GETPOST('id', 'int'); - -// Security check -$result = restrictedArea($user, 'banque', $id, 'bank_account&bank_account'); - - -/* - * View - */ - -top_httphead(); - -//print ''."\n"; - -// Load original field value -if (!empty($id)) { - require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; - $account = new Account($db); - $result = $account->fetch($id); - if ($result < 0) { - $return['value'] = ''; - $return['num'] = $result; - $return['error'] = $account->errors[0]; - } else { - $return['value'] = $account->currency_code; - $return['num'] = $result; - $return['error'] = ''; - } - - echo json_encode($return); -} From a2d9de14acb53f1f984155bac8e2d9b33d935e2c Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Wed, 12 Apr 2023 12:03:27 +0200 Subject: [PATCH 171/417] FIX: Propagate vat-reverse charge when supplier invoice is created from reception list --- htdocs/reception/list.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php index fe47b95fb1e..d348252efeb 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -2,7 +2,8 @@ /* Copyright (C) 2001-2005 Rodolphe Quiedeville * Copyright (C) 2004-2015 Laurent Destailleur * Copyright (C) 2005-2010 Regis Houssin - * Copyright (C) 2016 Ferran Marcet + * Copyright (C) 2016 Ferran Marcet + * Copyright (C) 2023 Alexandre Spangaro * * 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 @@ -345,6 +346,9 @@ if (empty($reshook)) { $objecttmp->remise_absolue = $remise_absolue; $objecttmp->transport_mode_id = $transport_mode_id; + // if the VAT reverse-charge is activated by default in supplier card to resume the information + $objecttmp->vat_reverse_charge = $soc->vat_reverse_charge; + $objecttmp->fk_project = $rcp->fk_project; //$objecttmp->multicurrency_code = $rcp->multicurrency_code; if (empty($createbills_onebythird)) { From 404397df8ce9f5cc9459e16dbecdf7430be3ec7f Mon Sep 17 00:00:00 2001 From: Joachim Kueter Date: Wed, 12 Apr 2023 14:12:42 +0200 Subject: [PATCH 172/417] Remove unnecessary output of extrafields The extrafields for a bom line are already output at line 130 (correct within html tags). The additional output here (without any html tags) causes the extrafields to be displayed additionally on top of all line items. --- htdocs/bom/tpl/objectline_create.tpl.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index b57196bb9a8..99898e37ae0 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -195,10 +195,6 @@ if ($filtertype != 1) { print ''; print ''; - -if (is_object($objectline)) { - print $objectline->showOptionals($extrafields, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay), '', '', 1, 'line'); -} ?>