From 05e09ccc17bd713d5ae2af13c31f79d8c7b00d22 Mon Sep 17 00:00:00 2001 From: altairis-noe Date: Fri, 16 Jul 2021 17:46:21 +0200 Subject: [PATCH 001/128] 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/128] 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/128] 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 f1c14316937459ac26077a69b5effde90070bbbf Mon Sep 17 00:00:00 2001 From: kkhelifa Date: Thu, 17 Nov 2022 17:09:13 +0100 Subject: [PATCH 004/128] 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 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 005/128] 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 620cbf398ab1790f489ff2fadfa5d68ff1b9fcdb Mon Sep 17 00:00:00 2001 From: kkhelifa Date: Thu, 30 Mar 2023 11:10:22 +0200 Subject: [PATCH 006/128] 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 007/128] 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 afda5c041698027c0daf61c4ca2a6af90e0ec45a Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 5 Apr 2023 11:21:22 +0200 Subject: [PATCH 008/128] 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 009/128] 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 010/128] 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 011/128] 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 012/128] 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 013/128] 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 3a13924685a454e1c7a571047ce9fea405710f86 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 5 Apr 2023 12:43:52 +0200 Subject: [PATCH 014/128] 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 015/128] 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 016/128] 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 017/128] 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 424c53109f8a128f0b5514c368ade04580fc7ace Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 17:56:03 +0200 Subject: [PATCH 018/128] 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 019/128] 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 4d504b3f985528457d3bd24dbb112f1c645296c0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 5 Apr 2023 18:43:59 +0200 Subject: [PATCH 020/128] 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 021/128] 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 022/128] 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 023/128] 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 024/128] #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 025/128] 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 026/128] 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 078/128] 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 079/128] 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 '
'.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').'
'; + 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 087/128] 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 088/128] 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 089/128] 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 090/128] 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 091/128] 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 092/128] 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 083/128] 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 084/128] 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 085/128] 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 080/128] 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 081/128] 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 082/128] 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 086/128] 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 093/128] 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 094/128] 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 095/128] 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 096/128] 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 097/128] 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 100/128] 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 101/128] 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 102/128] 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 103/128] 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 104/128] 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 105/128] 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 106/128] 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 107/128] 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 108/128] 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 109/128] 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 110/128] 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 111/128] 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 112/128] 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 113/128] 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 114/128] 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 098/128] 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 099/128] 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 115/128] 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 0f58368d5d8215387e28bc8d6456baa47a6da8b5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 11 Apr 2023 10:13:15 +0200 Subject: [PATCH 116/128] 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 117/128] 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 118/128] 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 119/128] 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 120/128] 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 121/128] 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 122/128] 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 123/128] 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 124/128] 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 125/128] 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 126/128] 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 127/128] 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 28c625dc6b286835c09e5660e1b83232131c3fbf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 12 Apr 2023 03:38:25 +0200 Subject: [PATCH 128/128] 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 .= '
';