diff --git a/COPYRIGHT b/COPYRIGHT index 7be728f8948..93f4a43fee1 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -51,7 +51,7 @@ JS libraries: Ace 1.4.14 BSD Yes JS library to get code syntaxique coloration in a textarea. ChartJS 3.7.1 MIT License Yes JS library for graph CKEditor 4.18 LGPL-2.1+ Yes Editor WYSIWYG -jQuery 3.6.0 MIT License Yes JS library +jQuery 3.6.4 MIT License Yes JS library jQuery UI 1.13.2 GPL and MIT License Yes JS library plugin UI jQuery select2 4.0.13 GPL and Apache License Yes JS library plugin for sexier multiselect. Warning: 4.0.6+ create troubles without patching css jQuery blockUI 2.70.0 GPL and MIT License Yes JS library plugin blockUI (to use ajax popups) diff --git a/ChangeLog b/ChangeLog index 900dff4a9ab..ce8c34636f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,7 +24,56 @@ Following changes may create regressions for some external modules, but were nec ***** ChangeLog for 17.0.1 compared to 17.0.0 ***** -TODO +FIX: 17.0 PHP Warning invalid argument supplied for foreach +FIX: #[23799] - External users are not able to create events - correction +FIX: #23966 Error "Param dbt_keyfield is required but not defined +FIX: #24138 Fix box_birthdays SQL for postgres +FIX: #24201 Upload of external module fails to copy from incorrectly generated temp source dir +FIX: #24240 Dolibarr V17.0.0 PHP8 fatal error +FIX: accountancy lettering: better error management +FIX: accountancy lettering: correctly calculated number of lettering operations done +FIX: accountancy lettering: error management and prevention +FIX: accountancy lettering: prevent null results when fetching link with payments +FIX: action delete card fac rec +FIX: Add bookmark with search fields that are arrays (backport 4157263cb898f1847cfcfc22dee6007c01b13a4d) +FIX: Add missing hook on LibStatut +FIX: Add more context for selectForFormsListWhere Hook +FIX: Autofill / clear qty in inventory page +FIX: avoid php8 warnings +FIX: avoid phpunit error +FIX: can not show all csv fields (a reason for that ?) +FIX: change date on select date input when prefix is used +FIX: dol_textishtml() function +FIX: expense report accountancy: sql syntax error when performing automatic linking +FIX: Extrafields in Notes to unify with orders or invoices. +FIX: fatal error when margin enable (missing check on element), fix User::hasRight() when checking a margin right +FIX: feedbacks +FIX: FILTER_VALIDATE_EMAIL param is not a string +FIX: #24298 No error or 0.00 instead of NULL in database anymore when emptying an extrafield of type price on a propal card +FIX: full group by handle +FIX: holiday counter massaction: ErrorBadValueForParamNotAString and PHP 8 warning when no approval user right +FIX: installation superadmin creation: PHP 8 warning +FIX: invoices order on sells journal +FIX: it was not possible to update extrafields of expedition lines with batch without editing batch value +FIX: limit after order in get objects in category +FIX: method dolGetGlobalString not defined with saphir +FIX: missing column default workstation +FIX: missing drop foreign key before modify field +FIX: missing "multidir_output" for project sharing (Multicompany) +FIX: missing protection on ajax public ticket page for valid email +FIX: ODT management inverted between purchase invoice and order +FIX: PDF Espadon => display extrafields +FIX: PDF Espadon Expedition : notes and tracking number +FIX: Phpunit Rename WebsiteTest.class.php to WebsiteTest.php +FIX: project referent elements list: conf to hide tasks was flipped +FIX: Protection on agenda view for a thirdparty id that does not exist +FIX: search_project_user +FIX: societe list: regression to redirection to customer card when single result of search filters +FIX: SQL error "unknown column p.fk_soc" because ANSI-92 joins take precedence over ANSI-89 joins +FIX: task have the same entity of project +FIX: token error when closing ticket from public interface +FIX: Warning on purchase order + Property fk_commande not defined + ***** ChangeLog for 17.0.0 compared to 16.0.0 ***** diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index cfcdf81a9b9..9ee0de6c055 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -996,8 +996,6 @@ class AdherentType extends CommonObject { global $langs, $user; - $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']); - $return = '
'; $return .= '
'; $return .= ''; @@ -1005,9 +1003,12 @@ class AdherentType extends CommonObject $return .= ''; $return .= '
'; $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; - $return .= ''; + + //$selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']); + //$return .= ''; + if ($user->rights->adherent->configurer) { - $return .= 'ref.'">'.img_edit().''; + $return .= 'ref).'">'.img_edit().''; } else { $return .= ' '; } diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index f4208f590fd..35d4015e270 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -424,10 +424,10 @@ if ($search_filter == 'waitingsubscription') { $sql .= " AND (datefin IS NULL AND t.subscription = '1')"; } if ($search_filter == 'uptodate') { - $sql .= " AND (datefin >= '".$db->idate($now)."' OR t.subscription = '0')"; + $sql .= " AND (datefin >= '".$db->idate($now)."' OR (datefin IS NULL AND t.subscription = '0'))"; } if ($search_filter == 'outofdate') { - $sql .= " AND (datefin < '".$db->idate($now)."' AND t.subscription = '1')"; + $sql .= " AND (datefin < '".$db->idate($now)."')"; } if ($search_status != '') { // Peut valoir un nombre ou liste de nombre separes par virgules @@ -516,6 +516,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { } $db->free($resql); } +//print $sql; // Complete request and execute it with limit $sql .= $db->order($sortfield, $sortorder); diff --git a/htdocs/adherents/subscription/card.php b/htdocs/adherents/subscription/card.php index b97fac372e5..d6ce54a20e9 100644 --- a/htdocs/adherents/subscription/card.php +++ b/htdocs/adherents/subscription/card.php @@ -352,10 +352,10 @@ if ($rowid && $action != 'edit') { print '
'; if ($user->hasRight('adherent', 'cotisation', 'creer')) { - if (!empty($bankline->rappro)) { + if (!empty($bankline->rappro) || empty($bankline)) { print '"; } else { - print '"; + print '"; } } diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index 4cd21775ae7..10b711e943f 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -32,13 +32,16 @@ require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $langs->loadLangs(array("members", "companies")); -$action = GETPOST('action', 'aZ09'); -$massaction = GETPOST('massaction', 'alpha'); -$confirm = GETPOST('confirm', 'alpha'); -$toselect = GETPOST('toselect', 'array'); -$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'subscriptionlist'; // To manage different context of search -$mode = GETPOST('mode', 'alpha'); - +$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'create'/'add', 'edit'/'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? +$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation +$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button +$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') +$mode = GETPOST('mode', 'aZ'); // The output mode ('list', 'kanban', 'hierarchy', 'calendar', ...) $statut = (GETPOSTISSET("statut") ?GETPOST("statut", "alpha") : 1); $search_ref = GETPOST('search_ref', 'alpha'); @@ -49,18 +52,19 @@ $search_login = GETPOST('search_login', 'alpha'); $search_note = GETPOST('search_note', 'alpha'); $search_account = GETPOST('search_account', 'int'); $search_amount = GETPOST('search_amount', 'alpha'); -$optioncss = GETPOST('optioncss', 'alpha'); -$sall = ''; +$search_all = ''; $date_select = GETPOST("date_select", 'alpha'); -$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; +// Load variable for pagination +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); -if (empty($page) || $page == -1) { +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { + // If $page is not defined, or '' or -1 or if we click on clear filters $page = 0; -} // If $page is not defined, or '' or -1 +} $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; @@ -71,13 +75,12 @@ if (!$sortfield) { $sortfield = "c.dateadh"; } +// Initialize technical objects $object = new Subscription($db); - -// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context -$hookmanager->initHooks(array('subscriptionlist')); $extrafields = new ExtraFields($db); +$hookmanager->initHooks(array('subscriptionlist')); -// 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_'); @@ -106,13 +109,16 @@ $arrayfields = array( // Security check $result = restrictedArea($user, 'adherent', '', '', 'cotisation'); +$permissiontodelete = $user->hasRight('adherent', 'cotisation', 'creer'); + /* * Actions */ if (GETPOST('cancel', 'alpha')) { - $action = 'list'; $massaction = ''; + $action = 'list'; + $massaction = ''; } if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; @@ -141,6 +147,16 @@ if (empty($reshook)) { $toselect = array(); $search_array_options = array(); } + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') + || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) { + $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation + } + + // Mass actions + $objectclass = 'Subscription'; + $objectlabel = 'Subscription'; + $uploaddir = $conf->adherent->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } @@ -162,6 +178,20 @@ $sql .= " c.rowid as crowid, c.fk_type, c.subscription,"; $sql .= " c.dateadh, c.datef, c.datec as date_creation, c.tms as date_update,"; $sql .= " c.fk_bank as bank, c.note,"; $sql .= " b.fk_account"; +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : ''); + } +} +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +$sql = preg_replace('/,\s*$/', '', $sql); + +$sqlfields = $sql; // $sql fields to remove for count total + $sql .= " FROM ".MAIN_DB_PREFIX."adherent as d"; $sql .= " JOIN ".MAIN_DB_PREFIX."subscription as c on d.rowid = c.fk_adherent"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."adherent_extrafields as ef on (d.rowid = ef.fk_object)"; @@ -199,60 +229,72 @@ if ($search_account > 0) { if ($search_amount) { $sql .= natural_search('c.subscription', $search_amount, 1); } - +if ($search_all) { + $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +} // Add where from extra fields 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; -$sql .= $db->order($sortfield, $sortorder); - -// Count total nb of records with no order and no limits +// Count total nb of records $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $resql = $db->query($sql); + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); + $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); if ($resql) { - $nbtotalofrecords = $db->num_rows($resql); + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; } else { dol_print_error($db); } - if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 + + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } + $db->free($resql); } -// Add limit -$sql .= $db->plimit($limit + 1, $offset); -$result = $db->query($sql); -if (!$result) { +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); +} + +$resql = $db->query($sql); +if (!$resql) { dol_print_error($db); exit; } -$num = $db->num_rows($result); +$num = $db->num_rows($resql); -$arrayofselected = is_array($toselect) ? $toselect : array(); -if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $sall) { +// Direct jump if only one record found +if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) { $obj = $db->fetch_object($resql); $id = $obj->rowid; header("Location: ".DOL_URL_ROOT.'/adherents/subscription/card.php?id='.$id); exit; } +// Output page +// -------------------------------------------------------------------- + $title = $langs->trans("Subscriptions"); if (!empty($date_select)) { $title .= ' ('.$langs->trans("Year").' '.$date_select.')'; } - $help_url = 'EN:Module_Foundations|FR:Module_Adhérents|ES:Módulo_Miembros|DE:Modul_Mitglieder'; + llxHeader('', $title, $help_url); -$i = 0; +$arrayofselected = is_array($toselect) ? $toselect : array(); $param = ''; if (!empty($mode)) { @@ -262,7 +304,7 @@ if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } if ($limit > 0 && $limit != $conf->liste_limit) { - $param .= '&limit='.urlencode($limit); + $param .= '&limit='.((int) $limit); } if ($statut != '') { $param .= "&statut=".urlencode($statut); @@ -290,27 +332,25 @@ if ($optioncss != '') { } // 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( //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), ); -//if ($user->hasRight('adherent', 'supprimer')) $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); -if (in_array($massaction, array('presend', 'predelete'))) { +if (!empty($permissiontodelete)) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +} +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { $arrayofmassactions = array(); } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); -$newcardbutton = ''; -$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss'=>'reposition')); -$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition')); - -if ($user->hasRight('adherent', 'cotisation', 'creer')) { - $newcardbutton .= dolGetButtonTitle($langs->trans('NewSubscription'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/adherents/list.php?status=-1,1'); -} - -print '
'; +print ''."\n"; if ($optioncss != '') { print ''; } @@ -319,10 +359,19 @@ print ''; print ''; print ''; +print ''; print ''; print ''; +print ''; print ''; +$newcardbutton = ''; +$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss'=>'reposition')); +$newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition')); +if ($user->hasRight('adherent', 'cotisation', 'creer')) { + $newcardbutton .= dolGetButtonTitleSeparator(); + $newcardbutton .= dolGetButtonTitle($langs->trans('NewSubscription'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/adherents/list.php?status=-1,1'); +} print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $subscription->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -332,30 +381,51 @@ $objecttmp = new Subscription($db); $trackid = 'sub'.$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 = ''; +/*$moreforfilter.='
'; + $moreforfilter.= $langs->trans('MyFilter') . ': '; + $moreforfilter.= '
';*/ -$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields -if ($massactionbutton) { - $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +if (empty($reshook)) { + $moreforfilter .= $hookmanager->resPrint; +} else { + $moreforfilter = $hookmanager->resPrint; } -print '
'; +if (!empty($moreforfilter)) { + print '
'; + print $moreforfilter; + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + print '
'; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$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 print ''."\n"; - -// Line for filters fields +// Fields title search +// -------------------------------------------------------------------- print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; @@ -423,7 +493,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); // 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['c.datec']['checked'])) { @@ -438,55 +508,71 @@ if (!empty($arrayfields['c.tms']['checked'])) { // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; } -print "\n"; +print ''."\n"; +$totalarray = array(); +$totalarray['nbfield'] = 0; +// Fields title label +// -------------------------------------------------------------------- print ''; +// Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], '', '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + $totalarray['nbfield']++; } if (!empty($arrayfields['d.ref']['checked'])) { print_liste_field_titre($arrayfields['d.ref']['label'], $_SERVER["PHP_SELF"], "c.rowid", $param, "", "", $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['d.fk_type']['checked'])) { print_liste_field_titre($arrayfields['d.fk_type']['label'], $_SERVER["PHP_SELF"], "c.fk_type", $param, "", "", $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['d.lastname']['checked'])) { print_liste_field_titre($arrayfields['d.lastname']['label'], $_SERVER["PHP_SELF"], "d.lastname", $param, "", "", $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['d.firstname']['checked'])) { print_liste_field_titre($arrayfields['d.firstname']['label'], $_SERVER["PHP_SELF"], "d.firstname", $param, "", "", $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['d.login']['checked'])) { print_liste_field_titre($arrayfields['d.login']['label'], $_SERVER["PHP_SELF"], "d.login", $param, "", "", $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['t.libelle']['checked'])) { print_liste_field_titre($arrayfields['t.libelle']['label'], $_SERVER["PHP_SELF"], "c.note", $param, "", '', $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['d.bank']['checked'])) { print_liste_field_titre($arrayfields['d.bank']['label'], $_SERVER["PHP_SELF"], "b.fk_account", $param, "", "", $sortfield, $sortorder); + $totalarray['nbfield']++; } if (!empty($arrayfields['c.dateadh']['checked'])) { print_liste_field_titre($arrayfields['c.dateadh']['label'], $_SERVER["PHP_SELF"], "c.dateadh", $param, "", '', $sortfield, $sortorder, 'center nowraponall '); + $totalarray['nbfield']++; } if (!empty($arrayfields['c.datef']['checked'])) { print_liste_field_titre($arrayfields['c.datef']['label'], $_SERVER["PHP_SELF"], "c.datef", $param, "", '', $sortfield, $sortorder, 'center nowraponall '); + $totalarray['nbfield']++; } if (!empty($arrayfields['d.amount']['checked'])) { print_liste_field_titre($arrayfields['d.amount']['label'], $_SERVER["PHP_SELF"], "c.subscription", $param, "", '', $sortfield, $sortorder, 'right '); + $totalarray['nbfield']++; } // Extra fields 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); // 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['c.datec']['checked'])) { print_liste_field_titre($arrayfields['c.datec']['label'], $_SERVER["PHP_SELF"], "c.datec", "", $param, 'align="center" class="nowrap"', $sortfield, $sortorder); @@ -494,17 +580,25 @@ if (!empty($arrayfields['c.datec']['checked'])) { if (!empty($arrayfields['c.tms']['checked'])) { print_liste_field_titre($arrayfields['c.tms']['label'], $_SERVER["PHP_SELF"], "c.tms", "", $param, 'align="center" class="nowrap"', $sortfield, $sortorder); } +// Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], '', '', '', 'align="center"', $sortfield, $sortorder, 'maxwidthsearch '); + print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; + $totalarray['nbfield']++; } -print "\n"; - +print ''."\n"; +// Loop on record +// -------------------------------------------------------------------- +$i = 0; +$savnbfield = $totalarray['nbfield']; $totalarray = array(); $totalarray['nbfield'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); while ($i < $imaxinloop) { - $obj = $db->fetch_object($result); + $obj = $db->fetch_object($resql); + if (empty($obj)) { + break; // Should not happen + } $subscription->ref = $obj->crowid; $subscription->id = $obj->crowid; @@ -532,9 +626,16 @@ while ($i < $imaxinloop) { if ($mode == 'kanban') { if ($i == 0) { - print ''; } } else { - print ''; + // Show here line of result + $j = 0; + print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print '\n"; + + print ''."\n"; } $i++; } @@ -720,19 +824,19 @@ if ($num == 0) { $colspan++; } } - print ''; + print ''; } $db->free($resql); -$parameters = array('sql' => $sql); -$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook +$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 "
'; + print ''; $searchpicto = $form->showFilterButtons('left'); print $searchpicto; print ''; + print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; print '
'; + print '
'; print '
'; } + // 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; + } + } //fetch informations needs on this mode $subscription->fk_adherent = $adherent->getNomUrl(1); @@ -552,10 +653,12 @@ while ($i < $imaxinloop) { print '
'; + 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->crowid, $arrayofselected)) { @@ -690,7 +793,7 @@ while ($i < $imaxinloop) { } // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; + 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->crowid, $arrayofselected)) { @@ -703,7 +806,8 @@ while ($i < $imaxinloop) { $totalarray['nbfield']++; } } - print "
'.$langs->trans("NoRecordFound").'
'.$langs->trans("NoRecordFound").'
"; -print '
'; -print ''; +print ''."\n"; +print '
'."\n"; +print ''."\n"; // End of page llxFooter(); diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 8a4c189766f..394a17433f4 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -433,7 +433,7 @@ if ($action == 'create') { print $form->selectarray("morphy", $morphys, GETPOSTISSET("morphy") ? GETPOST("morphy", 'aZ09') : 'morphy'); print ""; - print ''.$langs->trans("SubscriptionRequired").''; + print ''.$form->textwithpicto($langs->trans("SubscriptionRequired"), $langs->trans("SubscriptionRequiredDesc")).''; print $form->selectyesno("subscription", 1, 1); print ''; @@ -509,7 +509,7 @@ if ($rowid > 0) { print ''.$langs->trans("MembersNature").''.$object->getmorphylib($object->morphy).''; print ''; - print ''.$langs->trans("SubscriptionRequired").''; + print ''.$form->textwithpicto($langs->trans("SubscriptionRequired"), $langs->trans("SubscriptionRequiredDesc")).''; print yn($object->subscription); print ''; diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 054fa0bec31..880589fb5b1 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -684,18 +684,18 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; print '
'; - print '

'; + print '


'; // Operations - print '
'; - print ''; + print '
'; + print '
'; print ''; print ''; print ''; $arrayoftypes = array( - 'loadthirdparty' => $langs->trans('LoadThirdPartyFromName', $langs->transnoentities("ThirdPartyName")), - 'loadandcreatethirdparty' => $langs->trans('LoadThirdPartyFromNameOrCreate', $langs->transnoentities("ThirdPartyName")), + 'loadthirdparty' => $langs->trans('LoadThirdPartyFromName', $langs->transnoentities("ThirdPartyName").'/'.$langs->transnoentities("AliasNameShort").'/'.$langs->transnoentities("Email").'/'.$langs->transnoentities("ID")), + 'loadandcreatethirdparty' => $langs->trans('LoadThirdPartyFromNameOrCreate', $langs->transnoentities("ThirdPartyName").'/'.$langs->transnoentities("AliasNameShort").'/'.$langs->transnoentities("Email").'/'.$langs->transnoentities("ID")), 'recordjoinpiece' => 'AttachJoinedDocumentsToObject', 'recordevent' => 'RecordEvent' ); diff --git a/htdocs/bom/bom_agenda.php b/htdocs/bom/bom_agenda.php index d22f457df85..ddd57d34e76 100644 --- a/htdocs/bom/bom_agenda.php +++ b/htdocs/bom/bom_agenda.php @@ -92,7 +92,7 @@ if ($id > 0 || !empty($ref)) { //if ($user->socid > 0) accessforbidden(); //if ($user->socid > 0) $socid = $user->socid; $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); -restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft); +restrictedArea($user, 'bom', $object->id, $object->table_element, '', '', 'rowid', $isdraft); /* diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 33e562a8a20..e27cd0a2e1c 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -84,7 +84,7 @@ if ($object->id > 0) { //if ($user->socid > 0) accessforbidden(); //if ($user->socid > 0) $socid = $user->socid; $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); -$result = restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft); +$result = restrictedArea($user, 'bom', $object->id, $object->table_element, '', '', 'rowid', $isdraft); // Permissions $permissionnote = $user->hasRight('bom', 'write'); // Used by the include of actions_setnotes.inc.php diff --git a/htdocs/bom/bom_document.php b/htdocs/bom/bom_document.php index 03b9f416d43..88fbdde11c7 100644 --- a/htdocs/bom/bom_document.php +++ b/htdocs/bom/bom_document.php @@ -83,7 +83,7 @@ if ($id > 0 || !empty($ref)) { //if ($user->socid > 0) accessforbidden(); //if ($user->socid > 0) $socid = $user->socid; $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); -restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft); +restrictedArea($user, 'bom', $object->id, $object->table_element, '', '', 'rowid', $isdraft); $permissiontoadd = $user->hasRight('bom', 'write'); // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php diff --git a/htdocs/bom/bom_net_needs.php b/htdocs/bom/bom_net_needs.php index 56683e82338..f0e993d6eea 100644 --- a/htdocs/bom/bom_net_needs.php +++ b/htdocs/bom/bom_net_needs.php @@ -81,7 +81,7 @@ if ($object->id > 0) { //if ($user->socid > 0) accessforbidden(); //if ($user->socid > 0) $socid = $user->socid; $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); -$result = restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft); +$result = restrictedArea($user, 'bom', $object->id, $object->table_element, '', '', 'rowid', $isdraft); // Permissions $permissionnote = $user->hasRight('bom', 'write'); // Used by the include of actions_setnotes.inc.php diff --git a/htdocs/bom/bom_note.php b/htdocs/bom/bom_note.php index 10c64a1b104..188c34c8c05 100644 --- a/htdocs/bom/bom_note.php +++ b/htdocs/bom/bom_note.php @@ -67,7 +67,7 @@ $permissionnote = $user->hasRight('bom', 'write'); // Used by the include of act //if ($user->socid > 0) accessforbidden(); //if ($user->socid > 0) $socid = $user->socid; $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); -restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft); +restrictedArea($user, 'bom', $object->id, $object->table_element, '', '', 'rowid', $isdraft); /* diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index c665166b0af..27b9a05181b 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -893,19 +893,19 @@ if ($search_status <> '') { if ($search_status == 1 && empty($conf->expedition->enabled)) { $sql .= ' AND c.fk_statut IN (1,2)'; // If module expedition disabled, we include order with status 'sending in process' into 'validated' } else { - $sql .= ' AND c.fk_statut = '.((int) $search_status); // brouillon, validee, en cours, annulee + $sql .= ' AND c.fk_statut = '.((int) $search_status); // draft, validated, in process or canceled } } - if ($search_status == -2) { // To process + if ($search_status == -2) { // "validated + in process" //$sql.= ' AND c.fk_statut IN (1,2,3) AND c.facture = 0'; - $sql .= " AND ((c.fk_statut IN (1,2)) OR (c.fk_statut = 3 AND c.facture = 0))"; // If status is 2 and facture=1, it must be selected + $sql .= " AND (c.fk_statut IN (1,2))"; } - if ($search_status == -3) { // To bill + if ($search_status == -3) { // "validated + in process + delivered" //$sql.= ' AND c.fk_statut in (1,2,3)'; //$sql.= ' AND c.facture = 0'; // invoice not created - $sql .= ' AND ((c.fk_statut IN (1,2)) OR (c.fk_statut = 3 AND c.facture = 0))'; // validated, in process or closed but not billed + $sql .= ' AND (c.fk_statut IN (1,2,3))'; // validated, in process or closed } - if ($search_status == -4) { // "validate and in progress" + if ($search_status == -4) { // "validate + in progress" $sql .= ' AND (c.fk_statut IN (1,2))'; // validated, in process } } diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 4b17f3baab0..f9a665640cd 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -1463,6 +1463,7 @@ class Account extends CommonObject public function getNomUrl($withpicto = 0, $mode = '', $option = '', $save_lastsearch_value = -1, $notooltip = 0) { global $conf, $langs, $user; + include_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php'; $result = ''; @@ -1504,7 +1505,7 @@ class Account extends CommonObject } } - $linkstart = 'trans("WithdrawalsLine"); if ($type == 'bank-transfer') { @@ -318,7 +324,11 @@ if ($id) { print ''.$obj->ref."\n"; } - print '\n"; print '\n"; diff --git a/htdocs/contact/consumption.php b/htdocs/contact/consumption.php index 93acb2ab463..8efae5a836d 100644 --- a/htdocs/contact/consumption.php +++ b/htdocs/contact/consumption.php @@ -377,7 +377,7 @@ if ($sql_select) { $num = $db->num_rows($resql); - $param = "&socid=".urlencode($socid)."&type_element=".urlencode($type_element); + $param = "&socid=".urlencode($socid)."&type_element=".urlencode($type_element)."&id=".urlencode($id); if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index fd6e9aa6efb..73a8b86ea47 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1124,6 +1124,9 @@ class ExtraFields continue; } + $valarray = explode('|', $val); + $val = $valarray[0]; + if ($langfile && $val) { $options[$okey] = $langs->trans($val); } else { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 170b400b2a0..cf512d5f173 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8550,7 +8550,7 @@ class Form $tmpvalue = $value['label']; $tmpcolor = $value['color']; $tmppicto = $value['picto']; - $tmplabelhtml = $value['labelhtml']; + $tmplabelhtml = !empty($value['labelhtml']) ? $value['labelhtml'] : ''; } $newval = ($translate ? $langs->trans($tmpvalue) : $tmpvalue); $newval = ($key_in_label ? $tmpkey . ' - ' . $newval : $newval); diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index 8c4d958abac..d721ec78873 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -1292,21 +1292,4 @@ $(document).ready(function() { }); -/* - * Hacky fix for a bug in select2 with jQuery 3.6.0's new nested-focus "protection" - * see: https://github.com/select2/select2/issues/5993 - * see: https://github.com/jquery/jquery/issues/4382 - * - * TODO: Recheck with the select2 GH issue and remove once this is fixed on their side - */ -$(document).on('select2:open', () => { - console.log("Execute the focus (click on combo or use space when on component"); - let allFound = document.querySelectorAll('.select2-container--open .select2-search__field'); - $(this).one('mouseup keyup',()=>{ - setTimeout(()=>{ - allFound[allFound.length - 1].focus(); - },0); - }); -}); - // End of lib_head.js.php diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 29b8a15564d..e2e10a8de48 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -1380,7 +1380,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '', $showuserl // Birthday if (!empty($arrayfields['t.birthday']['checked'])) { print ''; } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index c65d9e551ea..d0c2d9998b4 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2976,7 +2976,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } $original_file = $conf->commande->multidir_output[$entity].'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('order').")"; - } elseif ($modulepart == 'project' && !empty($conf->project->dir_output)) { + } elseif ($modulepart == 'project' && !empty($conf->project->multidir_output[$entity])) { // Wrapping pour les projets if ($fuser->hasRight('projet', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; @@ -2988,9 +2988,9 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $accessallowed = checkUserAccessToObject($user, array('projet'), $tmpproject->id, 'projet&project', '', '', 'rowid', ''); } } - $original_file = $conf->project->dir_output.'/'.$original_file; + $original_file = $conf->project->multidir_output[$entity].'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")"; - } elseif ($modulepart == 'project_task' && !empty($conf->project->dir_output)) { + } elseif ($modulepart == 'project_task' && !empty($conf->project->multidir_output[$entity])) { if ($fuser->hasRight('projet', $lire) || preg_match('/^specimen/i', $original_file)) { $accessallowed = 1; // If we known $id of project, call checkUserAccessToObject to check permission on properties and contact of project @@ -3001,7 +3001,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $accessallowed = checkUserAccessToObject($user, array('projet_task'), $tmptask->id, 'projet_task&project', '', '', 'rowid', ''); } } - $original_file = $conf->project->dir_output.'/'.$original_file; + $original_file = $conf->project->multidir_output[$entity].'/'.$original_file; $sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$db->escape($refname)."' AND entity IN (".getEntity('project').")"; } elseif (($modulepart == 'commande_fournisseur' || $modulepart == 'order_supplier') && !empty($conf->fournisseur->commande->dir_output)) { // Wrapping pour les commandes fournisseurs diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index bdeb1994ba3..2da236006c0 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8049,6 +8049,10 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, } if (is_object($object) && $object->element == 'member') { $typeforonlinepayment = 'member'; + $amounttouse = 0; + if (!empty($object->last_subscription_amount)) { + $amounttouse = $object->last_subscription_amount; + } } if (is_object($object) && $object->element == 'contrat') { $typeforonlinepayment = 'contract'; @@ -8056,7 +8060,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, if (is_object($object) && $object->element == 'fichinter') { $typeforonlinepayment = 'ficheinter'; } - $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $substitutionarray['__REF__']); + + $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $substitutionarray['__REF__'], $amounttouse); $paymenturl = $url; } diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 2a38906e4de..9baccc8e9fc 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -290,7 +290,7 @@ function project_prepare_head(Project $project, $moreparam = '') } else { require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; - $upload_dir = $conf->project->dir_output."/".dol_sanitizeFileName($project->ref); + $upload_dir = $conf->project->multidir_output[$project->entity]."/".dol_sanitizeFileName($project->ref); $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); $nbLinks = Link::count($db, $project->element, $project->id); $totalAttached = $nbFiles + $nbLinks; @@ -418,7 +418,7 @@ function task_prepare_head($object) } $head[$h][0] = DOL_URL_ROOT.'/projet/tasks/document.php?id='.$object->id.(GETPOST('withproject') ? '&withproject=1' : ''); - $filesdir = $conf->project->dir_output."/".dol_sanitizeFileName($object->project->ref).'/'.dol_sanitizeFileName($object->ref); + $filesdir = $conf->project->multidir_output[$object->entity]."/".dol_sanitizeFileName($object->project->ref).'/'.dol_sanitizeFileName($object->ref); include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; $nbFiles = count(dol_dir_list($filesdir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 710eab4d878..3c9ca5e34d9 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -402,7 +402,6 @@ function restrictedArea(User $user, $features, $object = 0, $tableandshare = '', } if ($features == 'fournisseur') { // When vendor invoice and pruchase order are into module 'fournisseur' $features = 'fournisseur'; - $feature2 = ''; if ($object->element == 'invoice_supplier') { $feature2 = 'facture'; } elseif ($object->element == 'order_supplier') { diff --git a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php index d95d9912c2b..f6c648f2ff0 100644 --- a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php @@ -394,20 +394,19 @@ class pdf_espadon extends ModelePdfExpedition $label .= $object->tracking_url; } - $height_trackingnumber += 6; + $height_trackingnumber += 4; $pdf->SetFont('', 'B', $default_font_size - 2); $pdf->writeHTMLCell(60, $height_trackingnumber, $this->posxdesc - 1, $tab_top_alt, $label, 0, 1, false, true, 'L'); - - $tab_top = $pdf->GetY(); } } + $tab_top = $pdf->GetY(); } // Notes $pagenb = $pdf->getPage(); if (!empty($notetoshow) || !empty($object->tracking_number)) { - $tab_top -= 2; + $tab_top -= 1; $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite; $pageposbeforenote = $pagenb; @@ -476,7 +475,7 @@ class pdf_espadon extends ModelePdfExpedition $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter) + $height_trackingnumber + 1; $tab_top_newpage = $tab_topbeforetrackingnumber; } - $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1); + $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 2); } else { if (empty($height_trackingnumber)) { $height_note = $this->page_hauteur - ($tab_top + $heightforfooter); @@ -484,7 +483,7 @@ class pdf_espadon extends ModelePdfExpedition $height_note = $this->page_hauteur - ($tab_top + $heightforfooter)+ $height_trackingnumber + 1; $tab_top = $tab_topbeforetrackingnumber; } - $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1); + $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2); } // Add footer @@ -510,7 +509,7 @@ class pdf_espadon extends ModelePdfExpedition $height_note = $posyafter - $tab_top + $height_trackingnumber + 1; $tab_top = $tab_topbeforetrackingnumber; } - $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 1); + $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2); if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index e62f2b0e07e..a6fc98ffc08 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -748,6 +748,32 @@ class modProduct extends DolibarrModules $this->import_updatekeys_array[$r] = array_merge($this->import_updatekeys_array[$r], array('p.barcode'=>'BarCode')); //only show/allow barcode as update key if Barcode module enabled } + if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { + // Import products limit and desired stock by product and warehouse + $r++; + $this->import_code[$r] = $this->rights_class.'_stock_by_warehouse'; + $this->import_label[$r] = "ProductStockWarehouse"; // Translation key + $this->import_icon[$r] = $this->picto; + $this->import_entities_array[$r] = array(); // We define here only fields that use another icon that the one defined into import_icon + $this->import_tables_array[$r] = array('pwp'=>MAIN_DB_PREFIX.'product_warehouse_properties'); + $this->import_fields_array[$r] = array('pwp.fk_product'=>"Product*", + 'pwp.fk_entrepot'=>"Warehouse*", 'pwp.seuil_stock_alerte'=>"StockLimit", + 'pwp.desiredstock'=>"DesiredStock"); + $this->import_regex_array[$r] = array( + 'pwp.fk_product' => 'rowid@'.MAIN_DB_PREFIX.'product', + 'pwp.fk_entrepot' => 'rowid@'.MAIN_DB_PREFIX.'entrepot', + ); + $this->import_convertvalue_array[$r] = array( + 'pwp.fk_product'=>array('rule'=>'fetchidfromref', 'classfile'=>'/product/class/product.class.php', 'class'=>'Product', 'method'=>'fetch', 'element'=>'Product') + ,'pwp.fk_entrepot'=>array('rule'=>'fetchidfromref', 'classfile'=>'/product/stock/class/entrepot.class.php', 'class'=>'Entrepot', 'method'=>'fetch', 'element'=>'Entrepot') + ); + $this->import_examplevalues_array[$r] = array('pwp.fk_product'=>"ref:PRODUCT_REF or id:123456", + 'pwp.fk_entrepot'=>"ref:WAREHOUSE_REF or id:123456", + 'pwp.seuil_stock_alerte'=>"100", + 'pwp.desiredstock'=>"110" + ); + $this->import_updatekeys_array[$r] = array('pwp.fk_product'=>'Product', 'pwp.fk_entrepot'=>'Warehouse'); + } if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) { // Import suppliers prices (note: this code is duplicated in module Service) diff --git a/htdocs/core/modules/project/doc/pdf_baleine.modules.php b/htdocs/core/modules/project/doc/pdf_baleine.modules.php index 2bfd73757c9..06f6e400b75 100644 --- a/htdocs/core/modules/project/doc/pdf_baleine.modules.php +++ b/htdocs/core/modules/project/doc/pdf_baleine.modules.php @@ -195,11 +195,11 @@ class pdf_baleine extends ModelePDFProjects // Load traductions files required by page $outputlangs->loadLangs(array("main", "dict", "companies", "projects")); - if ($conf->project->dir_output) { + if ($conf->project->multidir_output[$object->entity]) { //$nblines = count($object->lines); // This is set later with array of tasks $objectref = dol_sanitizeFileName($object->ref); - $dir = $conf->project->dir_output; + $dir = $conf->project->multidir_output[$object->entity]; if (!preg_match('/specimen/i', $objectref)) { $dir .= "/".$objectref; } diff --git a/htdocs/core/modules/project/doc/pdf_beluga.modules.php b/htdocs/core/modules/project/doc/pdf_beluga.modules.php index c1365fde536..ba175dc7c52 100644 --- a/htdocs/core/modules/project/doc/pdf_beluga.modules.php +++ b/htdocs/core/modules/project/doc/pdf_beluga.modules.php @@ -242,11 +242,11 @@ class pdf_beluga extends ModelePDFProjects // Load traductions files required by page $outputlangs->loadLangs(array("main", "dict", "companies", "projects")); - if ($conf->project->dir_output) { + if ($conf->project->multidir_output[$object->entity]) { //$nblines = count($object->lines); // This is set later with array of tasks $objectref = dol_sanitizeFileName($object->ref); - $dir = $conf->project->dir_output; + $dir = $conf->project->multidir_output[$object->entity]; if (!preg_match('/specimen/i', $objectref)) { $dir .= "/".$objectref; } diff --git a/htdocs/core/modules/project/doc/pdf_timespent.modules.php b/htdocs/core/modules/project/doc/pdf_timespent.modules.php index c5aa80d5748..31a8127f733 100644 --- a/htdocs/core/modules/project/doc/pdf_timespent.modules.php +++ b/htdocs/core/modules/project/doc/pdf_timespent.modules.php @@ -195,11 +195,11 @@ class pdf_timespent extends ModelePDFProjects // Load traductions files required by page $outputlangs->loadLangs(array("main", "dict", "companies", "projects")); - if ($conf->project->dir_output) { + if ($conf->project->multidir_output[$object->entity]) { //$nblines = count($object->lines); // This is set later with array of tasks $objectref = dol_sanitizeFileName($object->ref); - $dir = $conf->project->dir_output; + $dir = $conf->project->multidir_output[$object->entity]; if (!preg_match('/specimen/i', $objectref)) { $dir .= "/".$objectref; } diff --git a/htdocs/core/tpl/admin_extrafields_add.tpl.php b/htdocs/core/tpl/admin_extrafields_add.tpl.php index 00dec927f9e..5404f831a65 100644 --- a/htdocs/core/tpl/admin_extrafields_add.tpl.php +++ b/htdocs/core/tpl/admin_extrafields_add.tpl.php @@ -209,7 +209,7 @@ $listofexamplesforlink = 'Societe:societe/class/societe.class.php
Contact:con - + @@ -220,7 +220,7 @@ $listofexamplesforlink = 'Societe:societe/class/societe.class.php
Contact:con - +
'.img_picto('', 'technic', 'class="pictofixedwidth"').$form->textwithpicto($langs->trans("EmailcollectorOperations"), $langs->trans("EmailcollectorOperationsDesc")).'
'; + if ($type == 'bank-transfer') { + print ''; + } else { + print ''; + } print img_object($langs->trans("ShowCompany"), "company").' '.$obj->name."'.price($obj->total_ttc)."'; - print dol_print_date($obj->birthday); + print dol_print_date($db->jdate($obj->birthday)); print '
textwithpicto($langs->trans("DisplayOnPdf"), $langs->trans("DisplayOnPdfDesc")); ?>
trans("Totalizable"); ?>>
trans("Totalizable"); ?>>
textwithpicto($langs->trans("CssOnEdit"), $langs->trans("HelpCssOnEditDesc")); ?>
textwithpicto($langs->trans("HelpOnTooltip"), $langs->trans("HelpOnTooltipDesc")); ?>
trans("AllEntities"); ?>>
trans("AllEntities"); ?>>
diff --git a/htdocs/core/tpl/passwordforgotten.tpl.php b/htdocs/core/tpl/passwordforgotten.tpl.php index 05731dbb408..deec94ee004 100644 --- a/htdocs/core/tpl/passwordforgotten.tpl.php +++ b/htdocs/core/tpl/passwordforgotten.tpl.php @@ -238,21 +238,23 @@ if (!empty($morelogincontent)) { -'; } } else { + print ''; } ?> -

diff --git a/htdocs/core/tpl/passwordreset.tpl.php b/htdocs/core/tpl/passwordreset.tpl.php index ea79ec98180..e3202ff511f 100644 --- a/htdocs/core/tpl/passwordreset.tpl.php +++ b/htdocs/core/tpl/passwordreset.tpl.php @@ -118,7 +118,7 @@ if ($setnewpassword && $username && $passworduidhash) { ?> - + global->MAIN_LOGIN_BACKGROUND) ? '' : ' style="background-size: cover; background-position: center center; background-attachment: fixed; background-repeat: no-repeat; background-image: url(\''.DOL_URL_ROOT.'/viewimage.php?cache=1&noalt=1&modulepart=mycompany&file='.urlencode('logos/'.$conf->global->MAIN_LOGIN_BACKGROUND).'\')"'; ?>> @@ -279,21 +279,23 @@ if (!empty($morelogincontent)) { -'; } } else { + print ''; } ?> -

diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index ffd1dfc3d50..4c4aaab84af 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -948,13 +948,13 @@ class EmailCollector extends CommonObject if (preg_match('/'.$regexstring.'/'.$regexoptions, $sourcestring, $regforval)) { // Overwrite param $tmpproperty $valueextracted = isset($regforval[count($regforval) - 1]) ?trim($regforval[count($regforval) - 1]) : null; - if (strtolower($sourcefield) == 'header') { + if (strtolower($sourcefield) == 'header') { // extract from HEADER if (preg_match('/^options_/', $tmpproperty)) { $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $this->decodeSMTPSubject($valueextracted); } else { $object->$tmpproperty = $this->decodeSMTPSubject($valueextracted); } - } else { + } else { // extract from BODY if (preg_match('/^options_/', $tmpproperty)) { $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $this->decodeSMTPSubject($valueextracted); } else { @@ -1509,7 +1509,7 @@ class EmailCollector extends CommonObject $emailto = $this->decodeSMTPSubject($overview[0]->to); - $operationslog .= '
Process email '.dol_escape_htmltag($iforemailloop)." - References: ".dol_escape_htmltag($headers['References'])." - Subject: ".dol_escape_htmltag($headers['Subject']); + $operationslog .= '
** Process email '.dol_escape_htmltag($iforemailloop)." - References: ".dol_escape_htmltag($headers['References'])." - Subject: ".dol_escape_htmltag($headers['Subject']); dol_syslog("** Process email ".$iforemailloop." References: ".$headers['References']." Subject: ".$headers['Subject']); @@ -1697,8 +1697,12 @@ class EmailCollector extends CommonObject //print $messagetext; //exit; + $fromstring = ''; + $replytostring = ''; + if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { $fromstring = $overview['from']; + //$replytostring = empty($overview['reply-to']) ? '' : $overview['reply-to']; $sender = $overview['sender']; $to = $overview['to']; @@ -1709,6 +1713,7 @@ class EmailCollector extends CommonObject $subject = $overview['subject']; } else { $fromstring = $overview[0]->from; + //$replytostring = empty($overview[0]->replyto) ? '' : $overview[0]->replyto; $sender = $overview[0]->sender; $to = $overview[0]->to; @@ -1729,6 +1734,13 @@ class EmailCollector extends CommonObject $from = $fromstring; $fromtext = ''; } + if (preg_match('/^(.*)<(.*)>$/', $replytostring, $reg)) { + $replyto = $reg[2]; + $replytotext = $reg[1]; + } else { + $replyto = $replytostring; + $replytotext = ''; + } $fk_element_id = 0; $fk_element_type = ''; @@ -2025,6 +2037,7 @@ class EmailCollector extends CommonObject $idtouseforthirdparty = ''; $nametouseforthirdparty = ''; $emailtouseforthirdparty = ''; + $namealiastouseforthirdparty = ''; // $actionparam = 'param=SET:aaa' or 'param=EXTRACT:BODY:....' $arrayvaluetouse = dolExplodeIntoArray($actionparam, ';', '='); @@ -2057,23 +2070,30 @@ 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 '.strtolower($sourcefield).' -> Found idtouseforthirdparty='.dol_escape_htmltag($idtouseforthirdparty); + $operationslog .= '
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 '.strtolower($sourcefield).' -> Found propertytooverwrite='.dol_escape_htmltag($propertytooverwrite); - } else { + $operationslog .= '
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 '.strtolower($sourcefield).' -> Found nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty); + $operationslog .= '
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; + + $operationslog .= '
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'; } } else { // Regex not found $idtouseforthirdparty = null; $nametouseforthirdparty = null; $emailtouseforthirdparty = null; + $namealiastouseforthirdparty = null; - $operationslog .= '
Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtolower($sourcefield).' -> Not found'; + $operationslog .= '
Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Not found'; } //var_dump($object->$tmpproperty);exit; } else { @@ -2085,6 +2105,7 @@ class EmailCollector extends CommonObject } elseif (preg_match('/^(SET|SETIFEMPTY):(.*)$/', $valueforproperty, $reg)) { //if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $reg[1]; //else $object->$tmpproperty = $reg[1]; + // Example: id=SETIFEMPTY:123 if ($propertytooverwrite == 'id') { $idtouseforthirdparty = $reg[2]; @@ -2093,10 +2114,14 @@ class EmailCollector extends CommonObject $emailtouseforthirdparty = $reg[2]; $operationslog .= '
We set property emailtouseforthrdparty='.dol_escape_htmltag($emailtouseforthirdparty); - } else { + } elseif ($propertytooverwrite == 'name') { $nametouseforthirdparty = $reg[2]; $operationslog .= '
We set property nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty); + } elseif ($propertytooverwrite == 'name_alias') { + $namealiastouseforthirdparty = $reg[2]; + + $operationslog .= '
We set property namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty); } } else { $errorforactions++; @@ -2106,8 +2131,8 @@ class EmailCollector extends CommonObject } } - if (!$errorforactions && ($idtouseforthirdparty || $emailtouseforthirdparty || $nametouseforthirdparty)) { - $result = $thirdpartystatic->fetch($idtouseforthirdparty, $nametouseforthirdparty, '', '', '', '', '', '', '', '', $emailtouseforthirdparty); + if (!$errorforactions && ($idtouseforthirdparty || $emailtouseforthirdparty || $nametouseforthirdparty || $namealiastouseforthirdparty)) { + $result = $thirdpartystatic->fetch($idtouseforthirdparty, $nametouseforthirdparty, '', '', '', '', '', '', '', '', $emailtouseforthirdparty, $namealiastouseforthirdparty); if ($result < 0) { $errorforactions++; $this->error = 'Error when getting thirdparty with name '.$nametouseforthirdparty.' (may be 2 record exists with same name ?)'; @@ -2115,21 +2140,25 @@ class EmailCollector extends CommonObject break; } elseif ($result == 0) { if ($operation['type'] == 'loadthirdparty') { - dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." was not found"); + dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." name_alias=".$namealiastouseforthirdparty." was not found"); $errorforactions++; $langs->load("errors"); - $this->error = $langs->trans('ErrorFailedToLoadThirdParty', $idtouseforthirdparty, $emailtouseforthirdparty, $nametouseforthirdparty); + $this->error = $langs->trans('ErrorFailedToLoadThirdParty', $idtouseforthirdparty, $emailtouseforthirdparty, $nametouseforthirdparty, $namealiastouseforthirdparty); $this->errors[] = $this->error; } elseif ($operation['type'] == 'loadandcreatethirdparty') { - dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." was not found. We try to create it."); + 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->name = $nametouseforthirdparty; - if ($fromtext != $nametouseforthirdparty) { - $thirdpartystatic->name_alias = $fromtext; + if (!empty($namealiastouseforthirdparty)) { + if ($namealiastouseforthirdparty != $nametouseforthirdparty) { + $thirdpartystatic->name_alias = $namealiastouseforthirdparty; + } + } else { + $thirdpartystatic->name_alias = (empty($replytostring) ? (empty($fromtext) ? '': $fromtext) : $replytostring); } - $thirdpartystatic->email = ($emailtouseforthirdparty ? $emailtouseforthirdparty : $from); + $thirdpartystatic->email = (empty($emailtouseforthirdparty) ? (empty($replyto) ? (empty($from) ? '' : $from) : $replyto) : $emailtouseforthirdparty); // Overwrite values with values extracted from source email $errorforthisaction = $this->overwritePropertiesOfObject($thirdpartystatic, $operation['actionparam'], $messagetext, $subject, $header, $operationslog); diff --git a/htdocs/eventorganization/conferenceorbooth_list.php b/htdocs/eventorganization/conferenceorbooth_list.php index 17b0bc2e570..258c47f12fc 100644 --- a/htdocs/eventorganization/conferenceorbooth_list.php +++ b/htdocs/eventorganization/conferenceorbooth_list.php @@ -403,7 +403,7 @@ if ($projectid > 0) { // Description print ''.$langs->trans("Description").''; - print nl2br($project->description); + print dol_htmlentitiesbr($project->description); print ''; // Categories diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index a9d11ca1eac..dcc50eff7dc 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -614,6 +614,7 @@ if (empty($reshook)) { $num_prod = count($lines); for ($i = 0; $i < $num_prod; $i++) { if ($lines[$i]->id == $line_id) { // we have found line to update + $update_done = false; $line = new ExpeditionLigne($db); $line->fk_expedition = $object->id; @@ -654,6 +655,8 @@ if (empty($reshook)) { if ($line->update($user) < 0) { setEventMessages($line->error, $line->errors, 'errors'); $error++; + } else { + $update_done=true; } } else { setEventMessages($lotStock->error, $lotStock->errors, 'errors'); @@ -696,6 +699,8 @@ if (empty($reshook)) { if ($line->update($user) < 0) { setEventMessages($line->error, $line->errors, 'errors'); $error++; + } else { + $update_done=true; } } else { setEventMessages($line->error, $line->errors, 'errors'); @@ -713,6 +718,8 @@ if (empty($reshook)) { if ($object->create_line_batch($line, $line->array_options) < 0) { setEventMessages($object->error, $object->errors, 'errors'); $error++; + } else { + $update_done=true; } } } else { @@ -750,6 +757,8 @@ if (empty($reshook)) { if ($line->update($user) < 0) { setEventMessages($line->error, $line->errors, 'errors'); $error++; + } else { + $update_done=true; } } unset($_POST[$stockLocation]); @@ -764,6 +773,8 @@ if (empty($reshook)) { if ($line->update($user) < 0) { setEventMessages($line->error, $line->errors, 'errors'); $error++; + } else { + $update_done=true; } unset($_POST[$qty]); } @@ -776,10 +787,17 @@ if (empty($reshook)) { if ($line->update($user) < 0) { setEventMessages($line->error, $line->errors, 'errors'); $error++; + } else { + $update_done=true; } unset($_POST[$qty]); } } + + if (empty($update_done)) { + $line->id = $lines[$i]->id; + $line->insertExtraFields(); + } } } diff --git a/htdocs/expedition/stats/index.php b/htdocs/expedition/stats/index.php index 9213e2ca849..c14d8c6d3b2 100644 --- a/htdocs/expedition/stats/index.php +++ b/htdocs/expedition/stats/index.php @@ -65,7 +65,7 @@ llxHeader(); print load_fiche_titre($langs->trans("StatisticsOfSendings"), '', 'dolly'); - +$dir = (!empty($conf->expedition->multidir_temp[$conf->entity]) ? $conf->expedition->multidir_temp[$conf->entity] : $conf->service->multidir_temp[$conf->entity]); dol_mkdir($dir); $stats = new ExpeditionStats($db, $socid, '', ($userid > 0 ? $userid : 0)); @@ -84,6 +84,7 @@ if (empty($user->rights->societe->client->voir) || $user->socid) { $px1 = new DolGraph(); $mesg = $px1->isGraphKo(); +$fileurlnb = ''; if (!$mesg) { $px1->SetData($data); $i = $startyear; $legend = array(); diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index f5a983ac5bb..50508f171df 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -486,6 +486,7 @@ if ($action == 'updateline' && $permissiontoreceive) { } } + /* * View */ @@ -616,6 +617,10 @@ if ($id > 0 || !empty($ref)) { print '
'.$langs->trans("OrderStatusNotReadyToDispatch").''; } + + print '
'; + + if ($object->statut == CommandeFournisseur::STATUS_ORDERSENT || $object->statut == CommandeFournisseur::STATUS_RECEIVED_PARTIALLY || $object->statut == CommandeFournisseur::STATUS_RECEIVED_COMPLETELY) { @@ -731,7 +736,7 @@ if ($id > 0 || !empty($ref)) { print ''.$langs->trans("QtyOrdered").''; print ''.$langs->trans("QtyDispatchedShort").''; print ' '.$langs->trans("QtyToDispatchShort"); - print '
'.$langs->trans("Reset").''; + print '
'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').$langs->trans("Reset").''; print ''; if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { @@ -1069,6 +1074,7 @@ if ($id > 0 || !empty($ref)) { $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception"); print '
'; + print ''; print '= qtyOrdered || qtyOrdered <= 1) { + window.alert("Remain quantity to dispatch is too low to be split"); } else if (qtyDispatched < qtyOrdered) { //replace tr suffix nbr $row.html($row.html().replace(/_0_/g,"_"+nbrTrs+"_")); diff --git a/htdocs/includes/jquery/js/jquery.js b/htdocs/includes/jquery/js/jquery.js index fc6c299b73e..7f35c11bdf3 100644 --- a/htdocs/includes/jquery/js/jquery.js +++ b/htdocs/includes/jquery/js/jquery.js @@ -1,5 +1,5 @@ /*! - * jQuery JavaScript Library v3.6.0 + * jQuery JavaScript Library v3.6.4 * https://jquery.com/ * * Includes Sizzle.js @@ -9,7 +9,7 @@ * Released under the MIT license * https://jquery.org/license * - * Date: 2021-03-02T17:08Z + * Date: 2023-03-08T15:28Z */ ( function( global, factory ) { @@ -23,7 +23,7 @@ // (such as Node.js), expose a factory as module.exports. // This accentuates the need for the creation of a real `window`. // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. + // See ticket trac-14549 for more info. module.exports = global.document ? factory( global, true ) : function( w ) { @@ -151,7 +151,7 @@ function toType( obj ) { var - version = "3.6.0", + version = "3.6.4", // Define a local copy of jQuery jQuery = function( selector, context ) { @@ -522,14 +522,14 @@ function isArrayLike( obj ) { } var Sizzle = /*! - * Sizzle CSS Selector Engine v2.3.6 + * Sizzle CSS Selector Engine v2.3.10 * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://js.foundation/ * - * Date: 2021-02-16 + * Date: 2023-02-14 */ ( function( window ) { var i, @@ -633,7 +633,7 @@ var i, whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), rdescend = new RegExp( whitespace + "|>" ), @@ -850,7 +850,7 @@ function Sizzle( selector, context, results, seed ) { // as such selectors are not recognized by querySelectorAll. // Thanks to Andrew Dupont for this technique. if ( nodeType === 1 && - ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + ( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) { // Expand context for sibling selectors newContext = rsibling.test( selector ) && testContext( context.parentNode ) || @@ -1174,6 +1174,24 @@ setDocument = Sizzle.setDocument = function( node ) { !el.querySelectorAll( ":scope fieldset div" ).length; } ); + // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ + // Make sure the the `:has()` argument is parsed unforgivingly. + // We include `*` in the test to detect buggy implementations that are + // _selectively_ forgiving (specifically when the list includes at least + // one valid selector). + // Note that we treat complete lack of support for `:has()` as if it were + // spec-compliant support, which is fine because use of `:has()` in such + // environments will fail in the qSA path and fall back to jQuery traversal + // anyway. + support.cssHas = assert( function() { + try { + document.querySelector( ":has(*,:jqfake)" ); + return false; + } catch ( e ) { + return true; + } + } ); + /* Attributes ---------------------------------------------------------------------- */ @@ -1440,6 +1458,17 @@ setDocument = Sizzle.setDocument = function( node ) { } ); } + if ( !support.cssHas ) { + + // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ + // Our regular `try-catch` mechanism fails to detect natively-unsupported + // pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`) + // in browsers that parse the `:has()` argument as a forgiving selector list. + // https://drafts.csswg.org/selectors/#relational now requires the argument + // to be parsed unforgivingly, but browsers have not yet fully adjusted. + rbuggyQSA.push( ":has" ); + } + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); @@ -1452,7 +1481,14 @@ setDocument = Sizzle.setDocument = function( node ) { // As in, an element does not contain itself contains = hasCompare || rnative.test( docElem.contains ) ? function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, + + // Support: IE <9 only + // IE doesn't have `contains` on `document` so we need to check for + // `documentElement` presence. + // We need to fall back to `a` when `documentElement` is missing + // as `ownerDocument` of elements within `