From 4fecd01ddd0b24a9b91af67f816bdf5b89db1c0c Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Fri, 10 Jun 2022 04:47:15 +0200 Subject: [PATCH 001/816] NEW Accountancy - Manage customer retained warranty --- htdocs/accountancy/admin/defaultaccounts.php | 3 + htdocs/accountancy/journal/sellsjournal.php | 115 ++++++++++++++++++- htdocs/langs/en_US/accountancy.lang | 1 + 3 files changed, 116 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/admin/defaultaccounts.php b/htdocs/accountancy/admin/defaultaccounts.php index 583b12368dc..da590e80562 100644 --- a/htdocs/accountancy/admin/defaultaccounts.php +++ b/htdocs/accountancy/admin/defaultaccounts.php @@ -84,6 +84,9 @@ $list_account[] = 'ACCOUNTING_VAT_PAY_ACCOUNT'; if (!empty($conf->banque->enabled)) { $list_account[] = 'ACCOUNTING_ACCOUNT_TRANSFER_CASH'; } +if (!empty($conf->global->INVOICE_USE_RETAINED_WARRANTY)) { + $list_account[] = 'ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY'; +} if (!empty($conf->don->enabled)) { $list_account[] = 'DONATION_ACCOUNTINGACCOUNT'; } diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 426bc6d7795..a36f67f55f0 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -4,7 +4,7 @@ * Copyright (C) 2011 Juanjo Menent * Copyright (C) 2012 Regis Houssin * Copyright (C) 2013 Christophe Battarel - * Copyright (C) 2013-2021 Alexandre Spangaro + * Copyright (C) 2013-2022 Alexandre Spangaro * Copyright (C) 2013-2016 Florian Henry * Copyright (C) 2013-2016 Olivier Geffroy * Copyright (C) 2014 Raphaël Doursenaud @@ -105,7 +105,7 @@ if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end)) $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false); } -$sql = "SELECT f.rowid, f.ref, f.type, f.datef as df, f.ref_client, f.date_lim_reglement as dlr, f.close_code,"; +$sql = "SELECT f.rowid, f.ref, f.type, f.datef as df, f.ref_client, f.date_lim_reglement as dlr, f.close_code, f.retained_warranty,"; $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.situation_percent, fd.vat_src_code,"; $sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur,"; if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) { @@ -167,6 +167,7 @@ if ($result) { $tabht = array(); $tabtva = array(); $def_tva = array(); + $tabwarranty = array(); $tabttc = array(); $tablocaltax1 = array(); $tablocaltax2 = array(); @@ -247,7 +248,13 @@ if ($result) { $tablocaltax2[$obj->rowid][$compta_localtax2] = 0; } - $tabttc[$obj->rowid][$compta_soc] += $obj->total_ttc * $situation_ratio; + $total_ttc = $obj->total_ttc * $situation_ratio; + if (!empty($conf->global->INVOICE_USE_RETAINED_WARRANTY) && $obj->retained_warranty > 0) { + $retained_warranty = (double)price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); + $tabwarranty[$obj->rowid][$compta_soc] += $retained_warranty; + $total_ttc -= $retained_warranty; + } + $tabttc[$obj->rowid][$compta_soc] += $total_ttc; $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio; if (empty($line->tva_npr)) { $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva * $situation_ratio; // We ignore line if VAT is a NPR @@ -299,6 +306,10 @@ if ($action == 'writebookkeeping') { $accountingaccountcustomer->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER, true); + $accountingaccountcustomerwarranty = new AccountingAccount($db); + + $accountingaccountcustomerwarranty->fetch(null, $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY, true); + foreach ($tabfac as $key => $val) { // Loop on each invoice $errorforline = 0; @@ -345,6 +356,55 @@ if ($action == 'writebookkeeping') { setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $val['ref']), null, 'errors'); } + // Warranty + if (!$errorforline) { + foreach ($tabwarranty[$key] as $k => $mt) { + $bookkeeping = new BookKeeping($db); + $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; + $bookkeeping->doc_ref = $val["ref"]; + $bookkeeping->date_creation = $now; + $bookkeeping->doc_type = 'customer_invoice'; + $bookkeeping->fk_doc = $key; + $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add + $bookkeeping->thirdparty_code = $companystatic->code_client; + + $bookkeeping->subledger_account = $tabcompany[$key]['code_compta']; + $bookkeeping->subledger_label = $tabcompany[$key]['name']; + + $bookkeeping->numero_compte = $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY; + $bookkeeping->label_compte = $accountingaccountcustomerwarranty->label; + + $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty"); + $bookkeeping->montant = $mt; + $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C'; + $bookkeeping->debit = ($mt >= 0) ? $mt : 0; + $bookkeeping->credit = ($mt < 0) ? -$mt : 0; + $bookkeeping->code_journal = $journal; + $bookkeeping->journal_label = $langs->transnoentities($journal_label); + $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; + + $totaldebit += $bookkeeping->debit; + $totalcredit += $bookkeeping->credit; + + $result = $bookkeeping->create($user); + if ($result < 0) { + if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists + $error++; + $errorforline++; + $errorforinvoice[$key] = 'alreadyjournalized'; + //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings'); + } else { + $error++; + $errorforline++; + $errorforinvoice[$key] = 'other'; + setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); + } + } + } + } + // Thirdparty if (!$errorforline) { foreach ($tabttc[$key] as $k => $mt) { @@ -627,6 +687,25 @@ if ($action == 'exportcsv') { // ISO and not UTF8 ! continue; } + // Warranty + foreach ($tabwarranty[$key] as $k => $mt) { + //if ($mt) { + print '"'.$key.'"'.$sep; + print '"'.$date.'"'.$sep; + print '"'.$val["ref"].'"'.$sep; + print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep; + print '"'.length_accounta(html_entity_decode($k)).'"'.$sep; + print '"'.length_accountg($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY).'"'.$sep; + print '"'.length_accounta(html_entity_decode($k)).'"'.$sep; + print '"'.$langs->trans("Thirdparty").'"'.$sep; + print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty").'"'.$sep; + print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep; + print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep; + print '"'.$journal.'"'; + print "\n"; + //} + } + // Third party foreach ($tabttc[$key] as $k => $mt) { //if ($mt) { @@ -852,6 +931,36 @@ if (empty($action) || $action == 'view') { print ""; } + // Warranty + foreach ($tabwarranty[$key] as $k => $mt) { + print ''; + print ""; + print "".$date.""; + print "".$invoicestatic->getNomUrl(1).""; + // Account + print ""; + $accountoshow = length_accountg($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY); + if (($accountoshow == "") || $accountoshow == 'NotDefined') { + print ''.$langs->trans("MainAccountForCustomersNotDefined").''; + } else { + print $accountoshow; + } + print ''; + // Subledger account + print ""; + $accountoshow = length_accounta($k); + if (($accountoshow == "") || $accountoshow == 'NotDefined') { + print ''.$langs->trans("ThirdpartyAccountNotDefined").''; + } else { + print $accountoshow; + } + print ''; + print "".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("Retainedwarranty").""; + print ''.($mt >= 0 ? price($mt) : '').""; + print ''.($mt < 0 ? price(-$mt) : '').""; + print ""; + } + // Third party foreach ($tabttc[$key] as $k => $mt) { print ''; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 0f85c4b1c33..8a6824f9eda 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -183,6 +183,7 @@ ADHERENT_SUBSCRIPTION_ACCOUNTINGACCOUNT=Accounting account to register subscript ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT=Accounting account by default to register customer deposit UseAuxiliaryAccountOnCustomerDeposit=Use sub-accounts on customer deposit lines +ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY=Accounting account by default to register customer retained warranty ACCOUNTING_PRODUCT_BUY_ACCOUNT=Accounting account by default for the bought products (used if not defined in the product sheet) ACCOUNTING_PRODUCT_BUY_INTRA_ACCOUNT=Accounting account by default for the bought products in EEC (used if not defined in the product sheet) From a1cec27540f190f2a1522a3392f8037d5f7bc554 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Fri, 10 Jun 2022 02:53:13 +0000 Subject: [PATCH 002/816] Fixing style errors. --- htdocs/accountancy/journal/sellsjournal.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index a36f67f55f0..cfa1f1d351f 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -250,7 +250,7 @@ if ($result) { $total_ttc = $obj->total_ttc * $situation_ratio; if (!empty($conf->global->INVOICE_USE_RETAINED_WARRANTY) && $obj->retained_warranty > 0) { - $retained_warranty = (double)price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); + $retained_warranty = (double) price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); $tabwarranty[$obj->rowid][$compta_soc] += $retained_warranty; $total_ttc -= $retained_warranty; } From 9ae40a2a02236e801e3bbe322068c6c736a98488 Mon Sep 17 00:00:00 2001 From: atm-florian Date: Tue, 14 Jun 2022 12:52:14 +0200 Subject: [PATCH 003/816] NEW: helper functions for dates + small demo case --- htdocs/core/lib/functions.lib.php | 31 ++++++++++++++++++++++++++ htdocs/fourn/facture/list.php | 36 ++++++------------------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 45bf99577d4..09a287200ba 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -11110,3 +11110,34 @@ function dolForgeCriteriaCallback($matches) return $db->escape($operand).' '.$db->escape($operator)." ".$tmpescaped; } + +/** + * Helper function that combines values of a dolibarr DatePicker (such as Form::selectDate) for year, month, day (and + * optionally hour, minute, second) fields to return a timestamp. + * + * @param string $prefix Prefix used to build the date selector (for instance using Form::selectDate) + * @param bool $useHourTime If true, will also include hour, minute, second values from the HTTP request + * @param string $gm Passed to dol_mktime + * @return int|string Date as a timestamp, '' or false if error + */ +function GETPOSTDATE($prefix, $useHourTime = false, $gm = 'auto') { + return dol_mktime($useHourTime ? (GETPOSTINT($prefix . 'hour')) : 0, $useHourTime ? (GETPOSTINT($prefix . 'minute')) : 0, $useHourTime ? (GETPOSTINT($prefix . 'second')) : 0, GETPOSTINT($prefix . 'month'), GETPOSTINT($prefix . 'day'), GETPOSTINT($prefix . 'year'), $gm); +} + +/** + * Helper function that combines values of a dolibarr DatePicker (such as Form::selectDate) for year, month, day (and + * optionally hour, minute, second) fields to return a a portion of URL reproducing the values from the current HTTP + * request. + * + * @param string $prefix Prefix used to build the date selector (for instance using Form::selectDate) + * @param bool $useHourTime If true, will also include hour, minute, second values from the HTTP request + * @return string Portion of URL with query parameters for the specified date + */ +function buildParamDate($prefix, $useHourTime = false) { + $TParam = [$prefix . 'day' => GETPOST($prefix . 'day'), $prefix . 'month' => GETPOST($prefix . 'month'), $prefix . 'year' => GETPOST($prefix . 'year')]; + if ($useHourTime) { + $TParam += [$prefix . 'hour' => GETPOST($prefix . 'hour'), $prefix . 'minute' => GETPOST($prefix . 'minute'), $prefix . 'second' => GETPOST($prefix . 'second')]; + } + + return '&' . http_build_query($TParam); +} diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 70a7334196a..ec0d8ce7427 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -98,14 +98,8 @@ $search_country = GETPOST("search_country", 'int'); $search_type_thirdparty = GETPOST("search_type_thirdparty", 'int'); $search_user = GETPOST('search_user', 'int'); $search_sale = GETPOST('search_sale', 'int'); -$search_date_startday = GETPOST('search_date_startday', 'int'); -$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); -$search_date_startyear = GETPOST('search_date_startyear', 'int'); -$search_date_endday = GETPOST('search_date_endday', 'int'); -$search_date_endmonth = GETPOST('search_date_endmonth', 'int'); -$search_date_endyear = GETPOST('search_date_endyear', 'int'); -$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver -$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear); +$search_date_start = GETPOSTDATE('search_date_start', false, 'tzserver'); +$search_date_end = GETPOSTDATE('search_date_end', false, 'tzserver'); $search_datelimit_startday = GETPOST('search_datelimit_startday', 'int'); $search_datelimit_startmonth = GETPOST('search_datelimit_startmonth', 'int'); $search_datelimit_startyear = GETPOST('search_datelimit_startyear', 'int'); @@ -274,12 +268,6 @@ if (empty($reshook)) { $search_type = ''; $search_country = ''; $search_type_thirdparty = ''; - $search_date_startday = ''; - $search_date_startmonth = ''; - $search_date_startyear = ''; - $search_date_endday = ''; - $search_date_endmonth = ''; - $search_date_endyear = ''; $search_date_start = ''; $search_date_end = ''; $search_datelimit_startday = ''; @@ -706,23 +694,11 @@ if ($resql) { if ($search_all) { $param .= '&search_all='.urlencode($search_all); } - if ($search_date_startday) { - $param .= '&search_date_startday='.urlencode($search_date_startday); + if ($search_date_start) { + $param .= buildParamDate('search_date_start', false); } - if ($search_date_startmonth) { - $param .= '&search_date_startmonth='.urlencode($search_date_startmonth); - } - if ($search_date_startyear) { - $param .= '&search_date_startyear='.urlencode($search_date_startyear); - } - if ($search_date_endday) { - $param .= '&search_date_endday='.urlencode($search_date_endday); - } - if ($search_date_endmonth) { - $param .= '&search_date_endmonth='.urlencode($search_date_endmonth); - } - if ($search_date_endyear) { - $param .= '&search_date_endyear='.urlencode($search_date_endyear); + if ($search_date_end) { + $param .= buildParamDate('search_date_end', false); } if ($search_datelimit_startday) { $param .= '&search_datelimit_startday='.urlencode($search_datelimit_startday); From e455997160c26ded69e30ab9eafbb148d2ae88e3 Mon Sep 17 00:00:00 2001 From: atm-florian Date: Tue, 14 Jun 2022 14:21:46 +0200 Subject: [PATCH 004/816] [minor] [stickler-ci] Opening brace should be on a new line --- htdocs/core/lib/functions.lib.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 09a287200ba..f783c764f78 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -11120,7 +11120,8 @@ function dolForgeCriteriaCallback($matches) * @param string $gm Passed to dol_mktime * @return int|string Date as a timestamp, '' or false if error */ -function GETPOSTDATE($prefix, $useHourTime = false, $gm = 'auto') { +function GETPOSTDATE($prefix, $useHourTime = false, $gm = 'auto') +{ return dol_mktime($useHourTime ? (GETPOSTINT($prefix . 'hour')) : 0, $useHourTime ? (GETPOSTINT($prefix . 'minute')) : 0, $useHourTime ? (GETPOSTINT($prefix . 'second')) : 0, GETPOSTINT($prefix . 'month'), GETPOSTINT($prefix . 'day'), GETPOSTINT($prefix . 'year'), $gm); } @@ -11133,7 +11134,8 @@ function GETPOSTDATE($prefix, $useHourTime = false, $gm = 'auto') { * @param bool $useHourTime If true, will also include hour, minute, second values from the HTTP request * @return string Portion of URL with query parameters for the specified date */ -function buildParamDate($prefix, $useHourTime = false) { +function buildParamDate($prefix, $useHourTime = false) +{ $TParam = [$prefix . 'day' => GETPOST($prefix . 'day'), $prefix . 'month' => GETPOST($prefix . 'month'), $prefix . 'year' => GETPOST($prefix . 'year')]; if ($useHourTime) { $TParam += [$prefix . 'hour' => GETPOST($prefix . 'hour'), $prefix . 'minute' => GETPOST($prefix . 'minute'), $prefix . 'second' => GETPOST($prefix . 'second')]; From b4e068dcdcd4fa55b78d38859b492e327dfb28f5 Mon Sep 17 00:00:00 2001 From: atm-florian Date: Tue, 14 Jun 2022 18:13:32 +0200 Subject: [PATCH 005/816] PR feedback: allow setting a specific hourtime --- htdocs/core/lib/functions.lib.php | 43 +++++++++++++++++++++++++------ htdocs/fourn/facture/list.php | 8 +++--- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index f783c764f78..aa4d5947fbb 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -11116,13 +11116,29 @@ function dolForgeCriteriaCallback($matches) * optionally hour, minute, second) fields to return a timestamp. * * @param string $prefix Prefix used to build the date selector (for instance using Form::selectDate) - * @param bool $useHourTime If true, will also include hour, minute, second values from the HTTP request + * @param string $hourTime 'getpost' to include hour, minute, second values from the HTTP request, 'XX:YY:ZZ' to set + * hour, minute, second respectively (for instance '23:59:59') * @param string $gm Passed to dol_mktime * @return int|string Date as a timestamp, '' or false if error */ -function GETPOSTDATE($prefix, $useHourTime = false, $gm = 'auto') +function GETPOSTDATE($prefix, $hourTime = '', $gm = 'auto') { - return dol_mktime($useHourTime ? (GETPOSTINT($prefix . 'hour')) : 0, $useHourTime ? (GETPOSTINT($prefix . 'minute')) : 0, $useHourTime ? (GETPOSTINT($prefix . 'second')) : 0, GETPOSTINT($prefix . 'month'), GETPOSTINT($prefix . 'day'), GETPOSTINT($prefix . 'year'), $gm); + if ($hourTime === 'getpost') { + $hour = GETPOSTINT($prefix . 'hour'); + $minute = GETPOSTINT($prefix . 'minute'); + $second = GETPOSTINT($prefix . 'second'); + } elseif (preg_match('/^(\d\d):(\d\d):(\d\d)$/', $hourTime, $m)) { + $hour = (int)$m[1]; + $minute = (int)$m[2]; + $second = (int)$m[3]; + } else { + $hour = $minute = $second = 0; + } + // normalize out of range values + $hour = min($hour, 23); + $minute = min($minute, 59); + $second = min($second, 59); + return dol_mktime($hour, $minute, $second, GETPOSTINT($prefix . 'month'), GETPOSTINT($prefix . 'day'), GETPOSTINT($prefix . 'year'), $gm); } /** @@ -11131,14 +11147,25 @@ function GETPOSTDATE($prefix, $useHourTime = false, $gm = 'auto') * request. * * @param string $prefix Prefix used to build the date selector (for instance using Form::selectDate) - * @param bool $useHourTime If true, will also include hour, minute, second values from the HTTP request + * @param int $timestamp If null, the timestamp will be created from request data + * @param bool $hourTime If timestamp is null, will be passed to GETPOSTDATE to construct the timestamp + * @param bool $gm If timestamp is null, will be passed to GETPOSTDATE to construct the timestamp * @return string Portion of URL with query parameters for the specified date */ -function buildParamDate($prefix, $useHourTime = false) +function buildParamDate($prefix, $timestamp = null, $hourTime = '', $gm = 'auto') { - $TParam = [$prefix . 'day' => GETPOST($prefix . 'day'), $prefix . 'month' => GETPOST($prefix . 'month'), $prefix . 'year' => GETPOST($prefix . 'year')]; - if ($useHourTime) { - $TParam += [$prefix . 'hour' => GETPOST($prefix . 'hour'), $prefix . 'minute' => GETPOST($prefix . 'minute'), $prefix . 'second' => GETPOST($prefix . 'second')]; + if ($timestamp === null) $timestamp = GETPOSTDATE($prefix, $hourTime, $gm); + $TParam = array( + $prefix . 'day' => intval(dol_print_date($timestamp, '%d')), + $prefix . 'month' => intval(dol_print_date($timestamp, '%m')), + $prefix . 'year' => intval(dol_print_date($timestamp, '%Y')), + ); + if ($hourTime === 'getpost' || ($timestamp !== null && dol_print_date($timestamp, '%H:%M:%S') !== '00:00:00')) { + $TParam = array_merge($TParam, array( + $prefix . 'hour' => intval(dol_print_date($timestamp, '%H')), + $prefix . 'minute' => intval(dol_print_date($timestamp, '%M')), + $prefix . 'second' => intval(dol_print_date($timestamp, '%S')) + )); } return '&' . http_build_query($TParam); diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index ec0d8ce7427..e63c8794aad 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -98,8 +98,8 @@ $search_country = GETPOST("search_country", 'int'); $search_type_thirdparty = GETPOST("search_type_thirdparty", 'int'); $search_user = GETPOST('search_user', 'int'); $search_sale = GETPOST('search_sale', 'int'); -$search_date_start = GETPOSTDATE('search_date_start', false, 'tzserver'); -$search_date_end = GETPOSTDATE('search_date_end', false, 'tzserver'); +$search_date_start = GETPOSTDATE('search_date_start', '', 'tzserver'); +$search_date_end = GETPOSTDATE('search_date_end', '23:59:59', 'tzserver'); $search_datelimit_startday = GETPOST('search_datelimit_startday', 'int'); $search_datelimit_startmonth = GETPOST('search_datelimit_startmonth', 'int'); $search_datelimit_startyear = GETPOST('search_datelimit_startyear', 'int'); @@ -695,10 +695,10 @@ if ($resql) { $param .= '&search_all='.urlencode($search_all); } if ($search_date_start) { - $param .= buildParamDate('search_date_start', false); + $param .= buildParamDate('search_date_start', null, '', 'tzserver'); } if ($search_date_end) { - $param .= buildParamDate('search_date_end', false); + $param .= buildParamDate('search_date_end', null, '', 'tzserver'); } if ($search_datelimit_startday) { $param .= '&search_datelimit_startday='.urlencode($search_datelimit_startday); From d4b19ed8a36b45c534ba8de3721281ad88363a4f Mon Sep 17 00:00:00 2001 From: atm-florian Date: Wed, 15 Jun 2022 08:46:54 +0200 Subject: [PATCH 006/816] [minor] formatting issues --- htdocs/core/lib/functions.lib.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index aa4d5947fbb..ecb45a33280 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -11117,7 +11117,7 @@ function dolForgeCriteriaCallback($matches) * * @param string $prefix Prefix used to build the date selector (for instance using Form::selectDate) * @param string $hourTime 'getpost' to include hour, minute, second values from the HTTP request, 'XX:YY:ZZ' to set - * hour, minute, second respectively (for instance '23:59:59') + * hour, minute, second respectively (for instance '23:59:59') * @param string $gm Passed to dol_mktime * @return int|string Date as a timestamp, '' or false if error */ @@ -11128,9 +11128,9 @@ function GETPOSTDATE($prefix, $hourTime = '', $gm = 'auto') $minute = GETPOSTINT($prefix . 'minute'); $second = GETPOSTINT($prefix . 'second'); } elseif (preg_match('/^(\d\d):(\d\d):(\d\d)$/', $hourTime, $m)) { - $hour = (int)$m[1]; - $minute = (int)$m[2]; - $second = (int)$m[3]; + $hour = intval($m[1]); + $minute = intval($m[2]); + $second = intval($m[3]); } else { $hour = $minute = $second = 0; } From 1414f72794c6850bb950f016b02f2559069d9e57 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 13 Jul 2022 16:37:50 +0200 Subject: [PATCH 007/816] NEW color in action list --- htdocs/admin/agenda_other.php | 88 +++++++++++++++++++++++++++++++++-- htdocs/comm/action/list.php | 32 ++++++++++++- 2 files changed, 116 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php index 1014d40de50..3f976efc784 100644 --- a/htdocs/admin/agenda_other.php +++ b/htdocs/admin/agenda_other.php @@ -53,6 +53,9 @@ $type = 'action'; * Actions */ +$error = 0; +$errors = array(); + include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; $reg = array(); @@ -109,7 +112,36 @@ if ($action == 'set') { } else { setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); } -} elseif ($action == 'specimen') { // For orders + +} elseif ($action == 'setcolors') { + $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_past_color', 'alphanohtml')); + $res = dolibarr_set_const($db, 'AGENDA_EVENT_PAST_COLOR', $event_color, 'chaine', 0, '', $conf->entity); + if (!$res > 0) { + $error++; + $errors[] = $db->lasterror(); + } + + $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_progress_color', 'alphanohtml')); + $res = dolibarr_set_const($db, 'AGENDA_EVENT_PROGRESS_COLOR', $event_color, 'chaine', 0, '', $conf->entity); + if (!$res > 0) { + $error++; + $errors[] = $db->lasterror(); + } + + $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_future_color', 'alphanohtml')); + $res = dolibarr_set_const($db, 'AGENDA_EVENT_FUTURE_COLOR', $event_color, 'chaine', 0, '', $conf->entity); + if (!$res > 0) { + $error++; + $errors[] = $db->lasterror(); + } + + if ($error) { + setEventMessages('', $errors, 'errors'); + } else { + setEventMessage($langs->trans('SetupSaved')); + } +} +elseif ($action == 'specimen') { // For orders $modele = GETPOST('module', 'alpha'); $commande = new CommandeFournisseur($db); @@ -192,9 +224,10 @@ print dol_get_fiche_head($head, 'other', $langs->trans("Agenda"), -1, 'action'); /* - * Documents models for supplier orders + * Miscellaneous */ +print load_fiche_titre($langs->trans('Miscellaneous'), '', ''); // Define array def of models $def = array(); @@ -394,7 +427,54 @@ print ''."\n"; print ''; -print dol_get_fiche_end(); +print $form->buttonsSaveCancel("Save", ''); + +print ''; + + +/* + * User interface (colors) + */ + +print load_fiche_titre($langs->trans('UserInterface'), '', ''); + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +$formother = new FormOther($db); + +print '
'; +print ''; +print ''; + +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; + +// AGENDA_EVENT_PAST_COLOR +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +// AGENDA_EVENT_PROGRESS_COLOR +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +// AGENDA_EVENT_FUTURE_COLOR +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; + +print '
'.$langs->trans("Parameters").' '.$langs->trans("Value").'
'.$langs->trans('AGENDA_EVENT_PAST_COLOR').' '."\n"; +print $formother->selectColor($conf->global->AGENDA_EVENT_PAST_COLOR, 'event_past_color'); +print '
'.$langs->trans('AGENDA_EVENT_PROGRESS_COLOR').' '."\n"; +print $formother->selectColor($conf->global->AGENDA_EVENT_PROGRESS_COLOR, 'event_progress_color'); +print '
'.$langs->trans('AGENDA_EVENT_FUTURE_COLOR').' '."\n"; +print $formother->selectColor($conf->global->AGENDA_EVENT_FUTURE_COLOR, 'event_future_color'); +print '
'; print $form->buttonsSaveCancel("Save", ''); @@ -402,6 +482,8 @@ print '
'; print "
"; +print dol_get_fiche_end(); + // End of page llxFooter(); $db->close(); diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index dd877e903e4..0dadd28ff9e 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -889,6 +889,7 @@ $i = 0; //$savnbfield = $totalarray['nbfield']; //$totalarray['nbfield'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); +$today_start_date_time = dol_now(); while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); if (empty($obj)) { @@ -923,7 +924,36 @@ while ($i < $imaxinloop) { $actionstatic->fetchResources(); } - print ''; + // get event color + $event_color = ''; + $event_more_class = ''; + $event_start_date_time = $actionstatic->datep; + if ($obj->fulldayevent) { + $today_start_date_time = dol_mktime(0, 0, 0, date('m', $today_start_date_time), date('d', $today_start_date_time), date('Y', $today_start_date_time)); + } + if ($event_start_date_time > $today_start_date_time) { + // future event + $event_color = $conf->global->AGENDA_EVENT_FUTURE_COLOR; + $event_more_class = 'event-future'; + } else { + // check event end date + $event_end_date_time = $db->jdate($obj->dp2); + if ($event_end_date_time != null && $event_end_date_time < $today_start_date_time) { + // past event + $event_color = $conf->global->AGENDA_EVENT_PAST_COLOR; + $event_more_class = 'event-past'; + } elseif ($event_end_date_time == null && $event_start_date_time < $today_start_date_time) { + // past event + $event_color = $conf->global->AGENDA_EVENT_PAST_COLOR; + $event_more_class = 'event-past'; + } else { + // today event + $event_color = $conf->global->AGENDA_EVENT_PROGRESS_COLOR; + $event_more_class = 'event-progress'; + } + } + + print ''; // Ref if (!empty($arrayfields['a.id']['checked'])) { From cda6e9184df96afe1d4fb54beec9aae1ef12c5cc Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 13 Jul 2022 16:52:57 +0200 Subject: [PATCH 008/816] NEW color in action list and translated --- htdocs/admin/agenda_other.php | 10 +++++----- htdocs/comm/action/list.php | 6 +++--- htdocs/langs/en_US/admin.lang | 5 ++++- htdocs/langs/fr_FR/admin.lang | 5 ++++- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php index 3f976efc784..08858252032 100644 --- a/htdocs/admin/agenda_other.php +++ b/htdocs/admin/agenda_other.php @@ -121,8 +121,8 @@ if ($action == 'set') { $errors[] = $db->lasterror(); } - $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_progress_color', 'alphanohtml')); - $res = dolibarr_set_const($db, 'AGENDA_EVENT_PROGRESS_COLOR', $event_color, 'chaine', 0, '', $conf->entity); + $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_current_color', 'alphanohtml')); + $res = dolibarr_set_const($db, 'AGENDA_EVENT_CURRENT_COLOR', $event_color, 'chaine', 0, '', $conf->entity); if (!$res > 0) { $error++; $errors[] = $db->lasterror(); @@ -459,12 +459,12 @@ print ' '."\n"; print ''."\n"; print $formother->selectColor($conf->global->AGENDA_EVENT_PAST_COLOR, 'event_past_color'); print ''."\n"; -// AGENDA_EVENT_PROGRESS_COLOR +// AGENDA_EVENT_CURRENT_COLOR print ''."\n"; -print ''.$langs->trans('AGENDA_EVENT_PROGRESS_COLOR').''."\n"; +print ''.$langs->trans('AGENDA_EVENT_CURRENT_COLOR').''."\n"; print ' '."\n"; print ''."\n"; -print $formother->selectColor($conf->global->AGENDA_EVENT_PROGRESS_COLOR, 'event_progress_color'); +print $formother->selectColor($conf->global->AGENDA_EVENT_CURRENT_COLOR, 'event_current_color'); print ''."\n"; // AGENDA_EVENT_FUTURE_COLOR print ''."\n"; diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 0dadd28ff9e..ec42c0257af 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -947,9 +947,9 @@ while ($i < $imaxinloop) { $event_color = $conf->global->AGENDA_EVENT_PAST_COLOR; $event_more_class = 'event-past'; } else { - // today event - $event_color = $conf->global->AGENDA_EVENT_PROGRESS_COLOR; - $event_more_class = 'event-progress'; + // current event + $event_color = $conf->global->AGENDA_EVENT_CURRENT_COLOR; + $event_more_class = 'event-current'; } } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 813c7a4faa0..07cd5da86a9 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1806,6 +1806,9 @@ AGENDA_USE_EVENT_TYPE=Use events types (managed in menu Setup -> Dictionaries -> AGENDA_USE_EVENT_TYPE_DEFAULT=Automatically set this default value for type of event in event create form AGENDA_DEFAULT_FILTER_TYPE=Automatically set this type of event in search filter of agenda view AGENDA_DEFAULT_FILTER_STATUS=Automatically set this status for events in search filter of agenda view +AGENDA_EVENT_PAST_COLOR=Past event color +AGENDA_EVENT_CURRENT_COLOR=Current event color +AGENDA_EVENT_FUTURE_COLOR=Future event color AGENDA_DEFAULT_VIEW=Which view do you want to open by default when selecting menu Agenda AGENDA_REMINDER_BROWSER=Enable event reminder on user's browser (When remind date is reached, a popup is shown by the browser. Each user can disable such notifications from its browser notification setup). AGENDA_REMINDER_BROWSER_SOUND=Enable sound notification @@ -2284,4 +2287,4 @@ AlwaysEnabled=Always Enabled DoesNotWorkWithAllThemes=Will not work with all themes NoName=No name ShowAdvancedOptions= Show advanced options -HideAdvancedoptions= Hide advanced options \ No newline at end of file +HideAdvancedoptions= Hide advanced options diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 3c653717801..8c9424546e9 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -1806,6 +1806,9 @@ AGENDA_USE_EVENT_TYPE=Utiliser les types d'événements (gérés dans le menu Co AGENDA_USE_EVENT_TYPE_DEFAULT=Configurez automatiquement cette valeur par défaut pour le type d'événement dans le formulaire de création d'événement. AGENDA_DEFAULT_FILTER_TYPE=Positionner automatiquement ce type d'événement dans le filtre de recherche de la vue agenda AGENDA_DEFAULT_FILTER_STATUS=Positionner automatiquement ce statut d'événement dans le filtre de recherche de la vue agenda +AGENDA_EVENT_PAST_COLOR=Couleur de l'événement passé +AGENDA_EVENT_CURRENT_COLOR=Couleur de l'événement en cours +AGENDA_EVENT_FUTURE_COLOR=Couleur de l'événement futur AGENDA_DEFAULT_VIEW=Quel onglet voulez-vous voir ouvrir par défaut quand on choisit le menu Agenda AGENDA_REMINDER_BROWSER=Activer le rappel d'événement sur le navigateur de l'utilisateur (lorsque la date de l'événement est atteinte, une popup est affichée sur la navigateur. Chaque utilisateur peut désactiver de telles notification depuis la configuration des notifications de son navigateur) AGENDA_REMINDER_BROWSER_SOUND=Activer les notifications sonores. @@ -2267,4 +2270,4 @@ DarkThemeMode=Mode thème sombre AlwaysDisabled=Toujours désactivé AccordingToBrowser=Selon le navigateur AlwaysEnabled=Toujours activé -DoesNotWorkWithAllThemes=Ne fonctionne pas avec tous les thèmes \ No newline at end of file +DoesNotWorkWithAllThemes=Ne fonctionne pas avec tous les thèmes From 0a82efce07b3d28a396995d25d5a2a32e3b8f0c3 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 13 Jul 2022 17:30:08 +0200 Subject: [PATCH 009/816] FIX reload stickler-ci From f69d5924498cc1e1eaed24f48eea42d39a1fb23f Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 13 Jul 2022 17:38:18 +0200 Subject: [PATCH 010/816] FIX stickler-ci --- htdocs/admin/agenda_other.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php index 08858252032..7c2c6640277 100644 --- a/htdocs/admin/agenda_other.php +++ b/htdocs/admin/agenda_other.php @@ -112,7 +112,6 @@ if ($action == 'set') { } else { setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); } - } elseif ($action == 'setcolors') { $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_past_color', 'alphanohtml')); $res = dolibarr_set_const($db, 'AGENDA_EVENT_PAST_COLOR', $event_color, 'chaine', 0, '', $conf->entity); @@ -140,8 +139,7 @@ if ($action == 'set') { } else { setEventMessage($langs->trans('SetupSaved')); } -} -elseif ($action == 'specimen') { // For orders +} elseif ($action == 'specimen') { // For orders $modele = GETPOST('module', 'alpha'); $commande = new CommandeFournisseur($db); From f40ab59b37df0a312a58608854fc654dc70ca042 Mon Sep 17 00:00:00 2001 From: GregM Date: Tue, 19 Jul 2022 16:08:38 +0200 Subject: [PATCH 011/816] FIX contacts disabled are not returned on create invoice --- htdocs/contact/class/contact.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index bb3f2ae035d..ce74f82b412 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1776,10 +1776,13 @@ class Contact extends CommonObject $sql = "SELECT sc.fk_socpeople as id, sc.fk_c_type_contact"; $sql .= " FROM ".MAIN_DB_PREFIX."c_type_contact tc"; $sql .= ", ".MAIN_DB_PREFIX."societe_contacts sc"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."socpeople sp"; + $sql .= " ON sc.fk_socpeople = sp.rowid"; $sql .= " WHERE sc.fk_soc =".((int) $this->socid); $sql .= " AND sc.fk_c_type_contact=tc.rowid"; $sql .= " AND tc.element = '".$this->db->escape($element)."'"; $sql .= " AND tc.active = 1"; + $sql .= " AND sp.statut = 1"; dol_syslog(__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); From 161958d34613d1bcc9ffb30f0f61b9ec440ac957 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Thu, 21 Jul 2022 10:56:03 +0200 Subject: [PATCH 012/816] NEW color for start date and owner --- htdocs/comm/action/list.php | 48 +++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index ec42c0257af..096771c9ea7 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -890,6 +890,7 @@ $i = 0; //$totalarray['nbfield'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); $today_start_date_time = dol_now(); +$cache_user_list = array(); while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); if (empty($obj)) { @@ -924,36 +925,54 @@ while ($i < $imaxinloop) { $actionstatic->fetchResources(); } - // get event color - $event_color = ''; + // cache of user list (owners) + if ($obj->fk_user_action > 0 && !isset($cache_user_list[$obj->fk_user_action])) { + $res = $userstatic->fetch($obj->fk_user_action); + if ($res > 0) { + $cache_user_list[$obj->fk_user_action] = $userstatic; + } + } + + // get event style for user owner + $event_owner_style = ''; + // We decide to choose color of owner of event (event->userownerid is user id of owner, event->userassigned contains all users assigned to event) + if ($cache_user_list[$obj->fk_user_action]->color != '') { + $event_owner_style .= 'border-left: #' . $cache_user_list[$obj->fk_user_action]->color . ' 5px solid;'; + } + + // get event style for start date $event_more_class = ''; + $event_start_date_style = ''; $event_start_date_time = $actionstatic->datep; if ($obj->fulldayevent) { $today_start_date_time = dol_mktime(0, 0, 0, date('m', $today_start_date_time), date('d', $today_start_date_time), date('Y', $today_start_date_time)); } if ($event_start_date_time > $today_start_date_time) { // future event - $event_color = $conf->global->AGENDA_EVENT_FUTURE_COLOR; $event_more_class = 'event-future'; + $event_start_date_color = $conf->global->AGENDA_EVENT_FUTURE_COLOR; } else { // check event end date $event_end_date_time = $db->jdate($obj->dp2); if ($event_end_date_time != null && $event_end_date_time < $today_start_date_time) { // past event - $event_color = $conf->global->AGENDA_EVENT_PAST_COLOR; $event_more_class = 'event-past'; + $event_start_date_color = $conf->global->AGENDA_EVENT_PAST_COLOR; } elseif ($event_end_date_time == null && $event_start_date_time < $today_start_date_time) { // past event - $event_color = $conf->global->AGENDA_EVENT_PAST_COLOR; $event_more_class = 'event-past'; + $event_start_date_color = $conf->global->AGENDA_EVENT_PAST_COLOR; } else { // current event - $event_color = $conf->global->AGENDA_EVENT_CURRENT_COLOR; $event_more_class = 'event-current'; + $event_start_date_color = $conf->global->AGENDA_EVENT_CURRENT_COLOR; } } + if ($event_start_date_color != '') { + $event_start_date_style .= 'background: #' . $event_start_date_color . ';'; + } - print ''; + print ''; // Ref if (!empty($arrayfields['a.id']['checked'])) { @@ -964,10 +983,15 @@ while ($i < $imaxinloop) { // User owner if (!empty($arrayfields['owner']['checked'])) { - print ''; // With edge and chrome the td overflow is not supported correctly when content is not full text. - if ($obj->fk_user_action > 0) { - $userstatic->fetch($obj->fk_user_action); - print $userstatic->getNomUrl(-1); + print ''; // With edge and chrome the td overflow is not supported correctly when content is not full text. + if ($obj->fk_user_action > 0 && !isset($cache_user_list[$obj->fk_user_action])) { + $res = $userstatic->fetch($obj->fk_user_action); + if ($res > 0) { + $cache_user_list[$obj->fk_user_action] = $userstatic; + } + } + if (isset($cache_user_list[$obj->fk_user_action])) { + print $cache_user_list[$obj->fk_user_action]->getNomUrl(-1); } else { print ' '; } @@ -1015,7 +1039,7 @@ while ($i < $imaxinloop) { // Start date if (!empty($arrayfields['a.datep']['checked'])) { - print ''; + print ''; if (empty($obj->fulldayevent)) { print dol_print_date($db->jdate($obj->dp), $formatToUse, 'tzuserrel'); } else { From 993812dc70d6e96118326e283054f8014fca76ec Mon Sep 17 00:00:00 2001 From: lvessiller Date: Thu, 21 Jul 2022 11:22:53 +0200 Subject: [PATCH 013/816] FIX stickler-ci --- htdocs/comm/action/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 096771c9ea7..627b1088afe 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -972,7 +972,7 @@ while ($i < $imaxinloop) { $event_start_date_style .= 'background: #' . $event_start_date_color . ';'; } - print ''; + print ''; // Ref if (!empty($arrayfields['a.id']['checked'])) { From 4d59fd2679a6854994a967924e17f9a7cadb5cae Mon Sep 17 00:00:00 2001 From: lvessiller Date: Tue, 26 Jul 2022 16:36:28 +0200 Subject: [PATCH 014/816] FIX reset today event time --- htdocs/comm/action/list.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 627b1088afe..dba1adecf08 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -889,7 +889,6 @@ $i = 0; //$savnbfield = $totalarray['nbfield']; //$totalarray['nbfield'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); -$today_start_date_time = dol_now(); $cache_user_list = array(); while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); @@ -945,7 +944,9 @@ while ($i < $imaxinloop) { $event_start_date_style = ''; $event_start_date_time = $actionstatic->datep; if ($obj->fulldayevent) { - $today_start_date_time = dol_mktime(0, 0, 0, date('m', $today_start_date_time), date('d', $today_start_date_time), date('Y', $today_start_date_time)); + $today_start_date_time = dol_mktime(0, 0, 0, date('m', $now), date('d', $now), date('Y', $now)); + } else { + $today_start_date_time = $now; } if ($event_start_date_time > $today_start_date_time) { // future event From 62b70b37d353f3a4dc28a5636ecada25716afaab Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 27 Jul 2022 08:32:46 +0200 Subject: [PATCH 015/816] NEW set today start time at begining --- htdocs/comm/action/list.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index dba1adecf08..674348d6158 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -877,6 +877,7 @@ print "\n"; $now = dol_now(); $delay_warning = $conf->global->MAIN_DELAY_ACTIONS_TODO * 24 * 60 * 60; +$today_start_time = dol_mktime(0, 0, 0, date('m', $now), date('d', $now), date('Y', $now)); require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php'; $caction = new CActionComm($db); @@ -943,8 +944,8 @@ while ($i < $imaxinloop) { $event_more_class = ''; $event_start_date_style = ''; $event_start_date_time = $actionstatic->datep; - if ($obj->fulldayevent) { - $today_start_date_time = dol_mktime(0, 0, 0, date('m', $now), date('d', $now), date('Y', $now)); + if ($obj->fulldayevent == 1) { + $today_start_date_time = $today_start_time; } else { $today_start_date_time = $now; } From 7a8006c0a0f02941a286301ac4129c54f0e90ac2 Mon Sep 17 00:00:00 2001 From: BB2A Anthony Berton Date: Wed, 27 Jul 2022 14:40:45 +0200 Subject: [PATCH 016/816] init --- htdocs/commande/list.php | 179 ++++++++++++++++++++++++++++++++- htdocs/langs/en_US/orders.lang | 1 + 2 files changed, 179 insertions(+), 1 deletion(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 264613ac597..00470b13afc 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -71,6 +71,15 @@ $search_dateorder_end = dol_mktime(23, 59, 59, GETPOST('search_dateorder_end_mon $search_datedelivery_start = dol_mktime(0, 0, 0, GETPOST('search_datedelivery_start_month', 'int'), GETPOST('search_datedelivery_start_day', 'int'), GETPOST('search_datedelivery_start_year', 'int')); $search_datedelivery_end = dol_mktime(23, 59, 59, GETPOST('search_datedelivery_end_month', 'int'), GETPOST('search_datedelivery_end_day', 'int'), GETPOST('search_datedelivery_end_year', 'int')); $search_product_category = GETPOST('search_product_category', 'int'); +/* +// Détail commande +*/ +$search_refProduct = GETPOST('search_refProduct', 'alpha'); +$search_descProduct = GETPOST('search_descProduct', 'alpha'); +$check_orderdetail = GETPOST('check_orderdetail', 'alpha'); +/* +// Détail commande fin +*/ $search_ref = GETPOST('search_ref', 'alpha') != '' ?GETPOST('search_ref', 'alpha') : GETPOST('sref', 'alpha'); $search_ref_customer = GETPOST('search_ref_customer', 'alpha'); $search_company = GETPOST('search_company', 'alpha'); @@ -204,6 +213,17 @@ $arrayfields = array( 'c.import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>999), 'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000) ); +/* + // Détail commande fin + */ +if (!empty($check_orderdetail)) { + $arrayfields['cdet.qty'] = array('label'=>'QtyOrdered', 'checked'=>1, 'position'=>1); + $arrayfields['pr.desc'] = array('label'=>'ProductDescription', 'checked'=>1, 'position'=>1); + $arrayfields['pr.ref'] = array('label'=>'ProductRef', 'checked'=>1, 'position'=>1); +} + /* + // Détail commande fin + */ // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; @@ -789,6 +809,16 @@ $sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label, $sql .= ' u.login, u.lastname, u.firstname, u.email as user_email, u.statut as user_statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender,'; $sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shipping_method,'; $sql .= ' c.fk_input_reason, c.import_key'; +/* +// Détail commande +*/ +if (!empty($check_orderdetail)) { + $sql .= ', cdet.description, cdet.qty, '; + $sql .= ' pr.rowid as product_rowid, pr.ref as product_ref, pr.label as product_label, pr.barcode as product_barcode, pr.tobatch as product_batch, pr.tosell as product_status, pr.tobuy as product_status_buy'; +} +/* +// Détail commande fin +*/ if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ", cc.fk_categorie, cc.fk_soc"; } @@ -809,7 +839,19 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_societe as cc ON s.rowid = cc.fk_soc"; // We'll need this table joined to the select in order to filter by categ } -$sql .= ', '.MAIN_DB_PREFIX.'commande as c'; +/* +// Détail commande +*/ +if (!empty($check_orderdetail)) { + $sql .= ', '.MAIN_DB_PREFIX.'commandedet as cdet'; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'commande as c ON cdet.fk_commande=c.rowid'; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as pr ON pr.rowid=cdet.fk_product'; +} else { + $sql .= ', '.MAIN_DB_PREFIX.'commande as c'; +} +/* +// Détail commande fin +*/ if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_extrafields as ef on (c.rowid = ef.fk_object)"; } @@ -1310,6 +1352,13 @@ if ($resql) { print ''; print '
'; } + /* + // Détail commande + */ + print '
 
'; + /* + // Détail commande fin + */ if ($sall) { foreach ($fieldstosearchall as $key => $val) { @@ -1391,6 +1440,27 @@ if ($resql) { print ''."\n"; print ''; + /* + // Détail commande + */ + if (!empty($arrayfields['pr.ref']['checked'])) { + print ''; + } + // Product Description + if (!empty($arrayfields['pr.desc']['checked'])) { + print ''; + } + // Product QtyOrdered + if (!empty($arrayfields['cdet.qty']['checked'])) { + print ''; + } + /* + // Détail commande fin + */ // Ref if (!empty($arrayfields['c.ref']['checked'])) { print ''; + + /* + // Détail commande + */ + if (!empty($arrayfields['pr.ref']['checked'])) { + print_liste_field_titre($arrayfields['pr.ref']['label'], $_SERVER["PHP_SELF"], 'pr.ref', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['pr.desc']['checked'])) { + print_liste_field_titre($arrayfields['pr.desc']['label'], $_SERVER["PHP_SELF"], 'pr.desc', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['cdet.qty']['checked'])) { + print_liste_field_titre($arrayfields['cdet.qty']['label'], $_SERVER["PHP_SELF"], 'cdet.qty', '', $param, '', $sortfield, $sortorder); + } + /* + // Détail commande fin + */ if (!empty($arrayfields['c.ref']['checked'])) { print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], 'c.ref', '', $param, '', $sortfield, $sortorder); } @@ -1820,6 +1906,14 @@ if ($resql) { } $total_ht = 0; $total_margin = 0; + /* + // Détail commande + */ + $totalqty = 0; + /* + // Détail commande fin + */ + $imaxinloop = ($limit ? min($num, $limit) : $num); $last_num = min($num, $limit); @@ -1872,9 +1966,92 @@ if ($resql) { $total_ht += $obj->total_ht; $total_margin += $marginInfo['total_margin']; } + /* + // Détail commande + *//* + if (isset($refpre) && $obj->product_ref != $refpre) { + print ''; + $i = 0; + // var_dump($totalarray); + while ($i < $totalarray['nbfield']) { + $i++; + if (!empty($totalarray['pos'][$i]) && $totalarray['pos'][$i] == 'cdet.qty') { + print ''; + } elseif ($i == 1) { + print ''; + } else { + print ''; + } + } + print ''; + $totalqty = $obj->qty; + //include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + + } else { + $totalqty = $totalqty + $obj->qty; + } + $refpre = isset($obj->product_ref) ? $obj->product_ref : ''; + /* + // Détail commande fin + */ print ''; + /* + // Détail commande + */ + // Product Ref + if (!empty($arrayfields['pr.ref']['checked'])) { + if (!empty($obj->product_rowid)) { + $generic_product->id = $obj->product_rowid; + $generic_product->ref = $obj->product_ref; + $generic_product->label = $obj->product_label; + $generic_product->status = $obj->product_status; + $generic_product->status_buy = $obj->product_status_buy; + $generic_product->status_batch = $obj->product_batch; + $generic_product->barcode = $obj->product_barcode; + print ''; + } else { + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + } + // Product Description + if (!empty($arrayfields['pr.desc']['checked'])) { + // print ''; + !empty($obj->product_label) ? $labelproduct = $obj->product_label : $labelproduct = $obj->description; + print ''; + + if (!$i) { + $totalarray['nbfield']++; + } + } + // Product QtyOrdered + if (!empty($arrayfields['cdet.qty']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'cdet.qty'; + } + if (isset($totalarray['val']['cdet.qty'])) { + $totalarray['val']['cdet.qty'] += $obj->qty; + } else { + $totalarray['val']['cdet.qty'] = $obj->qty; + } + } + /* + // Détail commande fin + */ // Ref if (!empty($arrayfields['c.ref']['checked'])) { print ''; - /* - // Détail commande - */ +// Détail commande if (!empty($arrayfields['pr.ref']['checked'])) { print ''; } - /* - // Détail commande fin - */ // Action column if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { @@ -1737,9 +1717,7 @@ if ($resql) { // Fields title print ''; - /* // Détail commande - */ if (!empty($arrayfields['pr.ref']['checked'])) { print_liste_field_titre($arrayfields['pr.ref']['label'], $_SERVER["PHP_SELF"], 'pr.ref', '', $param, '', $sortfield, $sortorder); } @@ -1749,9 +1727,6 @@ if ($resql) { if (!empty($arrayfields['cdet.qty']['checked'])) { print_liste_field_titre($arrayfields['cdet.qty']['label'], $_SERVER["PHP_SELF"], 'cdet.qty', '', $param, '', $sortfield, $sortorder); } - /* - // Détail commande fin - */ if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); @@ -1927,14 +1902,9 @@ if ($resql) { } $total_ht = 0; $total_margin = 0; - /* + // Détail commande - */ $totalqty = 0; - /* - // Détail commande fin - */ - $imaxinloop = ($limit ? min($num, $limit) : $num); $last_num = min($num, $limit); @@ -1987,46 +1957,10 @@ if ($resql) { $total_ht += $obj->total_ht; $total_margin += $marginInfo['total_margin']; } - /* - // Détail commande - *//* - if (isset($refpre) && $obj->product_ref != $refpre) { - print ''; - $i = 0; - // var_dump($totalarray); - while ($i < $totalarray['nbfield']) { - $i++; - if (!empty($totalarray['pos'][$i]) && $totalarray['pos'][$i] == 'cdet.qty') { - print ''; - } elseif ($i == 1) { - print ''; - } else { - print ''; - } - } - print ''; - $totalqty = $obj->qty; - //include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; - - } else { - $totalqty = $totalqty + $obj->qty; - } - $refpre = isset($obj->product_ref) ? $obj->product_ref : ''; - /* - // Détail commande fin - */ print ''; - /* // Détail commande - */ // Product Ref if (!empty($arrayfields['pr.ref']['checked'])) { if (!empty($obj->product_rowid)) { @@ -2070,9 +2004,6 @@ if ($resql) { $totalarray['val']['cdet.qty'] = $obj->qty; } } - /* - // Détail commande fin - */ // Action column if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { From 887d30e1b46b72c54972d84f205ea76716a51021 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 16:01:45 +0200 Subject: [PATCH 018/816] Add option ORDER_ADD_OPTION_SHOW_DETAIL_LIST --- htdocs/commande/list.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 00e87be1411..02ac878ecee 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1345,8 +1345,9 @@ if ($resql) { } // Détail commande - print '
 
'; - + if (!empty($conf->global->ORDER_ADD_OPTION_SHOW_DETAIL_LIST)){ + print '
 
'; + } if ($sall) { foreach ($fieldstosearchall as $key => $val) { @@ -1429,7 +1430,7 @@ if ($resql) { print '
'; -// Détail commande + // Détail commande if (!empty($arrayfields['pr.ref']['checked'])) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + // Détail commande if (!empty($arrayfields['pr.ref']['checked'])) { print ''; } - // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; - } - // Ref if (!empty($arrayfields['c.ref']['checked'])) { print ''; + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); + } + // Détail commande if (!empty($arrayfields['pr.ref']['checked'])) { + var_dump($_SERVER["PHP_SELF"]); print_liste_field_titre($arrayfields['pr.ref']['label'], $_SERVER["PHP_SELF"], 'pr.ref', '', $param, '', $sortfield, $sortorder); } if (!empty($arrayfields['pr.desc']['checked'])) { @@ -1738,10 +1743,6 @@ if ($resql) { print_liste_field_titre($arrayfields['cdet.qty']['label'], $_SERVER["PHP_SELF"], 'cdet.qty', '', $param, '', $sortfield, $sortorder); } - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); - } - if (!empty($arrayfields['c.ref']['checked'])) { print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], 'c.ref', '', $param, '', $sortfield, $sortorder); } @@ -1970,6 +1971,18 @@ if ($resql) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; } - // Détail commande - if (!empty($arrayfields['pr.ref']['checked'])) { - print ''; - } + // Product Description if (!empty($arrayfields['pr.desc']['checked'])) { print ''; - } else { - print ''; - } - if (!$i) { - $totalarray['nbfield']++; - } - } - // Product Description - if (!empty($arrayfields['pr.desc']['checked'])) { - // print ''; - !empty($obj->product_label) ? $labelproduct = $obj->product_label : $labelproduct = $obj->description; - print ''; - - if (!$i) { - $totalarray['nbfield']++; - } - } - // Product QtyOrdered - if (!empty($arrayfields['cdet.qty']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'cdet.qty'; - } - if (isset($totalarray['val']['cdet.qty'])) { - $totalarray['val']['cdet.qty'] += $obj->qty; - } else { - $totalarray['val']['cdet.qty'] = $obj->qty; - } - } - // Ref if (!empty($arrayfields['c.ref']['checked'])) { print ''; print ''; print '
'; + print ''; + print ''; + print ''; + print ''; @@ -1652,6 +1722,22 @@ if ($resql) { // Fields title print '
'.$totalqty.''; + if (is_object($form)) { + print $form->textwithpicto($langs->trans("Total"), $langs->transnoentitiesnoconv("Totalforthispage")); + } else { + print $langs->trans("Totalforthispage"); + } + print '
'.$generic_product->getNomUrl(1).'Ligne libre'.$obj->description.''.dol_escape_htmltag($labelproduct).''.$obj->qty.''; diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index a4261f8e62c..acb880fa4f3 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -130,6 +130,7 @@ SupplierOrderClassifiedBilled=Purchase Order %s set billed OtherOrders=Other orders SupplierOrderValidatedAndApproved=Supplier order is validated and approved : %s SupplierOrderValidated=Supplier order is validated : %s +OrderShowDetail=Show order detail ##### Types de contacts ##### TypeContact_commande_internal_SALESREPFOLL=Representative following-up sales order TypeContact_commande_internal_SHIPPING=Representative following-up shipping From 0e796a2a02a3a4ff21ac30db67cdaf1c45d016f9 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 15:35:35 +0200 Subject: [PATCH 017/816] Clean --- htdocs/commande/list.php | 97 ++++++---------------------------------- 1 file changed, 14 insertions(+), 83 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index c58cc12a21c..00e87be1411 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -11,7 +11,7 @@ * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016-2021 Ferran Marcet * Copyright (C) 2018 Charlene Benke - * Copyright (C) 2021 Anthony Berton + * Copyright (C) 2021-2022 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 @@ -71,15 +71,12 @@ $search_dateorder_end = dol_mktime(23, 59, 59, GETPOST('search_dateorder_end_mon $search_datedelivery_start = dol_mktime(0, 0, 0, GETPOST('search_datedelivery_start_month', 'int'), GETPOST('search_datedelivery_start_day', 'int'), GETPOST('search_datedelivery_start_year', 'int')); $search_datedelivery_end = dol_mktime(23, 59, 59, GETPOST('search_datedelivery_end_month', 'int'), GETPOST('search_datedelivery_end_day', 'int'), GETPOST('search_datedelivery_end_year', 'int')); $search_product_category = GETPOST('search_product_category', 'int'); -/* + // Détail commande -*/ $search_refProduct = GETPOST('search_refProduct', 'alpha'); $search_descProduct = GETPOST('search_descProduct', 'alpha'); $check_orderdetail = GETPOST('check_orderdetail', 'alpha'); -/* -// Détail commande fin -*/ + $search_ref = GETPOST('search_ref', 'alpha') != '' ?GETPOST('search_ref', 'alpha') : GETPOST('sref', 'alpha'); $search_ref_customer = GETPOST('search_ref_customer', 'alpha'); $search_company = GETPOST('search_company', 'alpha'); @@ -213,17 +210,14 @@ $arrayfields = array( 'c.import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>999), 'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000) ); -/* - // Détail commande fin - */ + +// Détail commande if (!empty($check_orderdetail)) { $arrayfields['cdet.qty'] = array('label'=>'QtyOrdered', 'checked'=>1, 'position'=>1); $arrayfields['pr.desc'] = array('label'=>'ProductDescription', 'checked'=>1, 'position'=>1); $arrayfields['pr.ref'] = array('label'=>'ProductRef', 'checked'=>1, 'position'=>1); } - /* - // Détail commande fin - */ + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; @@ -812,16 +806,13 @@ $sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label, $sql .= ' u.login, u.lastname, u.firstname, u.email as user_email, u.statut as user_statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender,'; $sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shipping_method,'; $sql .= ' c.fk_input_reason, c.import_key'; -/* + // Détail commande -*/ if (!empty($check_orderdetail)) { $sql .= ', cdet.description, cdet.qty, '; $sql .= ' pr.rowid as product_rowid, pr.ref as product_ref, pr.label as product_label, pr.barcode as product_barcode, pr.tobatch as product_batch, pr.tosell as product_status, pr.tobuy as product_status_buy'; } -/* -// Détail commande fin -*/ + if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ", cc.fk_categorie, cc.fk_soc"; } @@ -842,9 +833,8 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_societe as cc ON s.rowid = cc.fk_soc"; // We'll need this table joined to the select in order to filter by categ } -/* + // Détail commande -*/ if (!empty($check_orderdetail)) { $sql .= ', '.MAIN_DB_PREFIX.'commandedet as cdet'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'commande as c ON cdet.fk_commande=c.rowid'; @@ -852,9 +842,7 @@ if (!empty($check_orderdetail)) { } else { $sql .= ', '.MAIN_DB_PREFIX.'commande as c'; } -/* -// Détail commande fin -*/ + if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_extrafields as ef on (c.rowid = ef.fk_object)"; } @@ -1355,13 +1343,10 @@ if ($resql) { print ''; print '
'; } - /* + // Détail commande - */ print '
 
'; - /* - // Détail commande fin - */ + if ($sall) { foreach ($fieldstosearchall as $key => $val) { @@ -1444,9 +1429,7 @@ if ($resql) { print '
'; print ''; @@ -1462,9 +1445,6 @@ if ($resql) { if (!empty($arrayfields['cdet.qty']['checked'])) { print '
'.$totalqty.''; - if (is_object($form)) { - print $form->textwithpicto($langs->trans("Total"), $langs->transnoentitiesnoconv("Totalforthispage")); - } else { - print $langs->trans("Totalforthispage"); - } - print '
'; print ''; From 7df1f876f51aca06b1e747abb0bf05c2b8ed2095 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 16:02:27 +0200 Subject: [PATCH 019/816] Add removefilter --- htdocs/commande/list.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 02ac878ecee..b6490def16a 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -253,6 +253,8 @@ if (empty($reshook)) { $search_user = ''; $search_sale = ''; $search_product_category = ''; + $search_refProduct = ''; + $search_descProduct = ''; $search_ref = ''; $search_ref_customer = ''; $search_company = ''; From 5f3dc1b01fd1a4526b6b04f5588a3643d1d95f30 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 16:11:16 +0200 Subject: [PATCH 020/816] Add search in sql --- htdocs/commande/list.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index b6490def16a..882c56ca033 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -882,6 +882,13 @@ if ($socid > 0) { if (empty($user->rights->societe->client->voir) && !$socid) { $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id); } +if ($search_refProduct) { + $sql .= natural_search('pr.ref', $search_refProduct); +} +if ($search_descProduct) { + $sql .= natural_search('pr.label', $search_descProduct); + $sql .= natural_search('cdet.description', $search_descProduct); +} if ($search_ref) { $sql .= natural_search('c.ref', $search_ref); } From 7740c81f3b55fff507b733c6daa32cc71962f1be Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 27 Jul 2022 14:38:59 +0000 Subject: [PATCH 021/816] Fixing style errors. --- htdocs/commande/list.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 882c56ca033..1c5499e6e8c 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1352,9 +1352,9 @@ if ($resql) { print ''; print '
'; } - + // Détail commande - if (!empty($conf->global->ORDER_ADD_OPTION_SHOW_DETAIL_LIST)){ + if (!empty($conf->global->ORDER_ADD_OPTION_SHOW_DETAIL_LIST)) { print '
 
'; } @@ -1912,7 +1912,7 @@ if ($resql) { } $total_ht = 0; $total_margin = 0; - + // Détail commande $totalqty = 0; From 716adb103fc7a67a1ad18f7b5b883b09215eb4ab Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 16:52:48 +0200 Subject: [PATCH 022/816] FIX - Error with MAIN_CHECKBOX_LEFT_COLUMN --- htdocs/commande/list.php | 49 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 882c56ca033..a8d96597cc7 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1439,6 +1439,14 @@ if ($resql) { print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; @@ -1456,14 +1464,6 @@ if ($resql) { print ''; - $searchpicto = $form->showFilterButtons('left'); - print $searchpicto; - print ''; @@ -1727,8 +1727,13 @@ if ($resql) { // Fields title 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + } + // Détail commande // Product Ref if (!empty($arrayfields['pr.ref']['checked'])) { @@ -2015,18 +2028,6 @@ if ($resql) { } } - // Action column - if (!empty($conf->global->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->rowid, $arrayofselected)) { - $selected = 1; - } - print ''; - } - } - // Ref if (!empty($arrayfields['c.ref']['checked'])) { print ''; From 8dfb4288ecb950004147bc2c47f12f42bbcd262f Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 27 Jul 2022 17:27:05 +0200 Subject: [PATCH 023/816] Clean --- htdocs/commande/list.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 47d139c696a..ac1885b03af 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1733,7 +1733,6 @@ if ($resql) { // Détail commande if (!empty($arrayfields['pr.ref']['checked'])) { - var_dump($_SERVER["PHP_SELF"]); print_liste_field_titre($arrayfields['pr.ref']['label'], $_SERVER["PHP_SELF"], 'pr.ref', '', $param, '', $sortfield, $sortorder); } if (!empty($arrayfields['pr.desc']['checked'])) { From 1769530cfd5837fb4b163197d742ba8ce15bbe99 Mon Sep 17 00:00:00 2001 From: Antonio Date: Sat, 30 Jul 2022 12:12:19 -0500 Subject: [PATCH 024/816] agregar un mensaje de error traducido al espanol --- htdocs/public/error-401.php | 5 +++++ htdocs/public/error-404.php | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/htdocs/public/error-401.php b/htdocs/public/error-401.php index 3d453cd30e5..a160535ff10 100644 --- a/htdocs/public/error-401.php +++ b/htdocs/public/error-401.php @@ -20,6 +20,11 @@
Sorry. You are not allowed to access this resource. +
+
+ + No esta autorizado para acceder a este recurso. +
diff --git a/htdocs/public/error-404.php b/htdocs/public/error-404.php index c964e49cd85..84832100026 100644 --- a/htdocs/public/error-404.php +++ b/htdocs/public/error-404.php @@ -20,6 +20,10 @@
You requested a website or a page that does not exists. +
+
+ la pagina o el recurso solicitado no existe. +
From dac8613c396edb0f815ee9794469300c96d92abe Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 23 Aug 2022 10:46:09 +0200 Subject: [PATCH 025/816] Add new file --- htdocs/commande/list.php | 96 +- htdocs/commande/list_line.php | 2660 +++++++++++++++++++++++++++++++++ 2 files changed, 2671 insertions(+), 85 deletions(-) create mode 100644 htdocs/commande/list_line.php diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index ac1885b03af..1b74238db1c 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -11,7 +11,7 @@ * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016-2021 Ferran Marcet * Copyright (C) 2018 Charlene Benke - * Copyright (C) 2021-2022 Anthony Berton + * Copyright (C) 2021 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 @@ -72,10 +72,7 @@ $search_datedelivery_start = dol_mktime(0, 0, 0, GETPOST('search_datedelivery_st $search_datedelivery_end = dol_mktime(23, 59, 59, GETPOST('search_datedelivery_end_month', 'int'), GETPOST('search_datedelivery_end_day', 'int'), GETPOST('search_datedelivery_end_year', 'int')); $search_product_category = GETPOST('search_product_category', 'int'); -// Détail commande -$search_refProduct = GETPOST('search_refProduct', 'alpha'); -$search_descProduct = GETPOST('search_descProduct', 'alpha'); -$check_orderdetail = GETPOST('check_orderdetail', 'alpha'); + $search_ref = GETPOST('search_ref', 'alpha') != '' ?GETPOST('search_ref', 'alpha') : GETPOST('sref', 'alpha'); $search_ref_customer = GETPOST('search_ref_customer', 'alpha'); @@ -211,12 +208,7 @@ $arrayfields = array( 'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000) ); -// Détail commande -if (!empty($check_orderdetail)) { - $arrayfields['cdet.qty'] = array('label'=>'QtyOrdered', 'checked'=>1, 'position'=>1); - $arrayfields['pr.desc'] = array('label'=>'ProductDescription', 'checked'=>1, 'position'=>1); - $arrayfields['pr.ref'] = array('label'=>'ProductRef', 'checked'=>1, 'position'=>1); -} + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; @@ -809,11 +801,7 @@ $sql .= ' u.login, u.lastname, u.firstname, u.email as user_email, u.statut as u $sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shipping_method,'; $sql .= ' c.fk_input_reason, c.import_key'; -// Détail commande -if (!empty($check_orderdetail)) { - $sql .= ', cdet.description, cdet.qty, '; - $sql .= ' pr.rowid as product_rowid, pr.ref as product_ref, pr.label as product_label, pr.barcode as product_barcode, pr.tobatch as product_batch, pr.tosell as product_status, pr.tobuy as product_status_buy'; -} + if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ", cc.fk_categorie, cc.fk_soc"; @@ -836,14 +824,9 @@ if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_societe as cc ON s.rowid = cc.fk_soc"; // We'll need this table joined to the select in order to filter by categ } -// Détail commande -if (!empty($check_orderdetail)) { - $sql .= ', '.MAIN_DB_PREFIX.'commandedet as cdet'; - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'commande as c ON cdet.fk_commande=c.rowid'; - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as pr ON pr.rowid=cdet.fk_product'; -} else { - $sql .= ', '.MAIN_DB_PREFIX.'commande as c'; -} + +$sql .= ', '.MAIN_DB_PREFIX.'commande as c'; + if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_extrafields as ef on (c.rowid = ef.fk_object)"; @@ -1353,10 +1336,7 @@ if ($resql) { print '
'; } - // Détail commande - if (!empty($conf->global->ORDER_ADD_OPTION_SHOW_DETAIL_LIST)) { - print '
 
'; - } + if ($sall) { foreach ($fieldstosearchall as $key => $val) { @@ -1447,12 +1427,7 @@ if ($resql) { print '
'; - print ''; - print ''; @@ -1731,10 +1706,7 @@ if ($resql) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); } - // Détail commande - if (!empty($arrayfields['pr.ref']['checked'])) { - print_liste_field_titre($arrayfields['pr.ref']['label'], $_SERVER["PHP_SELF"], 'pr.ref', '', $param, '', $sortfield, $sortorder); - } + if (!empty($arrayfields['pr.desc']['checked'])) { print_liste_field_titre($arrayfields['pr.desc']['label'], $_SERVER["PHP_SELF"], 'pr.desc', '', $param, '', $sortfield, $sortorder); } @@ -1913,8 +1885,7 @@ if ($resql) { $total_ht = 0; $total_margin = 0; - // Détail commande - $totalqty = 0; + $imaxinloop = ($limit ? min($num, $limit) : $num); $last_num = min($num, $limit); @@ -1982,51 +1953,6 @@ if ($resql) { } } - // Détail commande - // Product Ref - if (!empty($arrayfields['pr.ref']['checked'])) { - if (!empty($obj->product_rowid)) { - $generic_product->id = $obj->product_rowid; - $generic_product->ref = $obj->product_ref; - $generic_product->label = $obj->product_label; - $generic_product->status = $obj->product_status; - $generic_product->status_buy = $obj->product_status_buy; - $generic_product->status_batch = $obj->product_batch; - $generic_product->barcode = $obj->product_barcode; - print ''.$generic_product->getNomUrl(1).'Ligne libre'.$obj->description.''.dol_escape_htmltag($labelproduct).''.$obj->qty.''; diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php new file mode 100644 index 00000000000..ac1885b03af --- /dev/null +++ b/htdocs/commande/list_line.php @@ -0,0 +1,2660 @@ + + * Copyright (C) 2004-2019 Laurent Destailleur + * Copyright (C) 2005 Marc Barilley / Ocebo + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2012 Juanjo Menent + * Copyright (C) 2013 Christophe Battarel + * Copyright (C) 2013 Cédric Salvador + * Copyright (C) 2015-2018 Frédéric France + * Copyright (C) 2015 Marcos García + * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2016-2021 Ferran Marcet + * Copyright (C) 2018 Charlene Benke + * Copyright (C) 2021-2022 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/commande/list.php + * \ingroup commande + * \brief Page to list orders + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +if (!empty($conf->margin->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmargin.class.php'; +} +require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("orders", 'sendings', 'deliveries', 'companies', 'compta', 'bills', 'stocks', 'products')); + +$action = GETPOST('action', 'aZ09'); +$massaction = GETPOST('massaction', 'alpha'); +$show_files = GETPOST('show_files', 'int'); +$confirm = GETPOST('confirm', 'alpha'); +$toselect = GETPOST('toselect', 'array'); +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'orderlist'; + +$search_datecloture_start = GETPOST('search_datecloture_start', 'int'); +if (empty($search_datecloture_start)) { + $search_datecloture_start = dol_mktime(0, 0, 0, GETPOST('search_datecloture_startmonth', 'int'), GETPOST('search_datecloture_startday', 'int'), GETPOST('search_datecloture_startyear', 'int')); +} +$search_datecloture_end = GETPOST('search_datecloture_end', 'int'); +if (empty($search_datecloture_end)) { + $search_datecloture_end = dol_mktime(23, 59, 59, GETPOST('search_datecloture_endmonth', 'int'), GETPOST('search_datecloture_endday', 'int'), GETPOST('search_datecloture_endyear', 'int')); +} +$search_dateorder_start = dol_mktime(0, 0, 0, GETPOST('search_dateorder_start_month', 'int'), GETPOST('search_dateorder_start_day', 'int'), GETPOST('search_dateorder_start_year', 'int')); +$search_dateorder_end = dol_mktime(23, 59, 59, GETPOST('search_dateorder_end_month', 'int'), GETPOST('search_dateorder_end_day', 'int'), GETPOST('search_dateorder_end_year', 'int')); +$search_datedelivery_start = dol_mktime(0, 0, 0, GETPOST('search_datedelivery_start_month', 'int'), GETPOST('search_datedelivery_start_day', 'int'), GETPOST('search_datedelivery_start_year', 'int')); +$search_datedelivery_end = dol_mktime(23, 59, 59, GETPOST('search_datedelivery_end_month', 'int'), GETPOST('search_datedelivery_end_day', 'int'), GETPOST('search_datedelivery_end_year', 'int')); +$search_product_category = GETPOST('search_product_category', 'int'); + +// Détail commande +$search_refProduct = GETPOST('search_refProduct', 'alpha'); +$search_descProduct = GETPOST('search_descProduct', 'alpha'); +$check_orderdetail = GETPOST('check_orderdetail', 'alpha'); + +$search_ref = GETPOST('search_ref', 'alpha') != '' ?GETPOST('search_ref', 'alpha') : GETPOST('sref', 'alpha'); +$search_ref_customer = GETPOST('search_ref_customer', 'alpha'); +$search_company = GETPOST('search_company', 'alpha'); +$search_company_alias = GETPOST('search_company_alias', 'alpha'); +$search_town = GETPOST('search_town', 'alpha'); +$search_zip = GETPOST('search_zip', 'alpha'); +$search_state = GETPOST("search_state", 'alpha'); +$search_country = GETPOST("search_country", 'int'); +$search_type_thirdparty = GETPOST("search_type_thirdparty", 'int'); +$sall = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); +$socid = GETPOST('socid', 'int'); +$search_user = GETPOST('search_user', 'int'); +$search_sale = GETPOST('search_sale', 'int'); +$search_total_ht = GETPOST('search_total_ht', 'alpha'); +$search_total_vat = GETPOST('search_total_vat', 'alpha'); +$search_total_ttc = GETPOST('search_total_ttc', 'alpha'); +$search_warehouse = GETPOST('search_warehouse', 'int'); +$search_multicurrency_code = GETPOST('search_multicurrency_code', 'alpha'); +$search_multicurrency_tx = GETPOST('search_multicurrency_tx', 'alpha'); +$search_multicurrency_montant_ht = GETPOST('search_multicurrency_montant_ht', 'alpha'); +$search_multicurrency_montant_vat = GETPOST('search_multicurrency_montant_vat', 'alpha'); +$search_multicurrency_montant_ttc = GETPOST('search_multicurrency_montant_ttc', 'alpha'); +$search_login = GETPOST('search_login', 'alpha'); +$search_categ_cus = GETPOST("search_categ_cus", 'int'); +$optioncss = GETPOST('optioncss', 'alpha'); +$search_billed = GETPOSTISSET('search_billed') ? GETPOST('search_billed', 'int') : GETPOST('billed', 'int'); +$search_status = GETPOST('search_status', 'int'); +$search_btn = GETPOST('button_search', 'alpha'); +$search_remove_btn = GETPOST('button_removefilter', 'alpha'); +$search_project_ref = GETPOST('search_project_ref', 'alpha'); +$search_project = GETPOST('search_project', 'alpha'); +$search_shippable = GETPOST('search_shippable', 'aZ09'); +$search_fk_cond_reglement = GETPOST("search_fk_cond_reglement", 'int'); +$search_fk_shipping_method = GETPOST("search_fk_shipping_method", 'int'); +$search_fk_mode_reglement = GETPOST("search_fk_mode_reglement", 'int'); +$search_fk_input_reason = GETPOST("search_fk_input_reason", 'int'); + +// Security check +$id = (GETPOST('orderid') ?GETPOST('orderid', 'int') : GETPOST('id', 'int')); +if ($user->socid) { + $socid = $user->socid; +} +$result = restrictedArea($user, 'commande', $id, ''); + +$diroutputmassaction = $conf->commande->multidir_output[$conf->entity].'/temp/massgeneration/'.$user->id; + +// 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 < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { + $page = 0; +} // If $page is not defined, or '' or -1 or if we click on clear filters +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortfield) { + $sortfield = 'c.ref'; +} +if (!$sortorder) { + $sortorder = 'DESC'; +} + +$show_shippable_command = GETPOST('show_shippable_command', 'aZ09'); + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$object = new Commande($db); +$hookmanager->initHooks(array('orderlist')); +$extrafields = new ExtraFields($db); + +// fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// List of fields to search into when doing a "search in all" +$fieldstosearchall = array( + 'c.ref'=>'Ref', + 'c.ref_client'=>'RefCustomerOrder', + 'pd.description'=>'Description', + 's.nom'=>"ThirdParty", + 's.name_alias'=>"AliasNameShort", + 's.zip'=>"Zip", + 's.town'=>"Town", + 'c.note_public'=>'NotePublic', +); +if (empty($user->socid)) { + $fieldstosearchall["c.note_private"] = "NotePrivate"; +} + +$checkedtypetiers = 0; +$arrayfields = array( + 'c.ref'=>array('label'=>"Ref", 'checked'=>1, 'position'=>5), + 'c.ref_client'=>array('label'=>"RefCustomerOrder", 'checked'=>-1, 'position'=>10), + 'p.ref'=>array('label'=>"ProjectRef", 'checked'=>-1, 'enabled'=>(empty($conf->project->enabled) ? 0 : 1), 'position'=>20), + 'p.title'=>array('label'=>"ProjectLabel", 'checked'=>0, 'enabled'=>(empty($conf->project->enabled) ? 0 : 1), 'position'=>25), + 's.nom'=>array('label'=>"ThirdParty", 'checked'=>1, 'position'=>30), + 's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>-1, 'position'=>31), + 's.town'=>array('label'=>"Town", 'checked'=>-1, 'position'=>35), + 's.zip'=>array('label'=>"Zip", 'checked'=>-1, 'position'=>40), + 'state.nom'=>array('label'=>"StateShort", 'checked'=>0, 'position'=>45), + 'country.code_iso'=>array('label'=>"Country", 'checked'=>0, 'position'=>50), + 'typent.code'=>array('label'=>"ThirdPartyType", 'checked'=>$checkedtypetiers, 'position'=>55), + 'c.date_commande'=>array('label'=>"OrderDateShort", 'checked'=>1, 'position'=>60), + 'c.date_delivery'=>array('label'=>"DateDeliveryPlanned", 'checked'=>1, 'enabled'=>empty($conf->global->ORDER_DISABLE_DELIVERY_DATE), 'position'=>65), + 'c.fk_shipping_method'=>array('label'=>"SendingMethod", 'checked'=>-1, 'position'=>66 , 'enabled'=>!empty($conf->expedition->enabled)), + 'c.fk_cond_reglement'=>array('label'=>"PaymentConditionsShort", 'checked'=>-1, 'position'=>67), + 'c.fk_mode_reglement'=>array('label'=>"PaymentMode", 'checked'=>-1, 'position'=>68), + 'c.fk_input_reason'=>array('label'=>"Channel", 'checked'=>-1, 'position'=>69), + 'c.total_ht'=>array('label'=>"AmountHT", 'checked'=>1, 'position'=>75), + 'c.total_vat'=>array('label'=>"AmountVAT", 'checked'=>0, 'position'=>80), + 'c.total_ttc'=>array('label'=>"AmountTTC", 'checked'=>0, 'position'=>85), + 'c.multicurrency_code'=>array('label'=>'Currency', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>90), + 'c.multicurrency_tx'=>array('label'=>'CurrencyRate', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>95), + 'c.multicurrency_total_ht'=>array('label'=>'MulticurrencyAmountHT', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>100), + 'c.multicurrency_total_vat'=>array('label'=>'MulticurrencyAmountVAT', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>105), + 'c.multicurrency_total_ttc'=>array('label'=>'MulticurrencyAmountTTC', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>110), + 'u.login'=>array('label'=>"Author", 'checked'=>1, 'position'=>115), + 'sale_representative'=>array('label'=>"SaleRepresentativesOfThirdParty", 'checked'=>0, 'position'=>116), + 'total_pa' => array('label' => (getDolGlobalString('MARGIN_TYPE') == '1' ? 'BuyingPrice' : 'CostPrice'), 'checked' => 0, 'position' => 300, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous ? 0 : 1)), + 'total_margin' => array('label' => 'Margin', 'checked' => 0, 'position' => 301, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous ? 0 : 1)), + 'total_margin_rate' => array('label' => 'MarginRate', 'checked' => 0, 'position' => 302, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous || empty($conf->global->DISPLAY_MARGIN_RATES) ? 0 : 1)), + 'total_mark_rate' => array('label' => 'MarkRate', 'checked' => 0, 'position' => 303, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous || empty($conf->global->DISPLAY_MARK_RATES) ? 0 : 1)), + 'c.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>120), + 'c.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>125), + 'c.date_cloture'=>array('label'=>"DateClosing", 'checked'=>0, 'position'=>130), + 'c.note_public'=>array('label'=>'NotePublic', 'checked'=>0, 'enabled'=>(empty($conf->global->MAIN_LIST_ALLOW_PUBLIC_NOTES)), 'position'=>135), + 'c.note_private'=>array('label'=>'NotePrivate', 'checked'=>0, 'enabled'=>(empty($conf->global->MAIN_LIST_ALLOW_PRIVATE_NOTES)), 'position'=>140), + 'shippable'=>array('label'=>"Shippable", 'checked'=>1,'enabled'=>(!empty($conf->expedition->enabled)), 'position'=>990), + 'c.facture'=>array('label'=>"Billed", 'checked'=>1, 'enabled'=>(empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)), 'position'=>995), + 'c.import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>999), + 'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000) +); + +// Détail commande +if (!empty($check_orderdetail)) { + $arrayfields['cdet.qty'] = array('label'=>'QtyOrdered', 'checked'=>1, 'position'=>1); + $arrayfields['pr.desc'] = array('label'=>'ProductDescription', 'checked'=>1, 'position'=>1); + $arrayfields['pr.ref'] = array('label'=>'ProductRef', 'checked'=>1, 'position'=>1); +} + +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; + +$object->fields = dol_sort_array($object->fields, 'position'); +$arrayfields = dol_sort_array($arrayfields, 'position'); + + + +/* + * Actions + */ + +if (GETPOST('cancel', 'alpha')) { + $action = 'list'; $massaction = ''; +} +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { + $massaction = ''; +} + +$parameters = array('socid'=>$socid); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Selection of new fields + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $search_categ = ''; + $search_user = ''; + $search_sale = ''; + $search_product_category = ''; + $search_refProduct = ''; + $search_descProduct = ''; + $search_ref = ''; + $search_ref_customer = ''; + $search_company = ''; + $search_company_alias = ''; + $search_town = ''; + $search_zip = ""; + $search_state = ""; + $search_type = ''; + $search_country = ''; + $search_type_thirdparty = ''; + $search_total_ht = ''; + $search_total_vat = ''; + $search_total_ttc = ''; + $search_warehouse = ''; + $search_multicurrency_code = ''; + $search_multicurrency_tx = ''; + $search_multicurrency_montant_ht = ''; + $search_multicurrency_montant_vat = ''; + $search_multicurrency_montant_ttc = ''; + $search_login = ''; + $search_dateorder_start = ''; + $search_dateorder_end = ''; + $search_datedelivery_start = ''; + $search_datedelivery_end = ''; + $search_project_ref = ''; + $search_project = ''; + $search_status = ''; + $search_billed = ''; + $toselect = array(); + $search_array_options = array(); + $search_categ_cus = 0; + $search_datecloture_start = ''; + $search_datecloture_end = ''; + $search_fk_cond_reglement = ''; + $search_fk_shipping_method = ''; + $search_fk_mode_reglement = ''; + $search_fk_input_reason = ''; + } + 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 = 'Commande'; + $objectlabel = 'Orders'; + $permissiontoread = $user->rights->commande->lire; + $permissiontoadd = $user->rights->commande->creer; + $permissiontodelete = $user->rights->commande->supprimer; + if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { + $permissiontovalidate = $user->rights->commande->order_advance->validate; + $permissiontoclose = $user->rights->commande->order_advance->close; + $permissiontocancel = $user->rights->commande->order_advance->annuler; + $permissiontosendbymail = $user->rights->commande->order_advance->send; + } else { + $permissiontovalidate = $user->rights->commande->creer; + $permissiontoclose = $user->rights->commande->creer; + $permissiontocancel = $user->rights->commande->creer; + $permissiontosendbymail = $user->rights->commande->creer; + } + $uploaddir = $conf->commande->multidir_output[$conf->entity]; + $triggersendname = 'ORDER_SENTBYMAIL'; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; + + if ($massaction == 'confirm_createbills') { // Create bills from orders. + $orders = GETPOST('toselect', 'array'); + $createbills_onebythird = GETPOST('createbills_onebythird', 'int'); + $validate_invoices = GETPOST('validate_invoices', 'int'); + + $errors = array(); + + $TFact = array(); + $TFactThird = array(); + $TFactThirdNbLines = array(); + + $nb_bills_created = 0; + $lastid= 0; + $lastref = ''; + + $db->begin(); + + $nbOrders = is_array($orders) ? count($orders) : 1; + + foreach ($orders as $id_order) { + $cmd = new Commande($db); + if ($cmd->fetch($id_order) <= 0) { + continue; + } + $cmd->fetch_thirdparty(); + + $objecttmp = new Facture($db); + if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) { + // If option "one bill per third" is set, and an invoice for this thirdparty was already created, we re-use it. + $objecttmp = $TFactThird[$cmd->socid]; + } else { + // If we want one invoice per order or if there is no first invoice yet for this thirdparty. + $objecttmp->socid = $cmd->socid; + $objecttmp->thirdparty = $cmd->thirdparty; + + $objecttmp->type = $objecttmp::TYPE_STANDARD; + $objecttmp->cond_reglement_id = !empty($cmd->cond_reglement_id) ? $cmd->cond_reglement_id : $cmd->thirdparty->cond_reglement_id; + $objecttmp->mode_reglement_id = !empty($cmd->mode_reglement_id) ? $cmd->mode_reglement_id : $cmd->thirdparty->mode_reglement_id; + + $objecttmp->fk_project = $cmd->fk_project; + $objecttmp->multicurrency_code = $cmd->multicurrency_code; + if (empty($createbills_onebythird)) { + $objecttmp->ref_client = $cmd->ref_client; + } + + $datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); + if (empty($datefacture)) { + $datefacture = dol_now(); + } + + $objecttmp->date = $datefacture; + $objecttmp->origin = 'commande'; + $objecttmp->origin_id = $id_order; + + $objecttmp->array_options = $cmd->array_options; // Copy extrafields + + $res = $objecttmp->create($user); + + if ($res > 0) { + $nb_bills_created++; + $lastref = $objecttmp->ref; + $lastid = $objecttmp->id; + + $TFactThird[$cmd->socid] = $objecttmp; + $TFactThirdNbLines[$cmd->socid] = 0; //init nblines to have lines ordered by expedition and rang + } else { + $langs->load("errors"); + $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->errors[0]); + $error++; + } + } + + if ($objecttmp->id > 0) { + $res = $objecttmp->add_object_linked($objecttmp->origin, $id_order); + + if ($res == 0) { + $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->errors[0]); + $error++; + } + + if (!$error) { + $lines = $cmd->lines; + if (empty($lines) && method_exists($cmd, 'fetch_lines')) { + $cmd->fetch_lines(); + $lines = $cmd->lines; + } + + $fk_parent_line = 0; + $num = count($lines); + + for ($i = 0; $i < $num; $i++) { + $desc = ($lines[$i]->desc ? $lines[$i]->desc : ''); + // If we build one invoice for several orders, we must put the ref of order on the invoice line + if (!empty($createbills_onebythird)) { + $desc = dol_concatdesc($desc, $langs->trans("Order").' '.$cmd->ref.' - '.dol_print_date($cmd->date, 'day')); + } + + if ($lines[$i]->subprice < 0) { + // Negative line, we create a discount line + $discount = new DiscountAbsolute($db); + $discount->fk_soc = $objecttmp->socid; + $discount->amount_ht = abs($lines[$i]->total_ht); + $discount->amount_tva = abs($lines[$i]->total_tva); + $discount->amount_ttc = abs($lines[$i]->total_ttc); + $discount->tva_tx = $lines[$i]->tva_tx; + $discount->fk_user = $user->id; + $discount->description = $desc; + $discountid = $discount->create($user); + if ($discountid > 0) { + $result = $objecttmp->insert_discount($discountid); + //$result=$discount->link_to_invoice($lineid,$id); + } else { + setEventMessages($discount->error, $discount->errors, 'errors'); + $error++; + break; + } + } else { + // Positive line + $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0); + // Date start + $date_start = false; + if ($lines[$i]->date_debut_prevue) { + $date_start = $lines[$i]->date_debut_prevue; + } + if ($lines[$i]->date_debut_reel) { + $date_start = $lines[$i]->date_debut_reel; + } + if ($lines[$i]->date_start) { + $date_start = $lines[$i]->date_start; + } + //Date end + $date_end = false; + if ($lines[$i]->date_fin_prevue) { + $date_end = $lines[$i]->date_fin_prevue; + } + if ($lines[$i]->date_fin_reel) { + $date_end = $lines[$i]->date_fin_reel; + } + if ($lines[$i]->date_end) { + $date_end = $lines[$i]->date_end; + } + // Reset fk_parent_line for no child products and special product + if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) { + $fk_parent_line = 0; + } + + // Extrafields + if (method_exists($lines[$i], 'fetch_optionals')) { + $lines[$i]->fetch_optionals(); + $array_options = $lines[$i]->array_options; + } + + $objecttmp->context['createfromclone']; + + $rang = ($nbOrders > 1) ? -1 : $lines[$i]->rang; + //there may already be rows from previous orders + if (!empty($createbills_onebythird)) { + $rang = $TFactThirdNbLines[$cmd->socid]; + } + + $result = $objecttmp->addline( + $desc, + $lines[$i]->subprice, + $lines[$i]->qty, + $lines[$i]->tva_tx, + $lines[$i]->localtax1_tx, + $lines[$i]->localtax2_tx, + $lines[$i]->fk_product, + $lines[$i]->remise_percent, + $date_start, + $date_end, + 0, + $lines[$i]->info_bits, + $lines[$i]->fk_remise_except, + 'HT', + 0, + $product_type, + $rang, + $lines[$i]->special_code, + $objecttmp->origin, + $lines[$i]->rowid, + $fk_parent_line, + $lines[$i]->fk_fournprice, + $lines[$i]->pa_ht, + $lines[$i]->label, + $array_options, + 100, + 0, + $lines[$i]->fk_unit + ); + if ($result > 0) { + $lineid = $result; + if (!empty($createbills_onebythird)) //increment rang to keep order + $TFactThirdNbLines[$rcp->socid]++; + } else { + $lineid = 0; + $error++; + break; + } + // Defined the new fk_parent_line + if ($result > 0 && $lines[$i]->product_type == 9) { + $fk_parent_line = $result; + } + } + } + } + } + + //$cmd->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module. + + if (!empty($createbills_onebythird) && empty($TFactThird[$cmd->socid])) { + $TFactThird[$cmd->socid] = $objecttmp; + } else { + $TFact[$objecttmp->id] = $objecttmp; + } + } + + // Build doc with all invoices + $TAllFact = empty($createbills_onebythird) ? $TFact : $TFactThird; + $toselect = array(); + + if (!$error && $validate_invoices) { + $massaction = $action = 'builddoc'; + + foreach ($TAllFact as &$objecttmp) { + $result = $objecttmp->validate($user); + if ($result <= 0) { + $error++; + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + break; + } + + $id = $objecttmp->id; // For builddoc action + + // Builddoc + $donotredirect = 1; + $upload_dir = $conf->facture->dir_output; + $permissiontoadd = $user->rights->facture->creer; + + // Call action to build doc + $savobject = $object; + $object = $objecttmp; + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + $object = $savobject; + } + + $massaction = $action = 'confirm_createbills'; + } + + if (!$error) { + $db->commit(); + + if ($nb_bills_created == 1) { + $texttoshow = $langs->trans('BillXCreated', '{s1}'); + $texttoshow = str_replace('{s1}', ''.$lastref.'', $texttoshow); + setEventMessages($texttoshow, null, 'mesgs'); + } else { + setEventMessages($langs->trans('BillCreated', $nb_bills_created), null, 'mesgs'); + } + + // Make a redirect to avoid to bill twice if we make a refresh or back + $param = ''; + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); + } + if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); + } + if ($sall) { + $param .= '&sall='.urlencode($sall); + } + if ($socid > 0) { + $param .= '&socid='.urlencode($socid); + } + if ($search_status != '') { + $param .= '&search_status='.urlencode($search_status); + } + if ($search_orderday) { + $param .= '&search_orderday='.urlencode($search_orderday); + } + if ($search_ordermonth) { + $param .= '&search_ordermonth='.urlencode($search_ordermonth); + } + if ($search_orderyear) { + $param .= '&search_orderyear='.urlencode($search_orderyear); + } + if ($search_deliveryday) { + $param .= '&search_deliveryday='.urlencode($search_deliveryday); + } + if ($search_deliverymonth) { + $param .= '&search_deliverymonth='.urlencode($search_deliverymonth); + } + if ($search_deliveryyear) { + $param .= '&search_deliveryyear='.urlencode($search_deliveryyear); + } + if ($search_ref) { + $param .= '&search_ref='.urlencode($search_ref); + } + if ($search_company) { + $param .= '&search_company='.urlencode($search_company); + } + if ($search_ref_customer) { + $param .= '&search_ref_customer='.urlencode($search_ref_customer); + } + if ($search_user > 0) { + $param .= '&search_user='.urlencode($search_user); + } + if ($search_sale > 0) { + $param .= '&search_sale='.urlencode($search_sale); + } + if ($search_total_ht != '') { + $param .= '&search_total_ht='.urlencode($search_total_ht); + } + if ($search_total_vat != '') { + $param .= '&search_total_vat='.urlencode($search_total_vat); + } + if ($search_total_ttc != '') { + $param .= '&search_total_ttc='.urlencode($search_total_ttc); + } + if ($search_project_ref >= 0) { + $param .= "&search_project_ref=".urlencode($search_project_ref); + } + if ($show_files) { + $param .= '&show_files='.urlencode($show_files); + } + if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); + } + if ($billed != '') { + $param .= '&billed='.urlencode($billed); + } + + header("Location: ".$_SERVER['PHP_SELF'].'?'.$param); + exit; + } else { + $db->rollback(); + + $action = 'create'; + $_GET["origin"] = $_POST["origin"]; + $_GET["originid"] = $_POST["originid"]; + if (!empty($errors)) { + setEventMessages(null, $errors, 'errors'); + } else { + setEventMessages("Error", null, 'errors'); + } + $error++; + } + } +} +if ($action == 'validate' && $permissiontoadd) { + if (GETPOST('confirm') == 'yes') { + $objecttmp = new $objectclass($db); + $db->begin(); + $error = 0; + foreach ($toselect as $checked) { + if ($objecttmp->fetch($checked)) { + if ($objecttmp->statut == 0) { + if (!empty($objecttmp->fk_warehouse)) { + $idwarehouse = $objecttmp->fk_warehouse; + } else { + $idwarehouse = 0; + } + if ($objecttmp->valid($user, $idwarehouse)) { + setEventMessage($langs->trans('hasBeenValidated', $objecttmp->ref), 'mesgs'); + } else { + setEventMessage($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + } + } else { + $langs->load("errors"); + setEventMessage($langs->trans('ErrorIsNotADraft', $objecttmp->ref), 'errors'); + $error++; + } + } else { + dol_print_error($db); + $error++; + } + } + if ($error) { + $db->rollback(); + } else { + $db->commit(); + } + } +} +if ($action == 'shipped' && $permissiontoadd) { + if (GETPOST('confirm') == 'yes') { + $objecttmp = new $objectclass($db); + $db->begin(); + $error = 0; + foreach ($toselect as $checked) { + if ($objecttmp->fetch($checked)) { + if ($objecttmp->statut == 1 || $objecttmp->statut == 2) { + if ($objecttmp->cloture($user)) { + setEventMessage($langs->trans('PassedInClosedStatus', $objecttmp->ref), 'mesgs'); + } else { + setEventMessage($langs->trans('CantBeClosed'), 'errors'); + $error++; + } + } else { + $langs->load("errors"); + setEventMessage($langs->trans('ErrorIsNotADraft', $objecttmp->ref), 'errors'); + $error++; + } + } else { + dol_print_error($db); + $error++; + } + } + if ($error) { + $db->rollback(); + } else { + $db->commit(); + } + } +} +// Closed records +if (!$error && $massaction === 'setbilled' && $permissiontoclose) { + $db->begin(); + + $objecttmp = new $objectclass($db); + $nbok = 0; + foreach ($toselect as $toselectid) { + $result = $objecttmp->fetch($toselectid); + if ($result > 0) { + $result = $objecttmp->classifyBilled($user, 0); + if ($result <= 0) { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } else { + $nbok++; + } + } else { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } + } + + if (!$error) { + if ($nbok > 1) { + setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs'); + } else { + setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs'); + } + $db->commit(); + } else { + $db->rollback(); + } +} + +/* + * View + */ + +$now = dol_now(); + +$form = new Form($db); +$formother = new FormOther($db); +$formfile = new FormFile($db); +$formmargin = null; +if (!empty($conf->margin->enabled)) { + $formmargin = new FormMargin($db); +} +$companystatic = new Societe($db); +$formcompany = new FormCompany($db); +$projectstatic = new Project($db); + +$title = $langs->trans("Orders"); +$help_url = "EN:Module_Customers_Orders|FR:Module_Commandes_Clients|ES:Módulo_Pedidos_de_clientes"; +// llxHeader('',$title,$help_url); + +$sql = 'SELECT'; +if ($sall || $search_product_category > 0 || $search_user > 0) { + $sql = 'SELECT DISTINCT'; +} +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; +$sql .= " typent.code as typent_code,"; +$sql .= " state.code_departement as state_code, state.nom as state_name,"; +$sql .= " country.code as country_code,"; +$sql .= ' c.rowid, c.ref, c.total_ht, c.total_tva, c.total_ttc, c.ref_client, c.fk_user_author,'; +$sql .= ' c.fk_multicurrency, c.multicurrency_code, c.multicurrency_tx, c.multicurrency_total_ht, c.multicurrency_total_tva as multicurrency_total_vat, c.multicurrency_total_ttc,'; +$sql .= ' c.date_valid, c.date_commande, c.note_public, c.note_private, c.date_livraison as date_delivery, c.fk_statut, c.facture as billed,'; +$sql .= ' c.date_creation as date_creation, c.tms as date_update, c.date_cloture as date_cloture,'; +$sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label,'; +$sql .= ' u.login, u.lastname, u.firstname, u.email as user_email, u.statut as user_statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender,'; +$sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shipping_method,'; +$sql .= ' c.fk_input_reason, c.import_key'; + +// Détail commande +if (!empty($check_orderdetail)) { + $sql .= ', cdet.description, cdet.qty, '; + $sql .= ' pr.rowid as product_rowid, pr.ref as product_ref, pr.label as product_label, pr.barcode as product_barcode, pr.tobatch as product_batch, pr.tosell as product_status, pr.tobuy as product_status_buy'; +} + +if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { + $sql .= ", cc.fk_categorie, cc.fk_soc"; +} +// 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); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +$sql .= ' FROM '.MAIN_DB_PREFIX.'societe as s'; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_typent as typent on (typent.id = s.fk_typent)"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = s.fk_departement)"; +if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_societe as cc ON s.rowid = cc.fk_soc"; // We'll need this table joined to the select in order to filter by categ +} + +// Détail commande +if (!empty($check_orderdetail)) { + $sql .= ', '.MAIN_DB_PREFIX.'commandedet as cdet'; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'commande as c ON cdet.fk_commande=c.rowid'; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as pr ON pr.rowid=cdet.fk_product'; +} else { + $sql .= ', '.MAIN_DB_PREFIX.'commande as c'; +} + +if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_extrafields as ef on (c.rowid = ef.fk_object)"; +} +if ($sall || $search_product_category > 0) { + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'commandedet as pd ON c.rowid=pd.fk_commande'; +} +if ($search_product_category > 0) { + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product=pd.fk_product'; +} +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet as p ON p.rowid = c.fk_projet"; +$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'user as u ON c.fk_user_author = u.rowid'; + +// We'll need this table joined to the select in order to filter by sale +if ($search_sale > 0 || (empty($user->rights->societe->client->voir) && !$socid)) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; +} +if ($search_user > 0) { + $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec"; + $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as tc"; +} + +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + +$sql .= ' WHERE c.fk_soc = s.rowid'; +$sql .= ' AND c.entity IN ('.getEntity('commande').')'; +if ($search_product_category > 0) { + $sql .= " AND cp.fk_categorie = ".((int) $search_product_category); +} +if ($socid > 0) { + $sql .= ' AND s.rowid = '.((int) $socid); +} +if (empty($user->rights->societe->client->voir) && !$socid) { + $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id); +} +if ($search_refProduct) { + $sql .= natural_search('pr.ref', $search_refProduct); +} +if ($search_descProduct) { + $sql .= natural_search('pr.label', $search_descProduct); + $sql .= natural_search('cdet.description', $search_descProduct); +} +if ($search_ref) { + $sql .= natural_search('c.ref', $search_ref); +} +if ($search_ref_customer) { + $sql .= natural_search('c.ref_client', $search_ref_customer); +} +if ($sall) { + $sql .= natural_search(array_keys($fieldstosearchall), $sall); +} +if ($search_billed != '' && $search_billed >= 0) { + $sql .= ' AND c.facture = '.((int) $search_billed); +} +if ($search_status <> '') { + if ($search_status <= 3 && $search_status >= -1) { // status from -1 to 3 are real status (other are virtual combination) + 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 + } + } + if ($search_status == -2) { // To 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 + } + if ($search_status == -3) { // To bill + //$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 + } + if ($search_status == -4) { // "validate and in progress" + $sql .= ' AND (c.fk_statut IN (1,2))'; // validated, in process + } +} + +if ($search_datecloture_start) { + $sql .= " AND c.date_cloture >= '".$db->idate($search_datecloture_start)."'"; +} +if ($search_datecloture_end) { + $sql .= " AND c.date_cloture <= '".$db->idate($search_datecloture_end)."'"; +} +if ($search_dateorder_start) { + $sql .= " AND c.date_commande >= '".$db->idate($search_dateorder_start)."'"; +} +if ($search_dateorder_end) { + $sql .= " AND c.date_commande <= '".$db->idate($search_dateorder_end)."'"; +} +if ($search_datedelivery_start) { + $sql .= " AND c.date_livraison >= '".$db->idate($search_datedelivery_start)."'"; +} +if ($search_datedelivery_end) { + $sql .= " AND c.date_livraison <= '".$db->idate($search_datedelivery_end)."'"; +} +if ($search_town) { + $sql .= natural_search('s.town', $search_town); +} +if ($search_zip) { + $sql .= natural_search("s.zip", $search_zip); +} +if ($search_state) { + $sql .= natural_search("state.nom", $search_state); +} +if ($search_country) { + $sql .= " AND s.fk_pays IN (".$db->sanitize($search_country).')'; +} +if ($search_type_thirdparty && $search_type_thirdparty != '-1') { + $sql .= " AND s.fk_typent IN (".$db->sanitize($search_type_thirdparty).')'; +} +if ($search_company) { + $sql .= natural_search('s.nom', $search_company); +} +if ($search_company_alias) { + $sql .= natural_search('s.name_alias', $search_company_alias); +} +if ($search_sale > 0) { + $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $search_sale); +} +if ($search_user > 0) { + $sql .= " AND ec.fk_c_type_contact = tc.rowid AND tc.element='commande' AND tc.source='internal' AND ec.element_id = c.rowid AND ec.fk_socpeople = ".((int) $search_user); +} +if ($search_total_ht != '') { + $sql .= natural_search('c.total_ht', $search_total_ht, 1); +} +if ($search_total_vat != '') { + $sql .= natural_search('c.total_tva', $search_total_vat, 1); +} +if ($search_total_ttc != '') { + $sql .= natural_search('c.total_ttc', $search_total_ttc, 1); +} +if ($search_warehouse != '' && $search_warehouse > 0) { + $sql .= natural_search('c.fk_warehouse', $search_warehouse, 1); +} +if ($search_multicurrency_code != '') { + $sql .= " AND c.multicurrency_code = '".$db->escape($search_multicurrency_code)."'"; +} +if ($search_multicurrency_tx != '') { + $sql .= natural_search('c.multicurrency_tx', $search_multicurrency_tx, 1); +} +if ($search_multicurrency_montant_ht != '') { + $sql .= natural_search('c.multicurrency_total_ht', $search_multicurrency_montant_ht, 1); +} +if ($search_multicurrency_montant_vat != '') { + $sql .= natural_search('c.multicurrency_total_tva', $search_multicurrency_montant_vat, 1); +} +if ($search_multicurrency_montant_ttc != '') { + $sql .= natural_search('c.multicurrency_total_ttc', $search_multicurrency_montant_ttc, 1); +} +if ($search_login) { + $sql .= natural_search(array("u.login", "u.firstname", "u.lastname"), $search_login); +} +if ($search_project_ref != '') { + $sql .= natural_search("p.ref", $search_project_ref); +} +if ($search_project != '') { + $sql .= natural_search("p.title", $search_project); +} +if ($search_categ_cus > 0) { + $sql .= " AND cc.fk_categorie = ".((int) $search_categ_cus); +} +if ($search_categ_cus == -2) { + $sql .= " AND cc.fk_categorie IS NULL"; +} +if ($search_fk_cond_reglement > 0) { + $sql .= " AND c.fk_cond_reglement = ".((int) $search_fk_cond_reglement); +} +if ($search_fk_shipping_method > 0) { + $sql .= " AND c.fk_shipping_method = ".((int) $search_fk_shipping_method); +} +if ($search_fk_mode_reglement > 0) { + $sql .= " AND c.fk_mode_reglement = ".((int) $search_fk_mode_reglement); +} +if ($search_fk_input_reason > 0) { + $sql .= " AND c.fk_input_reason = ".((int) $search_fk_input_reason); +} + +// 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 +$sql .= $hookmanager->resPrint; + +// Add HAVING from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint; + +$sql .= $db->order($sortfield, $sortorder); + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 + $page = 0; + $offset = 0; + } +} + +$sql .= $db->plimit($limit + 1, $offset); +//print $sql; + +$resql = $db->query($sql); +if ($resql) { + if ($socid > 0) { + $soc = new Societe($db); + $soc->fetch($socid); + $title = $langs->trans('CustomersOrders').' - '.$soc->name; + if (empty($search_company)) { + $search_company = $soc->name; + } + } else { + $title = $langs->trans('CustomersOrders'); + } + if (strval($search_status) == '0') { + $title .= ' - '.$langs->trans('StatusOrderDraftShort'); + } + if ($search_status == 1) { + $title .= ' - '.$langs->trans('StatusOrderValidatedShort'); + } + if ($search_status == 2) { + $title .= ' - '.$langs->trans('StatusOrderSentShort'); + } + if ($search_status == 3) { + $title .= ' - '.$langs->trans('StatusOrderToBillShort'); + } + if ($search_status == -1) { + $title .= ' - '.$langs->trans('StatusOrderCanceledShort'); + } + if ($search_status == -2) { + $title .= ' - '.$langs->trans('StatusOrderToProcessShort'); + } + if ($search_status == -3) { + $title .= ' - '.$langs->trans('StatusOrderValidated').', '.(empty($conf->expedition->enabled) ? '' : $langs->trans("StatusOrderSent").', ').$langs->trans('StatusOrderToBill'); + } + if ($search_status == -4) { + $title .= ' - '.$langs->trans("StatusOrderValidatedShort").'+'.$langs->trans("StatusOrderSentShort"); + } + + $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) { + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".DOL_URL_ROOT.'/commande/card.php?id='.$id); + exit; + } + + llxHeader('', $title, $help_url); + + $param = ''; + + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); + } + if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); + } + if ($sall) { + $param .= '&sall='.urlencode($sall); + } + if ($socid > 0) { + $param .= '&socid='.urlencode($socid); + } + if ($search_status != '') { + $param .= '&search_status='.urlencode($search_status); + } + if ($search_datecloture_start) { + $param .= '&search_datecloture_startday='.dol_print_date($search_datecloture_start, '%d').'&search_datecloture_startmonth='.dol_print_date($search_datecloture_start, '%m').'&search_datecloture_startyear='.dol_print_date($search_datecloture_start, '%Y'); + } + if ($search_datecloture_end) { + $param .= '&search_datecloture_endday='.dol_print_date($search_datecloture_end, '%d').'&search_datecloture_endmonth='.dol_print_date($search_datecloture_end, '%m').'&search_datecloture_endyear='.dol_print_date($search_datecloture_end, '%Y'); + } + if ($search_dateorder_start) { + $param .= '&search_dateorder_start_day='.dol_print_date($search_dateorder_start, '%d').'&search_dateorder_start_month='.dol_print_date($search_dateorder_start, '%m').'&search_dateorder_start_year='.dol_print_date($search_dateorder_start, '%Y'); + } + if ($search_dateorder_end) { + $param .= '&search_dateorder_end_day='.dol_print_date($search_dateorder_end, '%d').'&search_dateorder_end_month='.dol_print_date($search_dateorder_end, '%m').'&search_dateorder_end_year='.dol_print_date($search_dateorder_end, '%Y'); + } + if ($search_datedelivery_start) { + $param .= '&search_datedelivery_start_day='.dol_print_date($search_datedelivery_start, '%d').'&search_datedelivery_start_month='.dol_print_date($search_datedelivery_start, '%m').'&search_datedelivery_start_year='.dol_print_date($search_datedelivery_start, '%Y'); + } + if ($search_datedelivery_end) { + $param .= '&search_datedelivery_end_day='.dol_print_date($search_datedelivery_end, '%d').'&search_datedelivery_end_month='.dol_print_date($search_datedelivery_end, '%m').'&search_datedelivery_end_year='.dol_print_date($search_datedelivery_end, '%Y'); + } + if ($search_ref) { + $param .= '&search_ref='.urlencode($search_ref); + } + if ($search_company) { + $param .= '&search_company='.urlencode($search_company); + } + if ($search_company_alias) { + $param .= '&search_company_alias='.urlencode($search_company_alias); + } + if ($search_ref_customer) { + $param .= '&search_ref_customer='.urlencode($search_ref_customer); + } + if ($search_user > 0) { + $param .= '&search_user='.urlencode($search_user); + } + if ($search_sale > 0) { + $param .= '&search_sale='.urlencode($search_sale); + } + if ($search_total_ht != '') { + $param .= '&search_total_ht='.urlencode($search_total_ht); + } + if ($search_total_vat != '') { + $param .= '&search_total_vat='.urlencode($search_total_vat); + } + if ($search_total_ttc != '') { + $param .= '&search_total_ttc='.urlencode($search_total_ttc); + } + if ($search_warehouse != '') { + $param .= '&search_warehouse='.urlencode($search_warehouse); + } + if ($search_login) { + $param .= '&search_login='.urlencode($search_login); + } + if ($search_multicurrency_code != '') { + $param .= '&search_multicurrency_code='.urlencode($search_multicurrency_code); + } + if ($search_multicurrency_tx != '') { + $param .= '&search_multicurrency_tx='.urlencode($search_multicurrency_tx); + } + if ($search_multicurrency_montant_ht != '') { + $param .= '&search_multicurrency_montant_ht='.urlencode($search_multicurrency_montant_ht); + } + if ($search_multicurrency_montant_vat != '') { + $param .= '&search_multicurrency_montant_vat='.urlencode($search_multicurrency_montant_vat); + } + if ($search_multicurrency_montant_ttc != '') { + $param .= '&search_multicurrency_montant_ttc='.urlencode($search_multicurrency_montant_ttc); + } + if ($search_project_ref >= 0) { + $param .= "&search_project_ref=".urlencode($search_project_ref); + } + if ($search_town != '') { + $param .= '&search_town='.urlencode($search_town); + } + if ($search_zip != '') { + $param .= '&search_zip='.urlencode($search_zip); + } + if ($search_state != '') { + $param .= '&search_state='.urlencode($search_state); + } + if ($search_country != '') { + $param .= '&search_country='.urlencode($search_country); + } + if ($search_type_thirdparty && $search_type_thirdparty != '-1') { + $param .= '&search_type_thirdparty='.urlencode($search_type_thirdparty); + } + if ($search_product_category != '') { + $param .= '&search_product_category='.urlencode($search_product_category); + } + if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { + $param .= '&search_categ_cus='.urlencode($search_categ_cus); + } + if ($show_files) { + $param .= '&show_files='.urlencode($show_files); + } + if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); + } + if ($search_billed != '') { + $param .= '&search_billed='.urlencode($search_billed); + } + if ($search_fk_cond_reglement > 0) { + $param .= '&search_fk_cond_reglement='.urlencode($search_fk_cond_reglement); + } + if ($search_fk_shipping_method > 0) { + $param .= '&search_fk_shipping_method='.urlencode($search_fk_shipping_method); + } + if ($search_fk_mode_reglement > 0) { + $param .= '&search_fk_mode_reglement='.urlencode($search_fk_mode_reglement); + } + if ($search_fk_input_reason > 0) { + $param .= '&search_fk_input_reason='.urlencode($search_fk_input_reason); + } + + // 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); // Note that $action and $object may have been modified by hook + $param .= $hookmanager->resPrint; + + // List of mass actions available + $arrayofmassactions = array( + 'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), + 'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), + ); + if ($permissiontovalidate) { + $arrayofmassactions['prevalidate'] = img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"); + } + if ($permissiontosendbymail) { + $arrayofmassactions['presend'] = img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"); + } + if ($permissiontoclose) { + $arrayofmassactions['preshipped'] = img_picto('', 'dollyrevert', 'class="pictofixedwidth"').$langs->trans("ClassifyShipped"); + } + if ($permissiontocancel) { + $arrayofmassactions['cancelorders'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Cancel"); + } + if (!empty($conf->invoice->enabled) && $user->rights->facture->creer) { + $arrayofmassactions['createbills'] = img_picto('', 'bill', 'class="pictofixedwidth"').$langs->trans("CreateInvoiceForThisCustomer"); + } + if ($permissiontoclose) { + $arrayofmassactions['setbilled'] = img_picto('', 'bill', 'class="pictofixedwidth"').$langs->trans("ClassifyBilled"); + } + if ($permissiontodelete) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); + } + if (in_array($massaction, array('presend', 'predelete', 'createbills'))) { + $arrayofmassactions = array(); + } + $massactionbutton = $form->selectMassAction('', $arrayofmassactions); + + $url = DOL_URL_ROOT.'/commande/card.php?action=create'; + if (!empty($socid)) { + $url .= '&socid='.$socid; + } + $newcardbutton = dolGetButtonTitle($langs->trans('NewOrder'), '', 'fa fa-plus-circle', $url, '', $contextpage == 'orderlist' && $permissiontoadd); + + // Lines of title fields + print '
'; + if ($optioncss != '') { + print ''; + } + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'order', 0, $newcardbutton, '', $limit, 0, 0, 1); + + $topicmail = "SendOrderRef"; + $modelmail = "order_send"; + $objecttmp = new Commande($db); + $trackid = 'ord'.$object->id; + include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + + if ($massaction == 'prevalidate') { + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassValidation"), $langs->trans("ConfirmMassValidationQuestion"), "validate", null, '', 0, 200, 500, 1); + } + if ($massaction == 'preshipped') { + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("CloseOrder"), $langs->trans("ConfirmCloseOrder"), "shipped", null, '', 0, 200, 500, 1); + } + + if ($massaction == 'createbills') { + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'; + print $langs->trans('DateInvoice'); + print ''; + print $form->selectDate('', '', '', '', '', '', 1, 1); + print '
'; + print $langs->trans('CreateOneBillByThird'); + print ''; + print $form->selectyesno('createbills_onebythird', '', 1); + print '
'; + print $langs->trans('ValidateInvoices'); + print ''; + if (!empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_BILL)) { + print $form->selectyesno('validate_invoices', 0, 1, 1); + print ' ('.$langs->trans("AutoValidationNotPossibleWhenStockIsDecreasedOnInvoiceValidation").')'; + } else { + print $form->selectyesno('validate_invoices', 0, 1); + } + if (!empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER)) { + print '     '.$langs->trans("IfValidateInvoiceIsNoOrderStayUnbilled").''; + } else { + print '     '.$langs->trans("OptionToSetOrderBilledNotEnabled").''; + } + print '
'; + + print '
'; + print '
'; + print ' '; + print ''; + print '
'; + print '
'; + } + + // Détail commande + if (!empty($conf->global->ORDER_ADD_OPTION_SHOW_DETAIL_LIST)) { + print '
 
'; + } + + if ($sall) { + foreach ($fieldstosearchall as $key => $val) { + $fieldstosearchall[$key] = $langs->trans($val); + } + print '
'.$langs->trans("FilterOnInto", $sall).join(', ', $fieldstosearchall).'
'; + } + + $moreforfilter = ''; + + // If the user can view prospects other than his' + if ($user->rights->user->user->lire) { + $langs->load("commercial"); + $moreforfilter .= '
'; + $tmptitle = $langs->trans('ThirdPartiesOfSaleRepresentative'); + $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$formother->select_salesrepresentatives($search_sale, 'search_sale', $user, 0, $tmptitle, 'maxwidth250 widthcentpercentminusx'); + $moreforfilter .= '
'; + } + // If the user can view other users + if ($user->rights->user->user->lire) { + $moreforfilter .= '
'; + $tmptitle = $langs->trans('LinkedToSpecificUsers'); + $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_user, 'search_user', $tmptitle, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth250 widthcentpercentminusx'); + $moreforfilter .= '
'; + } + // If the user can view prospects other than his' + if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire && ($user->rights->produit->lire || $user->rights->service->lire)) { + include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + $moreforfilter .= '
'; + $tmptitle = $langs->trans('IncludingProductWithTag'); + $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, null, 'parent', null, null, 1); + $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"').$form->selectarray('search_product_category', $cate_arbo, $search_product_category, $tmptitle, 0, 0, '', 0, 0, 0, 0, 'maxwidth300 widthcentpercentminusx', 1); + $moreforfilter .= '
'; + } + if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + $moreforfilter .= '
'; + $tmptitle = $langs->trans('CustomersProspectsCategoriesShort'); + $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"').$formother->select_categories('customer', $search_categ_cus, 'search_categ_cus', 1, $tmptitle, 'maxwidth300 widthcentpercentminusx'); + $moreforfilter .= '
'; + } + if (!empty($conf->stock->enabled) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) { + require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; + $formproduct = new FormProduct($db); + $moreforfilter .= '
'; + $tmptitle = $langs->trans('Warehouse'); + $moreforfilter .= img_picto($tmptitle, 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($search_warehouse, 'search_warehouse', '', 1, 0, 0, $tmptitle, 0, 0, array(), 'maxwidth250 widthcentpercentminusx'); + $moreforfilter .= '
'; + } + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $moreforfilter .= $hookmanager->resPrint; + } else { + $moreforfilter = $hookmanager->resPrint; + } + + if (!empty($moreforfilter)) { + print '
'; + print $moreforfilter; + print '
'; + } + + $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; + $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields + $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); + + if (GETPOST('autoselectall', 'int')) { + $selectedfields .= ''; + } + + print '
'; + print ''."\n"; + + print ''; + + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + + // Détail commande + if (!empty($arrayfields['pr.ref']['checked'])) { + print ''; + } + // Product Description + if (!empty($arrayfields['pr.desc']['checked'])) { + print ''; + } + // Product QtyOrdered + if (!empty($arrayfields['cdet.qty']['checked'])) { + print ''; + } + + // Ref + if (!empty($arrayfields['c.ref']['checked'])) { + print ''; + } + // Ref customer + if (!empty($arrayfields['c.ref_client']['checked'])) { + print ''; + } + // Project ref + if (!empty($arrayfields['p.ref']['checked'])) { + print ''; + } + // Project title + if (!empty($arrayfields['p.title']['checked'])) { + print ''; + } + // Thirpdarty + if (!empty($arrayfields['s.nom']['checked'])) { + print ''; + } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + } + // Town + if (!empty($arrayfields['s.town']['checked'])) { + print ''; + } + // Zip + if (!empty($arrayfields['s.zip']['checked'])) { + print ''; + } + // State + if (!empty($arrayfields['state.nom']['checked'])) { + print ''; + } + // Country + if (!empty($arrayfields['country.code_iso']['checked'])) { + print ''; + } + // Company type + if (!empty($arrayfields['typent.code']['checked'])) { + print ''; + } + // Date order + if (!empty($arrayfields['c.date_commande']['checked'])) { + print ''; + } + if (!empty($arrayfields['c.date_delivery']['checked'])) { + print ''; + } + // Shipping Method + if (!empty($arrayfields['c.fk_shipping_method']['checked'])) { + print ''; + } + // Payment term + if (!empty($arrayfields['c.fk_cond_reglement']['checked'])) { + print ''; + } + // Payment mode + if (!empty($arrayfields['c.fk_mode_reglement']['checked'])) { + print ''; + } + // Channel + if (!empty($arrayfields['c.fk_input_reason']['checked'])) { + print ''; + } + if (!empty($arrayfields['c.total_ht']['checked'])) { + // Amount + print ''; + } + if (!empty($arrayfields['c.total_vat']['checked'])) { + // Amount + print ''; + } + if (!empty($arrayfields['c.total_ttc']['checked'])) { + // Amount + print ''; + } + if (!empty($arrayfields['c.multicurrency_code']['checked'])) { + // Currency + print ''; + } + if (!empty($arrayfields['c.multicurrency_tx']['checked'])) { + // Currency rate + print ''; + } + if (!empty($arrayfields['c.multicurrency_total_ht']['checked'])) { + // Amount + print ''; + } + if (!empty($arrayfields['c.multicurrency_total_vat']['checked'])) { + // Amount VAT + print ''; + } + if (!empty($arrayfields['c.multicurrency_total_ttc']['checked'])) { + // Amount + print ''; + } + if (!empty($arrayfields['u.login']['checked'])) { + // Author + print ''; + } + if (!empty($arrayfields['sale_representative']['checked'])) { + print ''; + } + if (!empty($arrayfields['total_pa']['checked'])) { + print ''; + } + if (!empty($arrayfields['total_margin']['checked'])) { + print ''; + } + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print ''; + } + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print ''; + } + // Extra fields + 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 + print $hookmanager->resPrint; + // Date creation + if (!empty($arrayfields['c.datec']['checked'])) { + print ''; + } + // Date modification + if (!empty($arrayfields['c.tms']['checked'])) { + print ''; + } + // Date cloture + if (!empty($arrayfields['c.date_cloture']['checked'])) { + print ''; + } + // Note public + if (!empty($arrayfields['c.note_public']['checked'])) { + print ''; + } + // Note private + if (!empty($arrayfields['c.note_private']['checked'])) { + print ''; + } + // Shippable + if (!empty($arrayfields['shippable']['checked'])) { + print ''; + } + // Status billed + if (!empty($arrayfields['c.facture']['checked'])) { + print ''; + } + // Import key + if (!empty($arrayfields['c.import_key']['checked'])) { + print ''; + } + // Status + if (!empty($arrayfields['c.fk_statut']['checked'])) { + print ''; + } + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + print "\n"; + + // Fields title + print ''; + + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); + } + + // Détail commande + if (!empty($arrayfields['pr.ref']['checked'])) { + print_liste_field_titre($arrayfields['pr.ref']['label'], $_SERVER["PHP_SELF"], 'pr.ref', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['pr.desc']['checked'])) { + print_liste_field_titre($arrayfields['pr.desc']['label'], $_SERVER["PHP_SELF"], 'pr.desc', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['cdet.qty']['checked'])) { + print_liste_field_titre($arrayfields['cdet.qty']['label'], $_SERVER["PHP_SELF"], 'cdet.qty', '', $param, '', $sortfield, $sortorder); + } + + if (!empty($arrayfields['c.ref']['checked'])) { + print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], 'c.ref', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.ref_client']['checked'])) { + print_liste_field_titre($arrayfields['c.ref_client']['label'], $_SERVER["PHP_SELF"], 'c.ref_client', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['p.ref']['checked'])) { + print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['p.title']['checked'])) { + print_liste_field_titre($arrayfields['p.title']['label'], $_SERVER["PHP_SELF"], "p.title", "", $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['s.nom']['checked'])) { + print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], 's.nom', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['s.name_alias']['checked'])) { + print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], 's.name_alias', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['s.town']['checked'])) { + print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], 's.town', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['s.zip']['checked'])) { + print_liste_field_titre($arrayfields['s.zip']['label'], $_SERVER["PHP_SELF"], 's.zip', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['state.nom']['checked'])) { + print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['country.code_iso']['checked'])) { + print_liste_field_titre($arrayfields['country.code_iso']['label'], $_SERVER["PHP_SELF"], "country.code_iso", "", $param, '', $sortfield, $sortorder, 'center '); + } + if (!empty($arrayfields['typent.code']['checked'])) { + print_liste_field_titre($arrayfields['typent.code']['label'], $_SERVER["PHP_SELF"], "typent.code", "", $param, '', $sortfield, $sortorder, 'center '); + } + if (!empty($arrayfields['c.date_commande']['checked'])) { + print_liste_field_titre($arrayfields['c.date_commande']['label'], $_SERVER["PHP_SELF"], 'c.date_commande', '', $param, '', $sortfield, $sortorder, 'center '); + } + if (!empty($arrayfields['c.date_delivery']['checked'])) { + print_liste_field_titre($arrayfields['c.date_delivery']['label'], $_SERVER["PHP_SELF"], 'c.date_livraison', '', $param, '', $sortfield, $sortorder, 'center '); + } + if (!empty($arrayfields['c.fk_shipping_method']['checked'])) { + print_liste_field_titre($arrayfields['c.fk_shipping_method']['label'], $_SERVER["PHP_SELF"], "c.fk_shipping_method", "", $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.fk_cond_reglement']['checked'])) { + print_liste_field_titre($arrayfields['c.fk_cond_reglement']['label'], $_SERVER["PHP_SELF"], "c.fk_cond_reglement", "", $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.fk_mode_reglement']['checked'])) { + print_liste_field_titre($arrayfields['c.fk_mode_reglement']['label'], $_SERVER["PHP_SELF"], "c.fk_mode_reglement", "", $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.fk_input_reason']['checked'])) { + print_liste_field_titre($arrayfields['c.fk_input_reason']['label'], $_SERVER["PHP_SELF"], "c.fk_input_reason", "", $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.total_ht']['checked'])) { + print_liste_field_titre($arrayfields['c.total_ht']['label'], $_SERVER["PHP_SELF"], 'c.total_ht', '', $param, '', $sortfield, $sortorder, 'right '); + } + if (!empty($arrayfields['c.total_vat']['checked'])) { + print_liste_field_titre($arrayfields['c.total_vat']['label'], $_SERVER["PHP_SELF"], 'c.total_tva', '', $param, '', $sortfield, $sortorder, 'right '); + } + if (!empty($arrayfields['c.total_ttc']['checked'])) { + print_liste_field_titre($arrayfields['c.total_ttc']['label'], $_SERVER["PHP_SELF"], 'c.total_ttc', '', $param, '', $sortfield, $sortorder, 'right '); + } + if (!empty($arrayfields['c.multicurrency_code']['checked'])) { + print_liste_field_titre($arrayfields['c.multicurrency_code']['label'], $_SERVER['PHP_SELF'], 'c.multicurrency_code', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.multicurrency_tx']['checked'])) { + print_liste_field_titre($arrayfields['c.multicurrency_tx']['label'], $_SERVER['PHP_SELF'], 'c.multicurrency_tx', '', $param, '', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.multicurrency_total_ht']['checked'])) { + print_liste_field_titre($arrayfields['c.multicurrency_total_ht']['label'], $_SERVER['PHP_SELF'], 'c.multicurrency_total_ht', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.multicurrency_total_vat']['checked'])) { + print_liste_field_titre($arrayfields['c.multicurrency_total_vat']['label'], $_SERVER['PHP_SELF'], 'c.multicurrency_total_tva', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['c.multicurrency_total_ttc']['checked'])) { + print_liste_field_titre($arrayfields['c.multicurrency_total_ttc']['label'], $_SERVER['PHP_SELF'], 'c.multicurrency_total_ttc', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['u.login']['checked'])) { + print_liste_field_titre($arrayfields['u.login']['label'], $_SERVER["PHP_SELF"], 'u.login', '', $param, 'align="center"', $sortfield, $sortorder); + } + if (!empty($arrayfields['sale_representative']['checked'])) { + print_liste_field_titre($arrayfields['sale_representative']['label'], $_SERVER["PHP_SELF"], "", "", "$param", '', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_pa']['checked'])) { + print_liste_field_titre($arrayfields['total_pa']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_margin']['checked'])) { + print_liste_field_titre($arrayfields['total_margin']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print_liste_field_titre($arrayfields['total_margin_rate']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print_liste_field_titre($arrayfields['total_mark_rate']['label'], $_SERVER['PHP_SELF'], '', '', $param, 'class="right"', $sortfield, $sortorder); + } + + $totalarray = array( + 'nbfield' => 0, + 'val' => array( + 'c.total_ht' => 0, + 'c.total_tva' => 0, + 'c.total_ttc' => 0, + ), + 'pos' => array(), + ); + // 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, + 'totalarray' => &$totalarray, + ); + $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // 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.date_creation", "", $param, '', $sortfield, $sortorder, 'center nowrap '); + } + if (!empty($arrayfields['c.tms']['checked'])) { + print_liste_field_titre($arrayfields['c.tms']['label'], $_SERVER["PHP_SELF"], "c.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap '); + } + if (!empty($arrayfields['c.date_cloture']['checked'])) { + print_liste_field_titre($arrayfields['c.date_cloture']['label'], $_SERVER["PHP_SELF"], "c.date_cloture", "", $param, '', $sortfield, $sortorder, 'center nowrap '); + } + if (!empty($arrayfields['c.note_public']['checked'])) { + print_liste_field_titre($arrayfields['c.note_public']['label'], $_SERVER["PHP_SELF"], "c.note_public", "", $param, '', $sortfield, $sortorder, 'right '); + } + if (!empty($arrayfields['c.note_private']['checked'])) { + print_liste_field_titre($arrayfields['c.note_private']['label'], $_SERVER["PHP_SELF"], "c.note_private", "", $param, '', $sortfield, $sortorder, 'right '); + } + if (!empty($arrayfields['shippable']['checked'])) { + print_liste_field_titre($arrayfields['shippable']['label'], $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center '); + } + if (!empty($arrayfields['c.facture']['checked'])) { + print_liste_field_titre($arrayfields['c.facture']['label'], $_SERVER["PHP_SELF"], 'c.facture', '', $param, '', $sortfield, $sortorder, 'center '); + } + if (!empty($arrayfields['c.import_key']['checked'])) { + print_liste_field_titre($arrayfields['c.import_key']['label'], $_SERVER["PHP_SELF"], "c.import_key", "", $param, '', $sortfield, $sortorder, 'center '); + } + if (!empty($arrayfields['c.fk_statut']['checked'])) { + print_liste_field_titre($arrayfields['c.fk_statut']['label'], $_SERVER["PHP_SELF"], "c.fk_statut", "", $param, '', $sortfield, $sortorder, 'center '); + } + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); + } + print ''."\n"; + + $total = 0; + $subtotal = 0; + $productstat_cache = array(); + $productstat_cachevirtual = array(); + $getNomUrl_cache = array(); + + $generic_commande = new Commande($db); + $generic_product = new Product($db); + $userstatic = new User($db); + $i = 0; + + $with_margin_info = false; + if (!empty($conf->margin->enabled) && ( + !empty($arrayfields['total_pa']['checked']) + || !empty($arrayfields['total_margin']['checked']) + || !empty($arrayfields['total_margin_rate']['checked']) + || !empty($arrayfields['total_mark_rate']['checked']) + ) + ) { + $with_margin_info = true; + } + $total_ht = 0; + $total_margin = 0; + + // Détail commande + $totalqty = 0; + + $imaxinloop = ($limit ? min($num, $limit) : $num); + $last_num = min($num, $limit); + while ($i < $imaxinloop) { + $obj = $db->fetch_object($resql); + + $notshippable = 0; + $warning = 0; + $text_info = ''; + $text_warning = ''; + $nbprod = 0; + + $companystatic->id = $obj->socid; + $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; + $companystatic->client = $obj->client; + $companystatic->code_client = $obj->code_client; + $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; + if (!isset($getNomUrl_cache[$obj->socid])) { + $getNomUrl_cache[$obj->socid] = $companystatic->getNomUrl(1, 'customer'); + } + + $generic_commande->id = $obj->rowid; + $generic_commande->ref = $obj->ref; + $generic_commande->statut = $obj->fk_statut; + $generic_commande->billed = $obj->billed; + $generic_commande->date = $db->jdate($obj->date_commande); + $generic_commande->date_livraison = $db->jdate($obj->date_delivery); // deprecated + $generic_commande->delivery_date = $db->jdate($obj->date_delivery); + $generic_commande->ref_client = $obj->ref_client; + $generic_commande->total_ht = $obj->total_ht; + $generic_commande->total_tva = $obj->total_tva; + $generic_commande->total_ttc = $obj->total_ttc; + $generic_commande->note_public = $obj->note_public; + $generic_commande->note_private = $obj->note_private; + + $projectstatic->id = $obj->project_id; + $projectstatic->ref = $obj->project_ref; + $projectstatic->title = $obj->project_label; + + $marginInfo = array(); + if ($with_margin_info === true) { + $generic_commande->fetch_lines(); + $marginInfo = $formmargin->getMarginInfosArray($generic_commande); + $total_ht += $obj->total_ht; + $total_margin += $marginInfo['total_margin']; + } + + print ''; + + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } else { + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + } + // Product Description + if (!empty($arrayfields['pr.desc']['checked'])) { + // print ''; + !empty($obj->product_label) ? $labelproduct = $obj->product_label : $labelproduct = $obj->description; + print ''; + + if (!$i) { + $totalarray['nbfield']++; + } + } + // Product QtyOrdered + if (!empty($arrayfields['cdet.qty']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'cdet.qty'; + } + if (isset($totalarray['val']['cdet.qty'])) { + $totalarray['val']['cdet.qty'] += $obj->qty; + } else { + $totalarray['val']['cdet.qty'] = $obj->qty; + } + } + + // Ref + if (!empty($arrayfields['c.ref']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Ref customer + if (!empty($arrayfields['c.ref_client']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Project ref + if (!empty($arrayfields['p.ref']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Project label + if (!empty($arrayfields['p.title']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Third party + if (!empty($arrayfields['s.nom']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Alias name + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Town + if (!empty($arrayfields['s.town']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Zip + if (!empty($arrayfields['s.zip']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['state.nom']['checked'])) { + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['country.code_iso']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Type ent + if (!empty($arrayfields['typent.code']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Order date + if (!empty($arrayfields['c.date_commande']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Plannned date of delivery + if (!empty($arrayfields['c.date_delivery']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Shipping Method + if (!empty($arrayfields['c.fk_shipping_method']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Payment terms + if (!empty($arrayfields['c.fk_cond_reglement']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Payment mode + if (!empty($arrayfields['c.fk_mode_reglement']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Channel + if (!empty($arrayfields['c.fk_input_reason']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['c.total_ht']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'c.total_ht'; + } + if (isset($totalarray['val']['c.total_ht'])) { + $totalarray['val']['c.total_ht'] += $obj->total_ht; + } else { + $totalarray['val']['c.total_ht'] = $obj->total_ht; + } + } + // Amount VAT + if (!empty($arrayfields['c.total_vat']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'c.total_tva'; + } + $totalarray['val']['c.total_tva'] += $obj->total_tva; + } + // Amount TTC + if (!empty($arrayfields['c.total_ttc']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'c.total_ttc'; + } + $totalarray['val']['c.total_ttc'] += $obj->total_ttc; + } + + // Currency + if (!empty($arrayfields['c.multicurrency_code']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Currency rate + if (!empty($arrayfields['c.multicurrency_tx']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['c.multicurrency_total_ht']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount VAT + if (!empty($arrayfields['c.multicurrency_total_vat']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount TTC + if (!empty($arrayfields['c.multicurrency_total_ttc']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + $userstatic->id = $obj->fk_user_author; + $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->email = $obj->user_email; + $userstatic->statut = $obj->user_statut; + $userstatic->entity = $obj->entity; + $userstatic->photo = $obj->photo; + $userstatic->office_phone = $obj->office_phone; + $userstatic->office_fax = $obj->office_fax; + $userstatic->user_mobile = $obj->user_mobile; + $userstatic->job = $obj->job; + $userstatic->gender = $obj->gender; + + // Author + if (!empty($arrayfields['u.login']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + if (!empty($arrayfields['sale_representative']['checked'])) { + // Sales representatives + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Total buying or cost price + if (!empty($arrayfields['total_pa']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total margin + if (!empty($arrayfields['total_margin']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_margin'; + } + $totalarray['val']['total_margin'] += $marginInfo['total_margin']; + } + // Total margin rate + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total mark rate + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; + } + if ($i >= $last_num - 1) { + if (!empty($total_ht)) { + $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); + } else { + $totalarray['val']['total_mark_rate'] = ''; + } + } + } + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + // Date creation + if (!empty($arrayfields['c.datec']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date modification + if (!empty($arrayfields['c.tms']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date cloture + if (!empty($arrayfields['c.date_cloture']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Note public + if (!empty($arrayfields['c.note_public']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Note private + if (!empty($arrayfields['c.note_private']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Show shippable Icon (this creates subloops, so may be slow) + if (!empty($arrayfields['shippable']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Billed + if (!empty($arrayfields['c.facture']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Import key + if (!empty($arrayfields['c.import_key']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status + if (!empty($arrayfields['c.fk_statut']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + + print "\n"; + + $total += $obj->total_ht; + $subtotal += $obj->total_ht; + $i++; + } + + // Show total line + include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + + // If no record found + if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; + } + + $db->free($resql); + + $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); + $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print $form->select_country($search_country, 'search_country', '', 0, 'minwidth100imp maxwidth100'); + print ''; + print $form->selectarray("search_type_thirdparty", $formcompany->typent_array(0), $search_type_thirdparty, 1, 0, 0, '', 0, 0, 0, (empty($conf->global->SOCIETE_SORT_ON_TYPEENT) ? 'ASC' : $conf->global->SOCIETE_SORT_ON_TYPEENT), '', 1); + print ''; + print '
'; + print $form->selectDate($search_dateorder_start ? $search_dateorder_start : -1, 'search_dateorder_start_', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_dateorder_end ? $search_dateorder_end : -1, 'search_dateorder_end_', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; + print '
'; + print '
'; + print $form->selectDate($search_datedelivery_start ? $search_datedelivery_start : -1, 'search_datedelivery_start_', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_datedelivery_end ? $search_datedelivery_end : -1, 'search_datedelivery_end_', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; + print '
'; + $form->selectShippingMethod($search_fk_shipping_method, 'search_fk_shipping_method', '', 1, '', 1); + print ''; + $form->select_conditions_paiements($search_fk_cond_reglement, 'search_fk_cond_reglement', 1, 1, 1); + print ''; + $form->select_types_paiements($search_fk_mode_reglement, 'search_fk_mode_reglement', '', 0, 1, 1, 0, -1); + print ''; + $form->selectInputReason($search_fk_input_reason, 'search_fk_input_reason', '', 1, '', 1); + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print $form->selectMultiCurrency($search_multicurrency_code, 'search_multicurrency_code', 1); + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'; + print $form->selectDate($search_datecloture_start ? $search_datecloture_start : -1, 'search_datecloture_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search_datecloture_end ? $search_datecloture_end : -1, 'search_datecloture_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; + print '
'; + print ''; + print ''; + //print $form->selectyesno('search_shippable', $search_shippable, 1, 0, 1, 1); + if (!empty($conf->global->ORDER_SHIPABLE_STATUS_DISABLED_BY_DEFAULT)) { + print ''; + print $langs->trans('ShowShippableStatus'); + } else { + $show_shippable_command = 1; + } + print ''; + print $form->selectyesno('search_billed', $search_billed, 1, 0, 1, 1); + print ''; + print ''; + $liststatus = array( + Commande::STATUS_DRAFT=>$langs->trans("StatusOrderDraftShort"), + Commande::STATUS_VALIDATED=>$langs->trans("StatusOrderValidated"), + Commande::STATUS_SHIPMENTONPROCESS=>$langs->trans("StatusOrderSentShort"), + Commande::STATUS_CLOSED=>$langs->trans("StatusOrderDelivered"), + -3=>$langs->trans("StatusOrderValidatedShort").'+'.$langs->trans("StatusOrderSentShort").'+'.$langs->trans("StatusOrderDelivered"), + -2=>$langs->trans("StatusOrderValidatedShort").'+'.$langs->trans("StatusOrderSentShort"), + Commande::STATUS_CANCELED=>$langs->trans("StatusOrderCanceledShort") + ); + print $form->selectarray('search_status', $liststatus, $search_status, -5, 0, 0, '', 0, 0, 0, '', 'maxwidth125', 1); + print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + } + + // Détail commande + // Product Ref + if (!empty($arrayfields['pr.ref']['checked'])) { + if (!empty($obj->product_rowid)) { + $generic_product->id = $obj->product_rowid; + $generic_product->ref = $obj->product_ref; + $generic_product->label = $obj->product_label; + $generic_product->status = $obj->product_status; + $generic_product->status_buy = $obj->product_status_buy; + $generic_product->status_batch = $obj->product_batch; + $generic_product->barcode = $obj->product_barcode; + print ''.$generic_product->getNomUrl(1).'Ligne libre'.$obj->description.''.dol_escape_htmltag($labelproduct).''.$obj->qty.''; + print $generic_commande->getNomUrl(1, ($search_status != 2 ? 0 : $obj->fk_statut), 0, 0, 0, 1, 1); + + $filename = dol_sanitizeFileName($obj->ref); + $filedir = $conf->commande->multidir_output[$conf->entity].'/'.dol_sanitizeFileName($obj->ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; + print $formfile->getDocumentsLink($generic_commande->element, $filename, $filedir); + + print ''.$obj->ref_client.''; + if ($obj->project_id > 0) { + print $projectstatic->getNomUrl(1); + } + print ''; + if ($obj->project_id > 0) { + print $projectstatic->title; + } + print ''; + print $getNomUrl_cache[$obj->socid]; + + // If module invoices enabled and user with invoice creation permissions + if (isModEnabled('facture') && !empty($conf->global->ORDER_BILLING_ALL_CUSTOMER)) { + if ($user->rights->facture->creer) { + if (($obj->fk_statut > 0 && $obj->fk_statut < 3) || ($obj->fk_statut == 3 && $obj->billed == 0)) { + print ' '; + print img_picto($langs->trans("CreateInvoiceForThisCustomer").' : '.$companystatic->name, 'object_bill', 'hideonsmartphone').''; + } + } + } + print ''; + print $obj->alias; + print ''; + print $obj->town; + print ''; + print $obj->zip; + print '".$obj->state_name."'; + $tmparray = getCountry($obj->fk_pays, 'all'); + print $tmparray['label']; + print ''; + if (empty($typenArray)) { + $typenArray = $formcompany->typent_array(1); + } + print $typenArray[$obj->typent_code]; + print ''; + print dol_print_date($db->jdate($obj->date_commande), 'day'); + // Warning late icon and note + if ($generic_commande->hasDelay()) { + print img_picto($langs->trans("Late").' : '.$generic_commande->showDelay(), "warning"); + } + print ''; + print dol_print_date($db->jdate($obj->date_delivery), 'dayhour'); + print ''; + $form->formSelectShippingMethod('', $obj->fk_shipping_method, 'none', 1); + print ''; + $form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 0, '', 1, $obj->deposit_percent); + print ''; + $form->form_modes_reglement($_SERVER['PHP_SELF'], $obj->fk_mode_reglement, 'none', '', -1); + print ''; + $form->formInputReason($_SERVER['PHP_SELF'], $obj->fk_input_reason, 'none', ''); + print ''.price($obj->total_ht)."'.price($obj->total_tva)."'.price($obj->total_ttc)."'.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."'; + $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); + print "'.price($obj->multicurrency_total_ht)."'.price($obj->multicurrency_total_vat)."'.price($obj->multicurrency_total_ttc)."'; + if ($userstatic->id) { + print $userstatic->getNomUrl(-1); + } else { + print ' '; + } + print "'; + if ($obj->socid > 0) { + $listsalesrepresentatives = $companystatic->getSalesRepresentatives($user); + if ($listsalesrepresentatives < 0) { + dol_print_error($db); + } + $nbofsalesrepresentative = count($listsalesrepresentatives); + if ($nbofsalesrepresentative > 6) { + // We print only number + print $nbofsalesrepresentative; + } elseif ($nbofsalesrepresentative > 0) { + $j = 0; + foreach ($listsalesrepresentatives as $val) { + $userstatic->id = $val['id']; + $userstatic->lastname = $val['lastname']; + $userstatic->firstname = $val['firstname']; + $userstatic->email = $val['email']; + $userstatic->statut = $val['statut']; + $userstatic->entity = $val['entity']; + $userstatic->photo = $val['photo']; + $userstatic->login = $val['login']; + $userstatic->office_phone = $val['office_phone']; + $userstatic->office_fax = $val['office_fax']; + $userstatic->user_mobile = $val['user_mobile']; + $userstatic->job = $val['job']; + $userstatic->gender = $val['gender']; + //print '
': + print ($nbofsalesrepresentative < 2) ? $userstatic->getNomUrl(-1, '', 0, 0, 12) : $userstatic->getNomUrl(-2); + $j++; + if ($j < $nbofsalesrepresentative) { + print ' '; + } + //print '
'; + } + } + //else print $langs->trans("NoSalesRepresentativeAffected"); + } else { + print ' '; + } + print '
'.price($marginInfo['pa_total']).''.price($marginInfo['total_margin']).''.(($marginInfo['total_margin_rate'] == '') ? '' : price($marginInfo['total_margin_rate'], null, null, null, null, 2).'%').''.(($marginInfo['total_mark_rate'] == '') ? '' : price($marginInfo['total_mark_rate'], null, null, null, null, 2).'%').''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + print dol_print_date($db->jdate($obj->date_cloture), 'dayhour', 'tzuser'); + print ''; + print dol_string_nohtmltag($obj->note_public); + print ''; + print dol_string_nohtmltag($obj->note_private); + print ''; + if (!empty($show_shippable_command) && !empty($conf->stock->enabled)) { + if (($obj->fk_statut > $generic_commande::STATUS_DRAFT) && ($obj->fk_statut < $generic_commande::STATUS_CLOSED)) { + $generic_commande->getLinesArray(); // Load array ->lines + $generic_commande->loadExpeditions(); // Load array ->expeditions + + $numlines = count($generic_commande->lines); // Loop on each line of order + for ($lig = 0; $lig < $numlines; $lig++) { + if (isset($generic_commande->expeditions[$generic_commande->lines[$lig]->id])) { + $reliquat = $generic_commande->lines[$lig]->qty - $generic_commande->expeditions[$generic_commande->lines[$lig]->id]; + } else { + $reliquat = $generic_commande->lines[$lig]->qty; + } + if ($generic_commande->lines[$lig]->product_type == 0 && $generic_commande->lines[$lig]->fk_product > 0) { // If line is a product and not a service + $nbprod++; // order contains real products + $generic_product->id = $generic_commande->lines[$lig]->fk_product; + + // Get local and virtual stock and store it into cache + if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product])) { + $generic_product->load_stock('nobatch'); // ->load_virtual_stock() is already included into load_stock() + $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_reel; + $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique; + } else { + $generic_product->stock_reel = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stock_reel']; + $generic_product->stock_theorique = $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique; + } + + if ($reliquat > $generic_product->stock_reel) { + $notshippable++; + } + if (empty($conf->global->SHIPPABLE_ORDER_ICON_IN_LIST)) { // Default code. Default should be this case. + $text_info .= $reliquat.' x '.$generic_commande->lines[$lig]->product_ref.' '.dol_trunc($generic_commande->lines[$lig]->product_label, 20); + $text_info .= ' - '.$langs->trans("Stock").': '.$generic_product->stock_reel.''; + $text_info .= ' - '.$langs->trans("VirtualStock").': '.$generic_product->stock_theorique.''; + $text_info .= ($reliquat != $generic_commande->lines[$lig]->qty ? ' ('.$langs->trans("QtyInOtherShipments").' '.($generic_commande->lines[$lig]->qty - $reliquat).')' : ''); + $text_info .= '
'; + } else { // BUGGED CODE. + // DOES NOT TAKE INTO ACCOUNT MANUFACTURING. THIS CODE SHOULD BE USELESS. PREVIOUS CODE SEEMS COMPLETE. + // COUNT STOCK WHEN WE SHOULD ALREADY HAVE VALUE + // Detailed virtual stock, looks bugged, uncomplete and need heavy load. + // stock order and stock order_supplier + $stock_order = 0; + $stock_order_supplier = 0; + if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) { // What about other options ? + if (!empty($conf->commande->enabled)) { + if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'])) { + $generic_product->load_stats_commande(0, '1,2'); + $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer'] = $generic_product->stats_commande['qty']; + } else { + $generic_product->stats_commande['qty'] = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_customer']; + } + $stock_order = $generic_product->stats_commande['qty']; + } + if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + if (empty($productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'])) { + $generic_product->load_stats_commande_fournisseur(0, '3'); + $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier'] = $generic_product->stats_commande_fournisseur['qty']; + } else { + $generic_product->stats_commande_fournisseur['qty'] = $productstat_cache[$generic_commande->lines[$lig]->fk_product]['stats_order_supplier']; + } + $stock_order_supplier = $generic_product->stats_commande_fournisseur['qty']; + } + } + $text_info .= $reliquat.' x '.$generic_commande->lines[$lig]->ref.' '.dol_trunc($generic_commande->lines[$lig]->product_label, 20); + $text_stock_reel = $generic_product->stock_reel.'/'.$stock_order; + if ($stock_order > $generic_product->stock_reel && !($generic_product->stock_reel < $generic_commande->lines[$lig]->qty)) { + $warning++; + $text_warning .= ''.$langs->trans('Available').' : '.$text_stock_reel.''; + } + if ($reliquat > $generic_product->stock_reel) { + $text_info .= ''.$langs->trans('Available').' : '.$text_stock_reel.''; + } else { + $text_info .= ''.$langs->trans('Available').' : '.$text_stock_reel.''; + } + if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { + $text_info .= ' '.$langs->trans('SupplierOrder').' : '.$stock_order_supplier; + } + $text_info .= ($reliquat != $generic_commande->lines[$lig]->qty ? ' ('.$langs->trans("QtyInOtherShipments").' '.($generic_commande->lines[$lig]->qty - $reliquat).')' : ''); + $text_info .= '
'; + } + } + } + if ($notshippable == 0) { + $text_icon = img_picto('', 'dolly', '', false, 0, 0, '', 'green paddingleft'); + $text_info = $text_icon.' '.$langs->trans('Shippable').'
'.$text_info; + } else { + $text_icon = img_picto('', 'dolly', '', false, 0, 0, '', 'error paddingleft'); + $text_info = $text_icon.' '.$langs->trans('NonShippable').'
'.$text_info; + } + } + + if ($nbprod) { + print $form->textwithtooltip('', $text_info, 2, 1, $text_icon, '', 2); + } + if ($warning) { // Always false in default mode + print $form->textwithtooltip('', $langs->trans('NotEnoughForAllOrders').'
'.$text_warning, 2, 1, img_picto('', 'error'), '', 2); + } + } + print '
'.yn($obj->billed).''.$obj->import_key.''.$generic_commande->LibStatut($obj->fk_statut, $obj->billed, 5, 1).''; + 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + } + print '
'.$langs->trans("NoRecordFound").'
'."\n"; + print '
'; + + print '
'."\n"; + + $hidegeneratedfilelistifempty = 1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) { + $hidegeneratedfilelistifempty = 0; + } + + // Show list of available documents + $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource .= str_replace('&', '&', $param); + + $filedir = $diroutputmassaction; + $genallowed = $permissiontoread; + $delallowed = $permissiontoadd; + + print $formfile->showdocuments('massfilesarea_orders', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); +} else { + dol_print_error($db); +} + +// End of page +llxFooter(); +$db->close(); From 5eb495224b1f73ccd960b1d0ce03681d932337ba Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 23 Aug 2022 10:51:38 +0200 Subject: [PATCH 026/816] clean --- htdocs/commande/list.php | 50 +--------------------------------------- 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 1b74238db1c..dbb99d0f993 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -11,7 +11,7 @@ * Copyright (C) 2015 Jean-François Ferry * Copyright (C) 2016-2021 Ferran Marcet * Copyright (C) 2018 Charlene Benke - * Copyright (C) 2021 Anthony Berton + * Copyright (C) 2021 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 @@ -71,9 +71,6 @@ $search_dateorder_end = dol_mktime(23, 59, 59, GETPOST('search_dateorder_end_mon $search_datedelivery_start = dol_mktime(0, 0, 0, GETPOST('search_datedelivery_start_month', 'int'), GETPOST('search_datedelivery_start_day', 'int'), GETPOST('search_datedelivery_start_year', 'int')); $search_datedelivery_end = dol_mktime(23, 59, 59, GETPOST('search_datedelivery_end_month', 'int'), GETPOST('search_datedelivery_end_day', 'int'), GETPOST('search_datedelivery_end_year', 'int')); $search_product_category = GETPOST('search_product_category', 'int'); - - - $search_ref = GETPOST('search_ref', 'alpha') != '' ?GETPOST('search_ref', 'alpha') : GETPOST('sref', 'alpha'); $search_ref_customer = GETPOST('search_ref_customer', 'alpha'); $search_company = GETPOST('search_company', 'alpha'); @@ -207,9 +204,6 @@ $arrayfields = array( 'c.import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>999), 'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000) ); - - - // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; @@ -245,8 +239,6 @@ if (empty($reshook)) { $search_user = ''; $search_sale = ''; $search_product_category = ''; - $search_refProduct = ''; - $search_descProduct = ''; $search_ref = ''; $search_ref_customer = ''; $search_company = ''; @@ -800,9 +792,6 @@ $sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label, $sql .= ' u.login, u.lastname, u.firstname, u.email as user_email, u.statut as user_statut, u.entity, u.photo, u.office_phone, u.office_fax, u.user_mobile, u.job, u.gender,'; $sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shipping_method,'; $sql .= ' c.fk_input_reason, c.import_key'; - - - if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ", cc.fk_categorie, cc.fk_soc"; } @@ -823,11 +812,7 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_societe as cc ON s.rowid = cc.fk_soc"; // We'll need this table joined to the select in order to filter by categ } - - $sql .= ', '.MAIN_DB_PREFIX.'commande as c'; - - if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_extrafields as ef on (c.rowid = ef.fk_object)"; } @@ -865,13 +850,6 @@ if ($socid > 0) { if (empty($user->rights->societe->client->voir) && !$socid) { $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id); } -if ($search_refProduct) { - $sql .= natural_search('pr.ref', $search_refProduct); -} -if ($search_descProduct) { - $sql .= natural_search('pr.label', $search_descProduct); - $sql .= natural_search('cdet.description', $search_descProduct); -} if ($search_ref) { $sql .= natural_search('c.ref', $search_ref); } @@ -1336,8 +1314,6 @@ if ($resql) { print '
'; } - - if ($sall) { foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); @@ -1418,7 +1394,6 @@ if ($resql) { print ''."\n"; print ''; - // Action column if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print ''; } - - // Product Description - if (!empty($arrayfields['pr.desc']['checked'])) { - print ''; - } - // Product QtyOrdered - if (!empty($arrayfields['cdet.qty']['checked'])) { - print ''; - } - // Ref if (!empty($arrayfields['c.ref']['checked'])) { print ''; } - if (!empty($arrayfields['c.total_ht']['checked'])) { + if (!empty($arrayfields['cdet.total_ht']['checked'])) { // Amount print ''; } - if (!empty($arrayfields['c.total_ttc']['checked'])) { + if (!empty($arrayfields['cdet.total_ttc']['checked'])) { // Amount print '\n"; if (!$i) { $totalarray['nbfield']++; } if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'c.total_ht'; + $totalarray['pos'][$totalarray['nbfield']] = 'cdet.total_ht'; } - if (isset($totalarray['val']['c.total_ht'])) { - $totalarray['val']['c.total_ht'] += $obj->total_ht; + if (isset($totalarray['val']['cdet.total_ht'])) { + $totalarray['val']['cdet.total_ht'] += $obj->total_ht; } else { - $totalarray['val']['c.total_ht'] = $obj->total_ht; + $totalarray['val']['cdet.total_ht'] = $obj->total_ht; } } // Amount VAT @@ -2216,20 +1708,20 @@ if ($resql) { $totalarray['nbfield']++; } if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'c.total_tva'; + $totalarray['pos'][$totalarray['nbfield']] = 'cdet.total_tva'; } - $totalarray['val']['c.total_tva'] += $obj->total_tva; + $totalarray['val']['cdet.total_tva'] += $obj->total_tva; } // Amount TTC - if (!empty($arrayfields['c.total_ttc']['checked'])) { + if (!empty($arrayfields['cdet.total_ttc']['checked'])) { print '\n"; if (!$i) { $totalarray['nbfield']++; } if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'c.total_ttc'; + $totalarray['pos'][$totalarray['nbfield']] = 'cdet.total_ttc'; } - $totalarray['val']['c.total_ttc'] += $obj->total_ttc; + $totalarray['val']['cdet.total_ttc'] += $obj->total_ttc; } // Currency From 62163ae903a3f0c9e0d37f343c4497d5e765f4cb Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 23 Aug 2022 14:47:54 +0200 Subject: [PATCH 029/816] Add in auguria menu --- htdocs/core/menus/init_menu_auguria.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index 96625dd1f95..6821b065010 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -178,6 +178,7 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled && $leftmenu=="orders"', __HANDLER__, 'left', 1207__+MAX_llx_menu__, 'commercial', '', 1202__+MAX_llx_menu__, '/commande/list.php?mainmenu=commercial&leftmenu=orders&search_status=4', 'StatusOrderProcessed', 1, 'orders', '$user->rights->commande->lire', '', 2, 6, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled && $leftmenu=="orders"', __HANDLER__, 'left', 1208__+MAX_llx_menu__, 'commercial', '', 1202__+MAX_llx_menu__, '/commande/list.php?mainmenu=commercial&leftmenu=orders&search_status=-1', 'StatusOrderCanceledShort', 1, 'orders', '$user->rights->commande->lire', '', 2, 7, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled', __HANDLER__, 'left', 1209__+MAX_llx_menu__, 'commercial', '', 1200__+MAX_llx_menu__, '/commande/stats/index.php?mainmenu=commercial&leftmenu=orders', 'Statistics', 1, 'orders', '$user->rights->commande->lire', '', 2, 4, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled && $conf->global->MAIN_FEATURES_LEVEL >= 2 && empty($user->socid)', __HANDLER__, 'left', 1210__+MAX_llx_menu__, 'commercial', '', 1200__+MAX_llx_menu__, '/commande/list_line.php?mainmenu=commercial&leftmenu=orders', 'ListOrderLigne', 1, 'orders', '$user->rights->commande->lire', '', 2, 1, __ENTITY__); -- Commercial - Supplier's proposals insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_proposal->enabled', __HANDLER__, 'left', 1650__+MAX_llx_menu__, 'commercial', 'propals_supplier', 3__+MAX_llx_menu__, '/supplier_proposal/index.php?leftmenu=propals_supplier', 'SupplierProposalsShort', 0, 'supplier_proposal', '$user->rights->supplier_proposal->lire', '', 2, 4, __ENTITY__); From 19248016bf05e8f77946035731c5643331fc12db Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 23 Aug 2022 15:40:12 +0200 Subject: [PATCH 030/816] Fix - $generic_commande mount --- htdocs/commande/list_line.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index 9437daebf33..cb7d76e8930 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -350,8 +350,9 @@ $sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.pho $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= " country.code as country_code,"; -$sql .= ' c.rowid, c.ref, c.ref_client, c.fk_user_author,'; +$sql .= ' c.rowid as c_rowid, c.ref, c.ref_client, c.fk_user_author,'; $sql .= ' c.fk_multicurrency, c.multicurrency_code, c.multicurrency_tx, c.multicurrency_total_ht, c.multicurrency_total_tva as multicurrency_total_vat, c.multicurrency_total_ttc,'; +$sql .= ' c.total_ht as c_total_ht, c.total_tva as c_total_tva, c.total_ttc as c_total_ttc,'; $sql .= ' c.date_valid, c.date_commande, c.note_public, c.note_private, c.date_livraison as date_delivery, c.fk_statut, c.facture as billed,'; $sql .= ' c.date_creation as date_creation, c.tms as date_update, c.date_cloture as date_cloture,'; $sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label,'; @@ -601,12 +602,12 @@ if ($resql) { if ($socid > 0) { $soc = new Societe($db); $soc->fetch($socid); - $title = $langs->trans('CustomersOrders').' - '.$soc->name; + $title = $langs->trans('ListOrderLigne').' - '.$soc->name; if (empty($search_company)) { $search_company = $soc->name; } } else { - $title = $langs->trans('CustomersOrders'); + $title = $langs->trans('ListOrderLigne'); } if (strval($search_status) == '0') { $title .= ' - '.$langs->trans('StatusOrderDraftShort'); @@ -1419,7 +1420,7 @@ if ($resql) { $getNomUrl_cache[$obj->socid] = $companystatic->getNomUrl(1, 'customer'); } - $generic_commande->id = $obj->rowid; + $generic_commande->id = $obj->c_rowid; $generic_commande->ref = $obj->ref; $generic_commande->statut = $obj->fk_statut; $generic_commande->billed = $obj->billed; @@ -1427,9 +1428,9 @@ if ($resql) { $generic_commande->date_livraison = $db->jdate($obj->date_delivery); // deprecated $generic_commande->delivery_date = $db->jdate($obj->date_delivery); $generic_commande->ref_client = $obj->ref_client; - $generic_commande->total_ht = $obj->total_ht; - $generic_commande->total_tva = $obj->total_tva; - $generic_commande->total_ttc = $obj->total_ttc; + $generic_commande->total_ht = $obj->c_total_ht; + $generic_commande->total_tva = $obj->c_total_tva; + $generic_commande->total_ttc = $obj->c_total_ttc; $generic_commande->note_public = $obj->note_public; $generic_commande->note_private = $obj->note_private; From 6d625d6128bb1656d8dfe2ccf58aa0977053fe04 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 23 Aug 2022 20:09:40 +0200 Subject: [PATCH 031/816] Add options for clean list --- htdocs/commande/list_line.php | 14 +++++++++++++- htdocs/langs/en_US/orders.lang | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index cb7d76e8930..d564daf27ab 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -57,6 +57,8 @@ $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'orderlist'; +$productonly = GETPOST('productonly', 'alpha'); +$disablelinefree = GETPOST('disablelinefree', 'alpha'); $search_datecloture_start = GETPOST('search_datecloture_start', 'int'); if (empty($search_datecloture_start)) { @@ -361,7 +363,7 @@ $sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shippin $sql .= ' c.fk_input_reason, c.import_key'; // Détail commande -$sql .= ', cdet.rowid, cdet.description, cdet.qty, cdet.total_ht, cdet.total_tva, cdet.total_ttc, '; +$sql .= ', cdet.rowid, cdet.description, cdet.qty, cdet.product_type, cdet.fk_product, cdet.total_ht, cdet.total_tva, cdet.total_ttc, '; $sql .= ' pr.rowid as product_rowid, pr.ref as product_ref, pr.label as product_label, pr.barcode as product_barcode, pr.tobatch as product_batch, pr.tosell as product_status, pr.tobuy as product_status_buy'; if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { @@ -418,6 +420,13 @@ $sql .= $hookmanager->resPrint; $sql .= ' WHERE c.fk_soc = s.rowid'; $sql .= ' AND c.entity IN ('.getEntity('commande').')'; + +if (!empty($productonly)) { + $sql .= " AND (cdet.product_type = 0 OR cdet.product_type = 1)"; +} +if (!empty($disablelinefree)) { + $sql .= " AND cdet.fk_product IS NOT NULL"; +} if ($search_product_category > 0) { $sql .= " AND cp.fk_categorie = ".((int) $search_product_category); } @@ -830,6 +839,9 @@ if ($resql) { print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'order', 0, $newcardbutton, '', $limit, 0, 0, 1); + print ''; + print ''; + $topicmail = "SendOrderRef"; $modelmail = "order_send"; $objecttmp = new Commande($db); diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index cb64d1b603a..a465fc41ea6 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -97,6 +97,8 @@ NumberOfOrdersByMonth=Number of orders by month AmountOfOrdersByMonthHT=Amount of orders by month (excl. tax) ListOfOrders=List of orders ListOrderLigne=Lines of orders +productonly=Lines products only +disablelinefree=No lines free CloseOrder=Close order ConfirmCloseOrder=Are you sure you want to set this order to delivered? Once an order is delivered, it can be set to billed. ConfirmDeleteOrder=Are you sure you want to delete this order? From 8cc9d72b37a534b5d90556ba9cb1a1f846c3b18c Mon Sep 17 00:00:00 2001 From: GregM Date: Tue, 30 Aug 2022 16:53:14 +0200 Subject: [PATCH 032/816] update sql --- htdocs/contact/class/contact.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index ce74f82b412..3ae7e7d8645 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1777,12 +1777,11 @@ class Contact extends CommonObject $sql .= " FROM ".MAIN_DB_PREFIX."c_type_contact tc"; $sql .= ", ".MAIN_DB_PREFIX."societe_contacts sc"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."socpeople sp"; - $sql .= " ON sc.fk_socpeople = sp.rowid"; + $sql .= " ON sc.fk_socpeople = sp.rowid AND sp.statut = 1"; $sql .= " WHERE sc.fk_soc =".((int) $this->socid); $sql .= " AND sc.fk_c_type_contact=tc.rowid"; $sql .= " AND tc.element = '".$this->db->escape($element)."'"; $sql .= " AND tc.active = 1"; - $sql .= " AND sp.statut = 1"; dol_syslog(__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); From c0c12a40b088b57694981844bc2d130958b15e88 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 1 Sep 2022 16:37:13 +0200 Subject: [PATCH 033/816] Fix inithook --- htdocs/commande/list_line.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index d564daf27ab..7ea36fe8d09 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -146,7 +146,7 @@ $show_shippable_command = GETPOST('show_shippable_command', 'aZ09'); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $object = new Commande($db); -$hookmanager->initHooks(array('orderlist')); +$hookmanager->initHooks(array('orderlistdetail')); $extrafields = new ExtraFields($db); // fetch optionals attributes and labels From 6e6a62d167d4ac9d48b937c0b6e98c3dbca7438e Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 7 Sep 2022 14:58:07 +0200 Subject: [PATCH 034/816] NEW set payment default values when supplier order created from reception --- htdocs/fourn/facture/card.php | 95 +++++++++++++++++++++++++++++--- htdocs/reception/list.php | 100 ++++++++++++++++++++++++++++++++-- 2 files changed, 181 insertions(+), 14 deletions(-) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 2f8f3f2adae..d096d02d92c 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1954,15 +1954,93 @@ if ($action == 'create') { $projectid = (!empty($objectsrc->fk_project) ? $objectsrc->fk_project : ''); //$ref_client = (!empty($objectsrc->ref_client)?$object->ref_client:''); - $soc = $objectsrc->thirdparty; - $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_supplier_id) ? $soc->cond_reglement_supplier_id : 0)); // TODO maybe add default value option - $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_supplier_id) ? $soc->mode_reglement_supplier_id : 0)); - $fk_account = (!empty($objectsrc->fk_account) ? $objectsrc->fk_account : (!empty($soc->fk_account) ? $soc->fk_account : 0)); - $remise_percent = (!empty($objectsrc->remise_percent) ? $objectsrc->remise_percent : (!empty($soc->remise_supplier_percent) ? $soc->remise_supplier_percent : 0)); - $remise_absolue = (!empty($objectsrc->remise_absolue) ? $objectsrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0)); - $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ?-1 : ''; - $transport_mode_id = (!empty($objectsrc->transport_mode_id) ? $objectsrc->transport_mode_id : (!empty($soc->transport_mode_id) ? $soc->transport_mode_id : 0)); + + $cond_reglement_id = 0; + $mode_reglement_id = 0; + $fk_account = 0; + $remise_percent = 0; + $remise_absolue = 0; + $transport_mode_id = 0; + + // set from object source + if (!empty($objectsrc->cond_reglement_id)) { + $cond_reglement_id = $objectsrc->cond_reglement_id; + } + if (!empty($objectsrc->mode_reglement_id)) { + $mode_reglement_id = $objectsrc->mode_reglement_id; + } + if (!empty($objectsrc->fk_account)) { + $fk_account = $objectsrc->fk_account; + } + if (!empty($objectsrc->remise_percent)) { + $remise_percent = $objectsrc->remise_percent; + } + if (!empty($objectsrc->remise_absolue)) { + $remise_absolue = $objectsrc->remise_absolue; + } + if (!empty($objectsrc->transport_mode_id)) { + $transport_mode_id = $objectsrc->transport_mode_id; + } + + if (empty($cond_reglement_id) + || empty($mode_reglement_id) + || empty($fk_account) + || empty($remise_percent) + || empty($remise_absolue) + || empty($transport_mode_id) + ) { + if ($origin == 'reception') { + // try to get from source of reception (supplier order) + if (!isset($objectsrc->supplier_order)) { + $objectsrc->fetch_origin(); + } + + if (!empty($objectsrc->commandeFournisseur)) { + $supplierOrder = $objectsrc->commandeFournisseur; + if (empty($cond_reglement_id) && !empty($supplierOrder->cond_reglement_id)) { + $cond_reglement_id = $supplierOrder->cond_reglement_id; + } + if (empty($mode_reglement_id) && !empty($supplierOrder->mode_reglement_id)) { + $mode_reglement_id = $supplierOrder->mode_reglement_id; + } + if (empty($fk_account) && !empty($supplierOrder->fk_account)) { + $fk_account = $supplierOrder->fk_account; + } + if (empty($remise_percent) && !empty($supplierOrder->remise_percent)) { + $remise_percent = $supplierOrder->remise_percent; + } + if (empty($remise_absolue) && !empty($supplierOrder->remise_absolue)) { + $remise_absolue = $supplierOrder->remise_absolue; + } + if (empty($transport_mode_id) && !empty($supplierOrder->transport_mode_id)) { + $transport_mode_id = $supplierOrder->transport_mode_id; + } + } + } + + // try to get from third-party of source object + if (!empty($soc)) { + if (empty($cond_reglement_id) && !empty($soc->cond_reglement_supplier_id)) { + $cond_reglement_id = $soc->cond_reglement_supplier_id; + } + if (empty($mode_reglement_id) && !empty($soc->mode_reglement_supplier_id)) { + $mode_reglement_id = $soc->mode_reglement_supplier_id; + } + if (empty($fk_account) && !empty($soc->fk_account)) { + $fk_account = $soc->fk_account; + } + if (empty($remise_percent) && !empty($soc->remise_supplier_percent)) { + $remise_percent = $soc->remise_supplier_percent; + } + if (empty($remise_absolue) && !empty($soc->remise_absolue)) { + $remise_absolue = $soc->remise_absolue; + } + if (empty($transport_mode_id) && !empty($soc->transport_mode_id)) { + $transport_mode_id = $soc->transport_mode_id; + } + } + } if (isModEnabled("multicurrency")) { if (!empty($objectsrc->multicurrency_code)) { @@ -1973,6 +2051,7 @@ if ($action == 'create') { } } + $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ?-1 : ''; $datetmp = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); $dateinvoice = ($datetmp == '' ? (empty($conf->global->MAIN_AUTOFILL_DATE) ?-1 : '') : $datetmp); $datetmp = dol_mktime(12, 0, 0, GETPOST('echmonth', 'int'), GETPOST('echday', 'int'), GETPOST('echyear', 'int')); diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php index 88c86168678..a6ed1ad935e 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -219,15 +219,98 @@ if (empty($reshook)) { } } } else { + $cond_reglement_id = 0; + $mode_reglement_id = 0; + $fk_account = 0; + $remise_percent = 0; + $remise_absolue = 0; + $transport_mode_id = 0; + if (!empty($rcp->cond_reglement_id)) { + $cond_reglement_id = $rcp->cond_reglement_id; + } + if (!empty($rcp->mode_reglement_id)) { + $mode_reglement_id = $rcp->mode_reglement_id; + } + if (!empty($rcp->fk_account)) { + $fk_account = $rcp->fk_account; + } + if (!empty($rcp->remise_percent)) { + $remise_percent = $rcp->remise_percent; + } + if (!empty($rcp->remise_absolue)) { + $remise_absolue = $rcp->remise_absolue; + } + if (!empty($rcp->transport_mode_id)) { + $transport_mode_id = $rcp->transport_mode_id; + } + + if (empty($cond_reglement_id) + || empty($mode_reglement_id) + || empty($fk_account) + || empty($remise_percent) + || empty($remise_absolue) + || empty($transport_mode_id) + ) { + if (!isset($rcp->supplier_order)) { + $rcp->fetch_origin(); + } + + // try to get from source of reception (supplier order) + if (!empty($rcp->commandeFournisseur)) { + $supplierOrder = $rcp->commandeFournisseur; + if (empty($cond_reglement_id) && !empty($supplierOrder->cond_reglement_id)) { + $cond_reglement_id = $supplierOrder->cond_reglement_id; + } + if (empty($mode_reglement_id) && !empty($supplierOrder->mode_reglement_id)) { + $mode_reglement_id = $supplierOrder->mode_reglement_id; + } + if (empty($fk_account) && !empty($supplierOrder->fk_account)) { + $fk_account = $supplierOrder->fk_account; + } + if (empty($remise_percent) && !empty($supplierOrder->remise_percent)) { + $remise_percent = $supplierOrder->remise_percent; + } + if (empty($remise_absolue) && !empty($supplierOrder->remise_absolue)) { + $remise_absolue = $supplierOrder->remise_absolue; + } + if (empty($transport_mode_id) && !empty($supplierOrder->transport_mode_id)) { + $transport_mode_id = $supplierOrder->transport_mode_id; + } + } + + // try get from third-party of reception + if (!empty($rcp->thirdparty)) { + $soc = $rcp->thirdparty; + if (empty($cond_reglement_id) && !empty($soc->cond_reglement_supplier_id)) { + $cond_reglement_id = $soc->cond_reglement_supplier_id; + } + if (empty($mode_reglement_id) && !empty($soc->mode_reglement_supplier_id)) { + $mode_reglement_id = $soc->mode_reglement_supplier_id; + } + if (empty($fk_account) && !empty($soc->fk_account)) { + $fk_account = $soc->fk_account; + } + if (empty($remise_percent) && !empty($soc->remise_supplier_percent)) { + $remise_percent = $soc->remise_supplier_percent; + } + if (empty($remise_absolue) && !empty($soc->remise_absolue)) { + $remise_absolue = $soc->remise_absolue; + } + if (empty($transport_mode_id) && !empty($soc->transport_mode_id)) { + $transport_mode_id = $soc->transport_mode_id; + } + } + } + // If we want one invoice per reception or if there is no first invoice yet for this thirdparty. $objecttmp->socid = $rcp->socid; $objecttmp->type = $objecttmp::TYPE_STANDARD; - $objecttmp->cond_reglement_id = $rcp->cond_reglement_id || $rcp->thirdparty->cond_reglement_supplier_id; - $objecttmp->mode_reglement_id = $rcp->mode_reglement_id || $rcp->thirdparty->mode_reglement_supplier_id; - - $objecttmp->fk_account = !empty($rcp->thirdparty->fk_account) ? $rcp->thirdparty->fk_account : 0; - $objecttmp->remise_percent = !empty($rcp->thirdparty->remise_percent) ? $rcp->thirdparty->remise_percent : 0; - $objecttmp->remise_absolue = !empty($rcp->thirdparty->remise_absolue) ? $rcp->thirdparty->remise_absolue : 0; + $objecttmp->cond_reglement_id = $cond_reglement_id; + $objecttmp->mode_reglement_id = $mode_reglement_id; + $objecttmp->fk_account = $fk_account; + $objecttmp->remise_percent = $remise_percent; + $objecttmp->remise_absolue = $remise_absolue; + $objecttmp->transport_mode_id = $transport_mode_id; $objecttmp->fk_project = $rcp->fk_project; //$objecttmp->multicurrency_code = $rcp->multicurrency_code; @@ -247,6 +330,11 @@ if (empty($reshook)) { $objecttmp->origin = 'reception'; $objecttmp->origin_id = $id_reception; + // Auto calculation of date due if not filled by user + if (empty($objecttmp->date_echeance)) { + $objecttmp->date_echeance = $objecttmp->calculate_date_lim_reglement(); + } + $objecttmp->array_options = $rcp->array_options; // Copy extrafields // Set $objecttmp->linked_objects with all links order_supplier existing on reception, so same links will be added to the generated supplier invoice From 1833add141e439011e56691b6f038907ba7adfc3 Mon Sep 17 00:00:00 2001 From: Quentin VIAL-GOUTEYRON Date: Thu, 8 Sep 2022 10:12:40 +0200 Subject: [PATCH 035/816] FIX theorical stock when stock calculate on bill --- htdocs/product/class/product.class.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 0900f11ed29..bb04f6e9359 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2990,7 +2990,6 @@ class Product extends CommonObject $sql .= " JOIN ".MAIN_DB_PREFIX."commande c ON el.fk_source = c.rowid "; $sql .= " WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).") AND c.facture = 0 AND fd.fk_product = ".((int) $this->id); dol_syslog(__METHOD__.":: sql $sql", LOG_NOTICE); - $resql = $this->db->query($sql); if ($resql) { if ($this->db->num_rows($resql) > 0) { @@ -2999,6 +2998,24 @@ class Product extends CommonObject } } + $this->stats_commande['qty'] -= $adeduire; + } else { + //For every order having invoice already validated we need to decrease stock cause it's in physical stock + $adeduire = 0; + $sql = 'SELECT sum(fd.qty) as count FROM '.MAIN_DB_PREFIX.'facturedet fd '; + $sql .= ' JOIN '.MAIN_DB_PREFIX.'facture f ON fd.fk_facture = f.rowid '; + $sql .= ' JOIN '.MAIN_DB_PREFIX."element_element el ON el.fk_target = f.rowid and el.targettype = 'facture' and sourcetype = 'commande'"; + $sql .= ' JOIN '.MAIN_DB_PREFIX.'commande c ON el.fk_source = c.rowid '; + $sql .= ' WHERE c.fk_statut IN ('.$this->db->sanitize($filtrestatut).') AND f.fk_statut > '.Facture::STATUS_DRAFT.' AND fd.fk_product = '.((int) $this->id); + dol_syslog(__METHOD__.":: sql $sql", LOG_NOTICE); + $resql = $this->db->query($sql); + if($resql) { + if($this->db->num_rows($resql) > 0) { + $obj = $this->db->fetch_object($resql); + $adeduire += $obj->count; + } + } + $this->stats_commande['qty'] -= $adeduire; } } From c4793fdb06a6f59f85defe372621c8c270df999a Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 8 Sep 2022 08:32:08 +0000 Subject: [PATCH 036/816] Fixing style errors. --- htdocs/product/class/product.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index bb04f6e9359..5a1385deb6f 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3009,8 +3009,8 @@ class Product extends CommonObject $sql .= ' WHERE c.fk_statut IN ('.$this->db->sanitize($filtrestatut).') AND f.fk_statut > '.Facture::STATUS_DRAFT.' AND fd.fk_product = '.((int) $this->id); dol_syslog(__METHOD__.":: sql $sql", LOG_NOTICE); $resql = $this->db->query($sql); - if($resql) { - if($this->db->num_rows($resql) > 0) { + if ($resql) { + if ($this->db->num_rows($resql) > 0) { $obj = $this->db->fetch_object($resql); $adeduire += $obj->count; } From 4fcfe966903ad783639492bc2c0039e2c7553ef9 Mon Sep 17 00:00:00 2001 From: Quentin VIAL-GOUTEYRON Date: Wed, 14 Sep 2022 09:45:18 +0200 Subject: [PATCH 037/816] fix two sides --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index bb04f6e9359..670b4548228 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3004,7 +3004,7 @@ class Product extends CommonObject $adeduire = 0; $sql = 'SELECT sum(fd.qty) as count FROM '.MAIN_DB_PREFIX.'facturedet fd '; $sql .= ' JOIN '.MAIN_DB_PREFIX.'facture f ON fd.fk_facture = f.rowid '; - $sql .= ' JOIN '.MAIN_DB_PREFIX."element_element el ON el.fk_target = f.rowid and el.targettype = 'facture' and sourcetype = 'commande'"; + $sql .= ' JOIN '.MAIN_DB_PREFIX."element_element el ON ((el.fk_target = f.rowid AND el.targettype = 'facture' AND sourcetype = 'commande') OR (el.fk_source = f.rowid AND el.targettype = 'commande' AND sourcetype = 'facture'))"; $sql .= ' JOIN '.MAIN_DB_PREFIX.'commande c ON el.fk_source = c.rowid '; $sql .= ' WHERE c.fk_statut IN ('.$this->db->sanitize($filtrestatut).') AND f.fk_statut > '.Facture::STATUS_DRAFT.' AND fd.fk_product = '.((int) $this->id); dol_syslog(__METHOD__.":: sql $sql", LOG_NOTICE); From 18be0b4f271d428e13949c2fc9441b9576c5a6a6 Mon Sep 17 00:00:00 2001 From: Quentin VIAL-GOUTEYRON Date: Tue, 20 Sep 2022 14:44:43 +0200 Subject: [PATCH 038/816] FIX missing facture class inclusion --- htdocs/product/class/product.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 705081484fe..ca2418a0ab1 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2926,7 +2926,6 @@ class Product extends CommonObject { // phpcs:enable global $conf, $user, $hookmanager; - $sql = "SELECT COUNT(DISTINCT c.fk_soc) as nb_customers, COUNT(DISTINCT c.rowid) as nb,"; $sql .= " COUNT(cd.rowid) as nb_rows, SUM(cd.qty) as qty"; $sql .= " FROM ".MAIN_DB_PREFIX."commandedet as cd"; @@ -3000,6 +2999,8 @@ class Product extends CommonObject $this->stats_commande['qty'] -= $adeduire; } else { + include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + //For every order having invoice already validated we need to decrease stock cause it's in physical stock $adeduire = 0; $sql = 'SELECT sum(fd.qty) as count FROM '.MAIN_DB_PREFIX.'facturedet fd '; From dc3d0c5c2e78bbe9c9fa1156b96c19422abeeaa3 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 28 Sep 2022 11:04:09 +0200 Subject: [PATCH 039/816] FIX duplicate invoice date --- htdocs/fourn/facture/card.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index d096d02d92c..e6c16d03eed 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -2050,10 +2050,9 @@ if ($action == 'create') { $currency_tx = $objectsrc->multicurrency_tx; } } - - $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ?-1 : ''; + $datetmp = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - $dateinvoice = ($datetmp == '' ? (empty($conf->global->MAIN_AUTOFILL_DATE) ?-1 : '') : $datetmp); + $dateinvoice = ($datetmp == '' ? (empty($conf->global->MAIN_AUTOFILL_DATE) ? -1 : '') : $datetmp); $datetmp = dol_mktime(12, 0, 0, GETPOST('echmonth', 'int'), GETPOST('echday', 'int'), GETPOST('echyear', 'int')); $datedue = ($datetmp == '' ?-1 : $datetmp); From 4bcd9220e64d6784453ef324c59b7c6a9bc836c5 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 28 Sep 2022 11:13:21 +0200 Subject: [PATCH 040/816] FIX stickler-ci --- htdocs/fourn/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index e6c16d03eed..d342ddc79d6 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -2050,7 +2050,7 @@ if ($action == 'create') { $currency_tx = $objectsrc->multicurrency_tx; } } - + $datetmp = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); $dateinvoice = ($datetmp == '' ? (empty($conf->global->MAIN_AUTOFILL_DATE) ? -1 : '') : $datetmp); $datetmp = dol_mktime(12, 0, 0, GETPOST('echmonth', 'int'), GETPOST('echday', 'int'), GETPOST('echyear', 'int')); From c268cf379c100c382fe90710ae2ca950edcbacfa Mon Sep 17 00:00:00 2001 From: lvessiller Date: Fri, 30 Sep 2022 14:00:06 +0200 Subject: [PATCH 041/816] FIX full day event compare start date in future --- htdocs/comm/action/list.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 674348d6158..d5fb64ec471 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -944,16 +944,17 @@ while ($i < $imaxinloop) { $event_more_class = ''; $event_start_date_style = ''; $event_start_date_time = $actionstatic->datep; - if ($obj->fulldayevent == 1) { - $today_start_date_time = $today_start_time; - } else { - $today_start_date_time = $now; - } - if ($event_start_date_time > $today_start_date_time) { + if ($event_start_date_time > $now) { // future event $event_more_class = 'event-future'; $event_start_date_color = $conf->global->AGENDA_EVENT_FUTURE_COLOR; } else { + if ($obj->fulldayevent == 1) { + $today_start_date_time = $today_start_time; + } else { + $today_start_date_time = $now; + } + // check event end date $event_end_date_time = $db->jdate($obj->dp2); if ($event_end_date_time != null && $event_end_date_time < $today_start_date_time) { From 069371fc954597341c3f7e889f8919c507e73174 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Fri, 30 Sep 2022 14:12:03 +0200 Subject: [PATCH 042/816] FIX reload stickler-ci From f18c84621266c9ff6bee315050318070cafab054 Mon Sep 17 00:00:00 2001 From: lvessiller Date: Mon, 3 Oct 2022 14:33:08 +0200 Subject: [PATCH 043/816] FIX user owner cache in event list --- htdocs/comm/action/list.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index d5fb64ec471..8a811a90f22 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -273,7 +273,6 @@ if (empty($reshook)) { */ $form = new Form($db); -$userstatic = new User($db); $formactions = new FormActions($db); $actionstatic = new ActionComm($db); @@ -927,6 +926,7 @@ while ($i < $imaxinloop) { // cache of user list (owners) if ($obj->fk_user_action > 0 && !isset($cache_user_list[$obj->fk_user_action])) { + $userstatic = new User($db); $res = $userstatic->fetch($obj->fk_user_action); if ($res > 0) { $cache_user_list[$obj->fk_user_action] = $userstatic; @@ -988,6 +988,7 @@ while ($i < $imaxinloop) { if (!empty($arrayfields['owner']['checked'])) { print ''; } - print ''; + if (!$i) { $totalarray['nbfield']++; } From cb3680a91bcc275357286757269846102157115f Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 26 Oct 2022 15:43:59 +0200 Subject: [PATCH 051/816] FIX - td --- htdocs/commande/list_det.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index 089c5dedbe1..7cd3f61c16d 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -1479,6 +1479,7 @@ if ($resql) { } print ''; } + print ''; } // Détail commande From 0f842fdb3a42b65cf254ff3d5aa9fc35bc30fe60 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 26 Oct 2022 16:02:25 +0200 Subject: [PATCH 052/816] FIX - $totalarray['nbfield']++; --- htdocs/commande/list_det.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index 7cd3f61c16d..cac3d3e50e6 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -1480,6 +1480,9 @@ if ($resql) { print ''; } print ''; + if (!$i) { + $totalarray['nbfield']++; + } } // Détail commande @@ -2100,10 +2103,9 @@ if ($resql) { print ''; } print ''; - } - - if (!$i) { - $totalarray['nbfield']++; + if (!$i) { + $totalarray['nbfield']++; + } } print "\n"; @@ -2112,7 +2114,7 @@ if ($resql) { $subtotal += $obj->total_ht; $i++; } - + var_dump($totalarray['nbfield']); // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; From 6c4b77a23c818c9b4225a2cd0659e7e93996835c Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 26 Oct 2022 18:35:58 +0200 Subject: [PATCH 053/816] Hook --- htdocs/commande/list_det.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index cac3d3e50e6..18c096d38c7 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -1911,7 +1911,7 @@ if ($resql) { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Fields from hook $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Date creation @@ -2107,7 +2107,8 @@ if ($resql) { $totalarray['nbfield']++; } } - + // $totalarray['nbfield']--; + // $totalarray['nbfield']--; print "\n"; $total += $obj->total_ht; From 1fc644572d678e455bcbc9d55b7c5ecfd601a556 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Sat, 29 Oct 2022 21:45:45 +0200 Subject: [PATCH 054/816] FIX - totalarray --- htdocs/commande/list_det.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index 18c096d38c7..7dcd8fb3835 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -1415,8 +1415,11 @@ if ($resql) { // Détail commande $totalqty = 0; + $totalarray = array(); + $totalarray['nbfield'] = 0; + $totalarray['val']['cdet.total_tva'] = 0; + $totalarray['val']['cdet.total_ttc'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); - $last_num = min($num, $limit); while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); @@ -1517,9 +1520,6 @@ if ($resql) { // Product QtyOrdered if (!empty($arrayfields['cdet.qty']['checked'])) { print ''; - if (!$i) { - $totalarray['nbfield']++; - } if (!$i) { $totalarray['pos'][$totalarray['nbfield']] = 'cdet.qty'; } @@ -1528,6 +1528,9 @@ if ($resql) { } else { $totalarray['val']['cdet.qty'] = $obj->qty; } + if (!$i) { + $totalarray['nbfield']++; + } } // Ref @@ -1898,7 +1901,7 @@ if ($resql) { if (!$i) { $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; } - if ($i >= $last_num - 1) { + if ($i >= $imaxinloop - 1) { if (!empty($total_ht)) { $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); } else { From 7baf98d6aa76a7e58c6f4360a6f519b8fec1de7f Mon Sep 17 00:00:00 2001 From: kkhelifa Date: Fri, 4 Nov 2022 16:18:19 +0100 Subject: [PATCH 055/816] FIX: Reload page on supplier change and keeping the values of the input already set in the form --- htdocs/fourn/commande/card.php | 17 +++++++++-------- htdocs/fourn/facture/card.php | 15 ++++++++------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 86e34ce39a1..204b2d724da 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1616,15 +1616,16 @@ if ($action == 'create') { print img_picto('', 'company').$form->select_company((empty($socid) ? '' : $socid), 'socid', 's.fournisseur=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300'); // reload page to retrieve customer informations if (!empty($conf->global->RELOAD_PAGE_ON_SUPPLIER_CHANGE)) { - print ''; + '; } print ' '; } diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 366047da07c..103748aa541 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1945,14 +1945,15 @@ if ($action == 'create') { // reload page to retrieve supplier informations if (!empty($conf->global->RELOAD_PAGE_ON_SUPPLIER_CHANGE)) { print ''; + '; } print ' '; } From c62a23b75a38009b39cca5db57dfb484d90d90aa Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Mon, 7 Nov 2022 13:07:50 +0100 Subject: [PATCH 056/816] clean code --- htdocs/commande/list_det.php | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index 7dcd8fb3835..fff7dc5b142 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -805,24 +805,6 @@ if ($resql) { $arrayofmassactions = array( 'GenerateOrdersSuppliers'=>img_picto('', 'doc', 'class="pictofixedwidth"').$langs->trans("GenerateOrdersSupplie"), ); - // if ($permissiontovalidate) { - // $arrayofmassactions['prevalidate'] = img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"); - // } - // if ($permissiontosendbymail) { - // $arrayofmassactions['presend'] = img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"); - // } - // if ($permissiontoclose) { - // $arrayofmassactions['preshipped'] = img_picto('', 'dollyrevert', 'class="pictofixedwidth"').$langs->trans("ClassifyShipped"); - // } - // if ($permissiontocancel) { - // $arrayofmassactions['cancelorders'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Cancel"); - // } - // if ($permissiontodelete) { - // $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); - // } - // if (in_array($massaction, array('presend', 'predelete', 'createbills'))) { - // $arrayofmassactions = array(); - // } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); $url = DOL_URL_ROOT.'/commande/card.php?action=create'; @@ -2118,7 +2100,7 @@ if ($resql) { $subtotal += $obj->total_ht; $i++; } - var_dump($totalarray['nbfield']); + // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; From ce7e59a4b27d4e5eb6f762fd6a443b8940aa7131 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Mon, 7 Nov 2022 14:15:21 +0100 Subject: [PATCH 057/816] ADD colum warehouse --- htdocs/commande/list_det.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index fff7dc5b142..fd36f229e5c 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -200,6 +200,7 @@ $arrayfields = array( 'c.multicurrency_total_ht'=>array('label'=>'MulticurrencyAmountHT', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>100), 'c.multicurrency_total_vat'=>array('label'=>'MulticurrencyAmountVAT', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>105), 'c.multicurrency_total_ttc'=>array('label'=>'MulticurrencyAmountTTC', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>110), + 'c.fk_warehouse'=>array('label'=>'Warehouse', 'checked'=>0, 'enabled'=>(empty($conf->stock->enabled) && empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER) ? 0 : 1), 'position'=>110), 'u.login'=>array('label'=>"Author", 'checked'=>1, 'position'=>115), 'sale_representative'=>array('label'=>"SaleRepresentativesOfThirdParty", 'checked'=>0, 'position'=>116), 'total_pa' => array('label' => (getDolGlobalString('MARGIN_TYPE') == '1' ? 'BuyingPrice' : 'CostPrice'), 'checked' => 0, 'position' => 300, 'enabled' => (empty($conf->margin->enabled) || !$user->rights->margins->liretous ? 0 : 1)), @@ -358,7 +359,7 @@ $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= " country.code as country_code,"; $sql .= ' c.rowid as c_rowid, c.ref, c.ref_client, c.fk_user_author,'; $sql .= ' c.fk_multicurrency, c.multicurrency_code, c.multicurrency_tx, c.multicurrency_total_ht, c.multicurrency_total_tva as multicurrency_total_vat, c.multicurrency_total_ttc,'; -$sql .= ' c.total_ht as c_total_ht, c.total_tva as c_total_tva, c.total_ttc as c_total_ttc,'; +$sql .= ' c.total_ht as c_total_ht, c.total_tva as c_total_tva, c.total_ttc as c_total_ttc, c.fk_warehouse as warehouse,'; $sql .= ' c.date_valid, c.date_commande, c.note_public, c.note_private, c.date_livraison as date_delivery, c.fk_statut, c.facture as billed,'; $sql .= ' c.date_creation as date_creation, c.tms as date_update, c.date_cloture as date_cloture,'; $sql .= ' p.rowid as project_id, p.ref as project_ref, p.title as project_label,'; @@ -1066,6 +1067,10 @@ if ($resql) { print ''; print ''; } + if (!empty($arrayfields['c.fk_warehouse']['checked'])) { + // Warehouse + print ''; + } if (!empty($arrayfields['c.multicurrency_code']['checked'])) { // Currency print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } // Currency if (!empty($arrayfields['c.multicurrency_code']['checked'])) { print '\n"; From e9d32c882291c2eded62dca1b4ae5ae4ca02f7fe Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Wed, 16 Nov 2022 14:31:59 +0100 Subject: [PATCH 058/816] NEW hook printFieldListFrom in contact list --- htdocs/contact/list.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 2bfdf9d1f66..39feeb125f4 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -402,6 +402,10 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_stcommcontact as st ON st.id = p.fk_stco if (empty($user->rights->societe->client->voir) && !$socid) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc"; } +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; $sql .= ' WHERE p.entity IN ('.getEntity('contact').')'; if (empty($user->rights->societe->client->voir) && !$socid) { //restriction $sql .= " AND (sc.fk_user = ".((int) $user->id)." OR p.fk_soc IS NULL)"; From b5688427abb8e7c356d84fb5d5dff7d58742bca4 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Mon, 21 Nov 2022 16:59:36 +0100 Subject: [PATCH 059/816] NEW : Now we can edit amount on vat and salaries clone action --- htdocs/compta/tva/card.php | 5 +++++ htdocs/salaries/card.php | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/htdocs/compta/tva/card.php b/htdocs/compta/tva/card.php index e7c7678b818..eae2f17f4ec 100644 --- a/htdocs/compta/tva/card.php +++ b/htdocs/compta/tva/card.php @@ -333,6 +333,10 @@ if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->tax->char $object->id = $object->ref = null; $object->paye = 0; + if (GETPOST('amount', 'alphanohtml')) { + $object->amount = price2num(GETPOST('amount', 'alphanohtml'), 'MT', 2); + } + if (GETPOST('clone_label', 'alphanohtml')) { $object->label = GETPOST('clone_label', 'alphanohtml'); } else { @@ -540,6 +544,7 @@ if ($id > 0) { //$formquestion[] = array('type' => 'date', 'name' => 'clone_date_ech', 'label' => $langs->trans("Date"), 'value' => -1); $formquestion[] = array('type' => 'date', 'name' => 'clone_period', 'label' => $langs->trans("PeriodEndDate"), 'value' => -1); + $formquestion[] = array('type' => 'text', 'name' => 'amount', 'label' => $langs->trans("Amount"), 'value' => price($object->amount), 'morecss' => 'width100'); print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneVAT', $object->ref), 'confirm_clone', $formquestion, 'yes', 1, 240); } diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 5ba1b818137..66844d40f5b 100644 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -380,6 +380,10 @@ if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->salaries- $object->paye = 0; $object->id = $object->ref = null; + if (GETPOST('amount', 'alphanohtml')) { + $object->amount = price2num(GETPOST('amount', 'alphanohtml'), 'MT', 2); + } + if (GETPOST('clone_label', 'alphanohtml')) { $object->label = GETPOST('clone_label', 'alphanohtml'); } else { @@ -710,6 +714,7 @@ if ($id) { //$formquestion[] = array('type' => 'date', 'name' => 'clone_date_ech', 'label' => $langs->trans("Date"), 'value' => -1); $formquestion[] = array('type' => 'date', 'name' => 'clone_date_start', 'label' => $langs->trans("DateStart"), 'value' => -1); $formquestion[] = array('type' => 'date', 'name' => 'clone_date_end', 'label' => $langs->trans("DateEnd"), 'value' => -1); + $formquestion[] = array('type' => 'text', 'name' => 'amount', 'label' => $langs->trans("Amount"), 'value' => price($object->amount), 'morecss' => 'width100'); $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneSalary', $object->ref), 'confirm_clone', $formquestion, 'yes', 1, 250); } From c689ce1c52c6c3bae58975acb4e9d080ca3cb674 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 21 Nov 2022 16:08:00 +0000 Subject: [PATCH 060/816] Fixing style errors. --- htdocs/salaries/card.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 66844d40f5b..7e3111743b3 100644 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -380,9 +380,9 @@ if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->salaries- $object->paye = 0; $object->id = $object->ref = null; - if (GETPOST('amount', 'alphanohtml')) { - $object->amount = price2num(GETPOST('amount', 'alphanohtml'), 'MT', 2); - } + if (GETPOST('amount', 'alphanohtml')) { + $object->amount = price2num(GETPOST('amount', 'alphanohtml'), 'MT', 2); + } if (GETPOST('clone_label', 'alphanohtml')) { $object->label = GETPOST('clone_label', 'alphanohtml'); From 01a4d0414d2cf0504e7696110e166d5953283a43 Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Tue, 22 Nov 2022 16:22:10 +0100 Subject: [PATCH 061/816] add applicant name --- htdocs/recruitment/recruitmentcandidature_agenda.php | 1 + htdocs/recruitment/recruitmentcandidature_card.php | 1 + htdocs/recruitment/recruitmentcandidature_document.php | 1 + htdocs/recruitment/recruitmentcandidature_note.php | 1 + 4 files changed, 4 insertions(+) diff --git a/htdocs/recruitment/recruitmentcandidature_agenda.php b/htdocs/recruitment/recruitmentcandidature_agenda.php index 04118f55572..ac4f54d115c 100644 --- a/htdocs/recruitment/recruitmentcandidature_agenda.php +++ b/htdocs/recruitment/recruitmentcandidature_agenda.php @@ -143,6 +143,7 @@ if ($object->id > 0) { $linkback = ''.$langs->trans("BackToList").''; $morehtmlref = '
'; + $morehtmlref.= $object->getFullName('', 1); /* // Ref customer $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); diff --git a/htdocs/recruitment/recruitmentcandidature_card.php b/htdocs/recruitment/recruitmentcandidature_card.php index 2452c9e530b..7cf9fb47b56 100644 --- a/htdocs/recruitment/recruitmentcandidature_card.php +++ b/htdocs/recruitment/recruitmentcandidature_card.php @@ -426,6 +426,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $linkback = ''.$langs->trans("BackToList").''; $morehtmlref = '
'; + $morehtmlref.= $object->getFullName('', 1); /* // Ref customer $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); diff --git a/htdocs/recruitment/recruitmentcandidature_document.php b/htdocs/recruitment/recruitmentcandidature_document.php index 3f08c770111..ed0cb115ea7 100644 --- a/htdocs/recruitment/recruitmentcandidature_document.php +++ b/htdocs/recruitment/recruitmentcandidature_document.php @@ -121,6 +121,7 @@ if ($object->id) { $linkback = ''.$langs->trans("BackToList").''; $morehtmlref = '
'; + $morehtmlref.= $object->getFullName('', 1); /* // Ref customer $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); diff --git a/htdocs/recruitment/recruitmentcandidature_note.php b/htdocs/recruitment/recruitmentcandidature_note.php index 1649ab5ee5e..f04a22aaf1b 100644 --- a/htdocs/recruitment/recruitmentcandidature_note.php +++ b/htdocs/recruitment/recruitmentcandidature_note.php @@ -96,6 +96,7 @@ if ($id > 0 || !empty($ref)) { $linkback = ''.$langs->trans("BackToList").''; $morehtmlref = '
'; + $morehtmlref.= $object->getFullName('', 1); /* // Ref customer $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); From 638b7bc6534d9eb1eedc9eb827a99defbb5b3a1b Mon Sep 17 00:00:00 2001 From: FLIO Date: Tue, 22 Nov 2022 17:02:12 +0100 Subject: [PATCH 062/816] fix(scrutinizer) https://scrutinizer-ci.com/g/Dolibarr/dolibarr/issues/develop/files/htdocs/core/boxes/box_services_contracts.php?selectedLabels%5B0%5D=9&selectedSeverities%5B0%5D=10&orderField=lastFound&order=desc&honorSelectedPaths=0 --- htdocs/core/boxes/box_services_contracts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/boxes/box_services_contracts.php b/htdocs/core/boxes/box_services_contracts.php index 3d1e640f34b..acc1d40eed5 100644 --- a/htdocs/core/boxes/box_services_contracts.php +++ b/htdocs/core/boxes/box_services_contracts.php @@ -124,7 +124,7 @@ class box_services_contracts extends ModeleBoxes $contractlinestatic->label = $objp->label; $contractlinestatic->description = $objp->description; $contractlinestatic->type = $objp->type; - $contractlinestatic->product_id = $objp->product_id; + $contractlinestatic->fk_productyy = $objp->product_id; $contractlinestatic->product_ref = $objp->product_ref; $contractlinestatic->product_type = $objp->product_type; $contractlinestatic->statut = $objp->contractline_status; From 1c5888d6d27c8608a701b46d106efa09ba4a19ea Mon Sep 17 00:00:00 2001 From: Christian Foellmann Date: Wed, 23 Nov 2022 20:47:32 +0100 Subject: [PATCH 063/816] add hook 'llxFooter' --- htdocs/core/class/hookmanager.class.php | 1 + htdocs/main.inc.php | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 5f87d81db9d..4886a3fd5d0 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -195,6 +195,7 @@ class HookManager 'getFormatedSupplierRef', 'getIdProfUrl', 'getInputIdProf', + 'llxFooter', 'menuDropdownQuickaddItems', 'menuLeftMenuItems', 'moveUploadedFile', diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 4b580e7b808..e0ea7b1dbfc 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -3213,6 +3213,17 @@ if (!function_exists("llxFooter")) { $ext = 'layout='.$conf->browser->layout.'&version='.urlencode(DOL_VERSION); + // Hook to add more things on all pages within fiche DIV + $llxfooter = ''; + $parameters = array(); + $reshook = $hookmanager->executeHooks('llxFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $llxfooter .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $llxfooter = $hookmanager->resPrint; + } + print $llxfooter; + // Global html output events ($mesgs, $errors, $warnings) dol_htmloutput_events($disabledoutputofmessages); From 3a861af01e12d1d2b7d899501b755079dd147087 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Fri, 25 Nov 2022 17:19:34 +0100 Subject: [PATCH 064/816] FIX reload travis From d5e6c08319ab297297ebae7bd74b516c1c29d260 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Thu, 1 Dec 2022 16:50:32 +0100 Subject: [PATCH 065/816] NEW operation type in email collector to load or create contact --- htdocs/admin/emailcollector_card.php | 1 + .../class/emailcollector.class.php | 114 ++++++++++++++++++ htdocs/langs/en_US/admin.lang | 1 + htdocs/langs/fr_FR/admin.lang | 1 + 4 files changed, 117 insertions(+) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 8dfafb19b63..b3d6e045470 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -668,6 +668,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $arrayoftypes = array( 'loadthirdparty' => $langs->trans('LoadThirdPartyFromName', $langs->transnoentities("ThirdPartyName")), 'loadandcreatethirdparty' => $langs->trans('LoadThirdPartyFromNameOrCreate', $langs->transnoentities("ThirdPartyName")), + 'loadandcreatecontact' => $langs->trans('LoadContactFromEmailOrCreate', $langs->transnoentities("Email")), 'recordjoinpiece' => 'AttachJoinedDocumentsToObject', 'recordevent' => 'RecordEvent' ); diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 8d72666ad53..db932e0a4ca 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2141,6 +2141,120 @@ class EmailCollector extends CommonObject } } } + } + // Search and create contact + elseif ($operation['type'] == 'loadandcreatecontact') { + if (empty($operation['actionparam'])) { + $errorforactions++; + $this->error = "Action loadandcreatecontact has empty parameter. Must be 'SET:xxx' or 'EXTRACT:(body|subject):regex' to define how to extract data"; + $this->errors[] = $this->error; + } else { + $contact_static = new Contact($this->db); + // Overwrite values with values extracted from source email + $errorforthisaction = $this->overwritePropertiesOfObject($contact_static, $operation['actionparam'], $messagetext, $subject, $header, $operationslog); + if ($errorforthisaction) { + $errorforactions++; + } else { + if (!empty($contact_static->email) && $contact_static->email != $from) $from = $contact_static->email; + + $result = $contactstatic->fetch(0, null, '', $from); + if ($result < 0) { + $errorforactions++; + $this->error = 'Error when getting contact with email ' . $from; + $this->errors[] = $this->error; + break; + } elseif ($result == 0) { + dol_syslog("Contact with email " . $from . " was not found. We try to create it."); + $contactstatic = new Contact($this->db); + + // Create contact + $contactstatic->email = $from; + $operationslog .= '
We set property email='.dol_escape_htmltag($from); + + // Overwrite values with values extracted from source email + $errorforthisaction = $this->overwritePropertiesOfObject($contactstatic, $operation['actionparam'], $messagetext, $subject, $header, $operationslog); + + if ($errorforthisaction) { + $errorforactions++; + } else { + // Search country by name or code + if (!empty($contactstatic->country)) { + require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; + $result = getCountry('', 3, $this->db, '', 1, $contactstatic->country); + if ($result == 'NotDefined') { + $errorforactions++; + $this->error = "Error country not found by this name '" . $contactstatic->country . "'"; + } elseif (!($result > 0)) { + $errorforactions++; + $this->error = "Error when search country by this name '" . $contactstatic->country . "'"; + $this->errors[] = $this->db->lasterror(); + } else { + $contactstatic->country_id = $result; + $operationslog .= '
We set property country_id='.dol_escape_htmltag($result); + } + } elseif (!empty($contactstatic->country_code)) { + require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; + $result = getCountry($contactstatic->country_code, 3, $this->db); + if ($result == 'NotDefined') { + $errorforactions++; + $this->error = "Error country not found by this code '" . $contactstatic->country_code . "'"; + } elseif (!($result > 0)) { + $errorforactions++; + $this->error = "Error when search country by this code '" . $contactstatic->country_code . "'"; + $this->errors[] = $this->db->lasterror(); + } else { + $contactstatic->country_id = $result; + $operationslog .= '
We set property country_id='.dol_escape_htmltag($result); + } + } + + if (!$errorforactions) { + // Search state by name or code (for country if defined) + if (!empty($contactstatic->state)) { + require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php'; + $result = dol_getIdFromCode($this->db, $contactstatic->state, 'c_departements', 'nom', 'rowid'); + if (empty($result)) { + $errorforactions++; + $this->error = "Error state not found by this name '" . $contactstatic->state . "'"; + } elseif (!($result > 0)) { + $errorforactions++; + $this->error = "Error when search state by this name '" . $contactstatic->state . "'"; + $this->errors[] = $this->db->lasterror(); + } else { + $contactstatic->state_id = $result; + $operationslog .= '
We set property state_id='.dol_escape_htmltag($result); + } + } elseif (!empty($contactstatic->state_code)) { + require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php'; + $result = dol_getIdFromCode($this->db, $contactstatic->state_code, 'c_departements', 'code_departement', 'rowid'); + if (empty($result)) { + $errorforactions++; + $this->error = "Error state not found by this code '" . $contactstatic->state_code . "'"; + } elseif (!($result > 0)) { + $errorforactions++; + $this->error = "Error when search state by this code '" . $contactstatic->state_code . "'"; + $this->errors[] = $this->db->lasterror(); + } else { + $contactstatic->state_id = $result; + $operationslog .= '
We set property state_id='.dol_escape_htmltag($result); + } + } + } + + if (!$errorforactions) { + $result = $contactstatic->create($user); + if ($result <= 0) { + $errorforactions++; + $this->error = $contactstatic->error; + $this->errors = $contactstatic->errors; + } else { + $operationslog .= '
Contact created -> id = '.dol_escape_htmltag($contactstatic->id); + } + } + } + } + } + } } elseif ($operation['type'] == 'recordevent') { // Create event $actioncomm = new ActionComm($this->db); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index b6c780a6be0..9fa5f7f1c28 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2119,6 +2119,7 @@ CodeLastResult=Latest result code NbOfEmailsInInbox=Number of emails in source directory LoadThirdPartyFromName=Load third party searching on %s (load only) LoadThirdPartyFromNameOrCreate=Load third party searching on %s (create if not found) +LoadContactFromEmailOrCreate=Load contact searching on %s (create if not found) AttachJoinedDocumentsToObject=Save attached files into object documents if a ref of an object is found into email topic. WithDolTrackingID=Message from a conversation initiated by a first email sent from Dolibarr WithoutDolTrackingID=Message from a conversation initiated by a first email NOT sent from Dolibarr diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 79a266df816..6a59583e7c0 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -2115,6 +2115,7 @@ CodeLastResult=Dernier code de retour NbOfEmailsInInbox=Nombre de courriels dans le répertoire source LoadThirdPartyFromName=Charger le Tiers en cherchant sur %s (chargement uniquement) LoadThirdPartyFromNameOrCreate=Charger le Tiers en cherchant sur %s (créer si non trouvé) +LoadContactFromEmailOrCreate=Charger le Contact en cherchant sur %s (créer si non trouvé) AttachJoinedDocumentsToObject=Enregistrez les fichiers joints dans des documents d'objet si la référence d'un objet est trouvée dans le sujet de l'e-mail. WithDolTrackingID=Message d'une conversation initiée par un premier mail envoyé depuis Dolibarr WithoutDolTrackingID=Message d'une conversation initiée par un premier e-mail NON envoyé depuis Dolibarr From 3be0f0e1d0f2c206442cc83b7325d6f8ac6ac7d9 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Thu, 1 Dec 2022 17:21:41 +0100 Subject: [PATCH 066/816] FIX stickler-ci --- htdocs/emailcollector/class/emailcollector.class.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index db932e0a4ca..1393913bb35 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2141,9 +2141,7 @@ class EmailCollector extends CommonObject } } } - } - // Search and create contact - elseif ($operation['type'] == 'loadandcreatecontact') { + } elseif ($operation['type'] == 'loadandcreatecontact') { // Search and create contact if (empty($operation['actionparam'])) { $errorforactions++; $this->error = "Action loadandcreatecontact has empty parameter. Must be 'SET:xxx' or 'EXTRACT:(body|subject):regex' to define how to extract data"; From 8426e955c8f221817653f9cc498db8eb60a7c713 Mon Sep 17 00:00:00 2001 From: Jesse Rovira Date: Fri, 2 Dec 2022 12:34:13 -0300 Subject: [PATCH 067/816] Showing Due date into last customer invoice at comm card --- htdocs/comm/card.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index f578aa75cf5..0df573b7f9b 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -1418,7 +1418,7 @@ if ($object->id > 0) { $sql .= ', f.total_tva'; $sql .= ', f.total_ttc'; $sql .= ', f.entity'; - $sql .= ', f.datef as df, f.datec as dc, f.paye as paye, f.fk_statut as status'; + $sql .= ', f.datef as df, f.date_lim_reglement as dl, f.datec as dc, f.paye as paye, f.fk_statut as status'; $sql .= ', s.nom, s.rowid as socid'; $sql .= ', SUM(pf.amount) as am'; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture as f"; @@ -1496,6 +1496,11 @@ if ($object->id > 0) { } else { print '
'; } + if ($objp->dl > 0) { + print ''; + } else { + print ''; + } print ''; From f98381de8a45047a182d10df72c1509575f2a915 Mon Sep 17 00:00:00 2001 From: Jesse Rovira Date: Fri, 2 Dec 2022 13:36:17 -0300 Subject: [PATCH 068/816] Showing label for Due date into last customer invoice at comm card --- htdocs/comm/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 0df573b7f9b..345a97e9e19 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -1492,12 +1492,12 @@ if ($object->id > 0) { //print $formfile->getDocumentsLink($facturestatic->element, $filename, $filedir); print ''; if ($objp->df > 0) { - print ''; + print ''; } else { print ''; } if ($objp->dl > 0) { - print ''; + print ''; } else { print ''; } From 19e3a8949a0476647849c18e4aeae45785ce6e73 Mon Sep 17 00:00:00 2001 From: FLIO Date: Mon, 5 Dec 2022 10:51:09 +0100 Subject: [PATCH 069/816] Fix(scrutinizer) --- htdocs/core/boxes/box_services_contracts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/boxes/box_services_contracts.php b/htdocs/core/boxes/box_services_contracts.php index acc1d40eed5..433db55a515 100644 --- a/htdocs/core/boxes/box_services_contracts.php +++ b/htdocs/core/boxes/box_services_contracts.php @@ -124,7 +124,7 @@ class box_services_contracts extends ModeleBoxes $contractlinestatic->label = $objp->label; $contractlinestatic->description = $objp->description; $contractlinestatic->type = $objp->type; - $contractlinestatic->fk_productyy = $objp->product_id; + $contractlinestatic->fk_product = $objp->product_id; $contractlinestatic->product_ref = $objp->product_ref; $contractlinestatic->product_type = $objp->product_type; $contractlinestatic->statut = $objp->contractline_status; From 1c108f3583c76c00fd243f918d2fc84643b251fb Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 6 Dec 2022 16:11:14 +0100 Subject: [PATCH 070/816] New mode kaban for products list --- htdocs/product/class/product.class.php | 55 ++ htdocs/product/list.php | 1128 ++++++++++++------------ htdocs/theme/eldy/info-box.inc.php | 25 + 3 files changed, 655 insertions(+), 553 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index ffb72bfca78..b0b55cab66c 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -6238,6 +6238,61 @@ class Product extends CommonObject return $prodDurationHours; } + + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs,$conf; + + $return = '
'; + $return .= '
'; + $return .= '
'; + $label = ''; + + if ($this->is_photo_available($conf->product->multidir_output[$this->entity])) { + $label .= $this->show_photos('product', $conf->product->multidir_output[$this->entity]); + $return .= $label; + } else { + if ($this->type == Product::TYPE_PRODUCT) { + $label .= img_picto('', 'product'); + } elseif ($this->type == Product::TYPE_SERVICE) { + $label .= img_picto('', 'service'); + } + $return .= $label; + } + + $return .= '
'; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + if (property_exists($this, 'label')) { + $return .= '
'.$this->label.''; + } + if (property_exists($this, 'price') && property_exists($this, 'price_ttc')) { + if ($this->price_base_type == 'TTC') { + $return .= '
'.price($this->price_ttc).' '.$langs->trans("TTC").''; + } else { + if ($this->status) { + $return .= '
'.price($this->price).' '.$langs->trans("HT").''; + } + } + } + if (property_exists($this, 'stock_reel')) { + $return .= '
'.$langs->trans('PhysicalStock').' : '.$this->stock_reel.''; + } + if (method_exists($this, 'getLibStatut')) { + $return .='
'.$this->getLibStatut(5, 1).' '.$this->getLibStatut(5, 0).''; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } /** diff --git a/htdocs/product/list.php b/htdocs/product/list.php index df9acd10cf7..f45f33c9de1 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -97,6 +97,8 @@ $search_accountancy_code_buy_export = GETPOST("search_accountancy_code_buy_expor $search_finished = GETPOST("search_finished", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); $type = GETPOST("type", "int"); +$mode = GETPOST('mode', 'alpha'); + //Show/hide child products if (isModEnabled('variants') && !empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) { @@ -642,6 +644,9 @@ if ($resql) { } $param = ''; + if (!empty($mode)) { + $param = "&mode=".urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -751,6 +756,8 @@ if ($resql) { $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 ($type === "") { $perm = ($user->rights->produit->creer || $user->rights->service->creer); } elseif ($type == Product::TYPE_SERVICE) { @@ -784,6 +791,7 @@ if ($resql) { print ''; print ''; print ''; + print ''; //print ''; print ''; if (empty($arrayfields['p.fk_product_type']['checked'])) { @@ -1297,7 +1305,8 @@ if ($resql) { $i = 0; $totalarray = array(); $totalarray['nbfield'] = 0; - while ($i < min($num, $limit)) { + $imaxinloop = ($limit ? min($num, $limit) : $num); + while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); // Multilangs @@ -1366,592 +1375,605 @@ if ($resql) { if ($product_static->isService()) { $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'lire'); } + if ($mode == 'Kanban') { + if ($i == 0) { + print '
'; + } + } else { + print ''; - print ''; - - // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Ref - if (!empty($arrayfields['p.rowid']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Ref - if (!empty($arrayfields['p.ref']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Ref supplier - if (!empty($arrayfields['pfp.ref_fourn']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Thumbnail - if (!empty($arrayfields['thumbnail']['checked'])) { - $product_thumbnail_html = ''; - if (!empty($product_static->entity)) { - $product_thumbnail = $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80); - if ($product_static->nbphoto > 0) { - $product_thumbnail_html = $product_thumbnail; + // Ref + if (!empty($arrayfields['p.rowid']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; } } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Label - if (!empty($arrayfields['p.label']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Type - if (!empty($arrayfields['p.fk_product_type']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Barcode - if (!empty($arrayfields['p.barcode']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Duration - if (!empty($arrayfields['p.duration']['checked'])) { - print '\n"; + if (!$i) { + $totalarray['nbfield']++; } - print $duration_value; - print ((!empty($duration_unit) && isset($dur[$duration_unit]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : ''); - } elseif (!preg_match('/^[a-z]$/i', $obj->duration)) { // If duration is a simple char (like 's' of 'm'), we do not show value - print $obj->duration; } - print ''; - if (!$i) { - $totalarray['nbfield']++; + // Ref supplier + if (!empty($arrayfields['pfp.ref_fourn']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Finished - if (!empty($arrayfields['p.finished']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } + // Thumbnail + if (!empty($arrayfields['thumbnail']['checked'])) { + $product_thumbnail_html = ''; + if (!empty($product_static->entity)) { + $product_thumbnail = $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80); + if ($product_static->nbphoto > 0) { + $product_thumbnail_html = $product_thumbnail; + } + } - // Weight - if (!empty($arrayfields['p.weight']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Weight units - if (!empty($arrayfields['p.weight_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Length - if (!empty($arrayfields['p.length']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Length units - if (!empty($arrayfields['p.length_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Width - if (!empty($arrayfields['p.width']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Width units - if (!empty($arrayfields['p.width_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Height - if (!empty($arrayfields['p.height']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Height units - if (!empty($arrayfields['p.height_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Surface - if (!empty($arrayfields['p.surface']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Surface units - if (!empty($arrayfields['p.surface_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Volume - if (!empty($arrayfields['p.volume']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Volume units - if (!empty($arrayfields['p.volume_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Unit - if (!empty($arrayfields['cu.label']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Sell price - if (!empty($arrayfields['p.sellprice']['checked'])) { - print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Type + if (!empty($arrayfields['p.fk_product_type']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; } } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Multiprices - if (!empty($conf->global->PRODUIT_MULTIPRICES)) { - if (! isset($productpricescache)) { - $productpricescache=array(); - } - if (! isset($productpricescache[$obj->rowid])) { - $productpricescache[$obj->rowid] = array(); + // Barcode + if (!empty($arrayfields['p.barcode']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - if ($obj->tosell && $usercancreadprice) { - // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array - // then reuse the cache array if we need prices for other price levels - $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type"; - $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p"; - $sqlp .= " WHERE fk_product = ".((int) $obj->rowid); - $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; - $resultp = $db->query($sqlp); - if ($resultp) { - $nump = $db->num_rows($resultp); - $j = 0; - while ($j < $nump) { - $objp = $db->fetch_object($resultp); + // Duration + if (!empty($arrayfields['p.duration']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Finished + if (!empty($arrayfields['p.finished']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Weight + if (!empty($arrayfields['p.weight']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Weight units + if (!empty($arrayfields['p.weight_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Length + if (!empty($arrayfields['p.length']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Length units + if (!empty($arrayfields['p.length_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Width + if (!empty($arrayfields['p.width']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Width units + if (!empty($arrayfields['p.width_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Height + if (!empty($arrayfields['p.height']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Height units + if (!empty($arrayfields['p.height_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Surface + if (!empty($arrayfields['p.surface']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Surface units + if (!empty($arrayfields['p.surface_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Volume + if (!empty($arrayfields['p.volume']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Volume units + if (!empty($arrayfields['p.volume_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Unit + if (!empty($arrayfields['cu.label']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Sell price + if (!empty($arrayfields['p.sellprice']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + + // Multiprices + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + if (! isset($productpricescache)) { + $productpricescache=array(); + } + if (! isset($productpricescache[$obj->rowid])) { + $productpricescache[$obj->rowid] = array(); + } + + if ($obj->tosell && $usercancreadprice) { + // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array + // then reuse the cache array if we need prices for other price levels + $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type"; + $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p"; + $sqlp .= " WHERE fk_product = ".((int) $obj->rowid); + $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; + $resultp = $db->query($sqlp); + if ($resultp) { + $nump = $db->num_rows($resultp); + $j = 0; + while ($j < $nump) { + $objp = $db->fetch_object($resultp); + + if (empty($productpricescache[$obj->rowid][$objp->price_level])) { + $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price; + $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc; + $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type; + } + + $j++; } - $j++; + $db->free($resultp); + } else { + dol_print_error($db); } + } - $db->free($resultp); + foreach ($arraypricelevel as $key => $value) { + if (!empty($arrayfields['p.sellprice'.$key]['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + } + } + + // Better buy price + if (!empty($arrayfields['p.minbuyprice']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Number of buy prices + if (!empty($arrayfields['p.numbuyprice']['checked'])) { + print ''; + } + + // VAT or Sell Tax Rate + if (!empty($arrayfields['p.tva_tx']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // WAP + if (!empty($arrayfields['p.pmp']['checked'])) { + print ''; + } + // Cost price + if (!empty($arrayfields['p.cost_price']['checked'])) { + print ''; + } + + // Limit alert + if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Desired stock + if (!empty($arrayfields['p.desiredstock']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Stock real + if (!empty($arrayfields['p.stock']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Stock virtual + if (!empty($arrayfields['stock_virtual']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Lot/Serial + if (!empty($arrayfields['p.tobatch']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['p.fk_country']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['p.fk_state']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Accountancy code sell + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Accountancy code buy + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, '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; + // Date creation + if (!empty($arrayfields['p.datec']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['p.tms']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Status (to sell) + if (!empty($arrayfields['p.tosell']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status (to buy) + if (!empty($arrayfields['p.tobuy']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; } } - foreach ($arraypricelevel as $key => $value) { - if (!empty($arrayfields['p.sellprice'.$key]['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if (!$i) { + $totalarray['nbfield']++; } } - } - // Better buy price - if (!empty($arrayfields['p.minbuyprice']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } + print "\n"; } - - // Number of buy prices - if (!empty($arrayfields['p.numbuyprice']['checked'])) { - print ''; - } - - // VAT or Sell Tax Rate - if (!empty($arrayfields['p.tva_tx']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // WAP - if (!empty($arrayfields['p.pmp']['checked'])) { - print ''; - } - // Cost price - if (!empty($arrayfields['p.cost_price']['checked'])) { - print ''; - } - - // Limit alert - if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Desired stock - if (!empty($arrayfields['p.desiredstock']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Stock real - if (!empty($arrayfields['p.stock']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Stock virtual - if (!empty($arrayfields['stock_virtual']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Lot/Serial - if (!empty($arrayfields['p.tobatch']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['p.fk_country']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['p.fk_state']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Accountancy code sell - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Accountancy code buy - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, '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; - // Date creation - if (!empty($arrayfields['p.datec']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['p.tms']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Status (to sell) - if (!empty($arrayfields['p.tosell']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status (to buy) - if (!empty($arrayfields['p.tobuy']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Action column - if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - print "\n"; $i++; } diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index 29f1a229054..b241d4d278b 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -173,6 +173,31 @@ a.info-box-text-a i.fa.fa-exclamation-triangle { bottom: 0; } +/* customize section img box on list of products */ +.info-box-img { + height: 105px !important; + width: 88px; + border-top-left-radius: 2px; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 2px; + display: block; + overflow: hidden; + float: left; + text-align: center; + font-size: 2.8em; + line-height: 90px; + margin-right: 5px; + background: var(--colorbacktitle1) !important; +} +.info-box-img > img { + width: 90%; + position: relative; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + global->MAIN_DISABLE_GLOBAL_BOXSTATS) && !empty($conf->global->MAIN_INCLUDE_GLOBAL_STATS_IN_OPENED_DASHBOARD)) { ?> .info-box-icon-text{ opacity: 1; From 3f2367dc16406967486a3325c29cdda3c241ad9f Mon Sep 17 00:00:00 2001 From: Milen Karaganski Date: Wed, 7 Dec 2022 13:49:54 +0200 Subject: [PATCH 071/816] NEW|New [Bulk delete Project tasks] Massaction to delete multiple tasks from tab Taks of Project --- htdocs/core/lib/project.lib.php | 13 +++++++++++- htdocs/projet/tasks.php | 36 +++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index b944e8b47a5..7b0b30bcaef 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -569,9 +569,10 @@ function project_admin_prepare_head() * @param string $filterprogresscalc filter text * @param string $showbilltime Add the column 'TimeToBill' and 'TimeBilled' * @param array $arrayfields Array with displayed coloumn information + * @param array $arrayofselected Array with selected fields * @return int Nb of tasks shown */ -function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId = '', $addordertick = 0, $projectidfortotallink = 0, $filterprogresscalc = '', $showbilltime = 0, $arrayfields = array()) +function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId = '', $addordertick = 0, $projectidfortotallink = 0, $filterprogresscalc = '', $showbilltime = 0, $arrayfields = array(), $arrayofselected = array()) { global $user, $langs, $conf, $db, $hookmanager; global $projectstatic, $taskstatic, $extrafields; @@ -910,6 +911,16 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t // Tick to drag and drop print ''; + // Action column + print ''; + print "\n"; if (!$showlineingray) { diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index 951406b4275..c619b25a37b 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -183,6 +183,14 @@ $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; * Actions */ +if (GETPOST('cancel', 'alpha')) { + $action = 'list'; + $massaction = ''; +} +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { + $massaction = ''; +} + $parameters = array('id'=>$id); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { @@ -413,6 +421,7 @@ $help_url = "EN:Module_Projects|FR:Module_Projets|ES:Módulo_Proyectos"; llxHeader("", $title, $help_url); +$arrayofselected = is_array($toselect) ? $toselect : array(); if ($id > 0 || !empty($ref)) { $result = $object->fetch($id, $ref); @@ -544,6 +553,17 @@ if ($id > 0 || !empty($ref)) { // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + $arrayofmassactions = array( + 'clone'=>img_picto('', 'rightarrow', 'class="pictofixedwidth"').$langs->trans("Clone"), + ); + if ($permissiontodelete) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); + } + if (in_array($massaction, array('presend', 'predelete'))) { + $arrayofmassactions = array(); + } + $massactionbutton = $form->selectMassAction('', $arrayofmassactions); + // Project card $linkback = ''.$langs->trans("BackToList").''; @@ -842,7 +862,11 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third $linktotasks .= dolGetButtonTitle($langs->trans('ViewGantt'), '', 'fa fa-stream imgforviewmode', DOL_URL_ROOT.'/projet/ganttview.php?id='.$object->id.'&withproject=1', '', 1, array('morecss'=>'reposition marginleftonly')); //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1); - print load_fiche_titre($title, $linktotasks.'   '.$linktocreatetask, 'projecttask'); + print load_fiche_titre($title, $linktotasks.'   '.$linktocreatetask, 'projecttask', '', '', '', $massactionbutton); + + $objecttmp = new Task($db); + $trackid = 'task'.$taskstatic->id; + include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; // Get list of tasks in tasksarray and taskarrayfiltered // We need all tasks (even not limited to a user because a task to user can have a parent that is not affected to him). @@ -877,6 +901,11 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third print ''; } + // Show the massaction checkboxes only when this page is not opend from the Extended POS + if ($massactionbutton && $contextpage != 'poslist') { + $selectedfields = $form->showCheckAddButtons('checkforselect', 1); + } + print '
'; print '
'; @@ -1427,18 +1402,6 @@ if ($resql) { print ''; - print ''; - print ''; @@ -1705,15 +1668,6 @@ if ($resql) { if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); } - - - if (!empty($arrayfields['pr.desc']['checked'])) { - print_liste_field_titre($arrayfields['pr.desc']['label'], $_SERVER["PHP_SELF"], 'pr.desc', '', $param, '', $sortfield, $sortorder); - } - if (!empty($arrayfields['cdet.qty']['checked'])) { - print_liste_field_titre($arrayfields['cdet.qty']['label'], $_SERVER["PHP_SELF"], 'cdet.qty', '', $param, '', $sortfield, $sortorder); - } - if (!empty($arrayfields['c.ref']['checked'])) { print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], 'c.ref', '', $param, '', $sortfield, $sortorder); } @@ -1885,8 +1839,6 @@ if ($resql) { $total_ht = 0; $total_margin = 0; - - $imaxinloop = ($limit ? min($num, $limit) : $num); $last_num = min($num, $limit); while ($i < $imaxinloop) { From b3c903723f3e3335be8f8a8fe426cd5312c846b3 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 23 Aug 2022 11:37:08 +0200 Subject: [PATCH 027/816] Add menu and clean --- htdocs/commande/list_line.php | 33 +++++++------------------ htdocs/core/menus/standard/eldy.lib.php | 3 +++ htdocs/langs/en_US/orders.lang | 1 + 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index ac1885b03af..219d8745587 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -75,7 +75,6 @@ $search_product_category = GETPOST('search_product_category', 'int'); // Détail commande $search_refProduct = GETPOST('search_refProduct', 'alpha'); $search_descProduct = GETPOST('search_descProduct', 'alpha'); -$check_orderdetail = GETPOST('check_orderdetail', 'alpha'); $search_ref = GETPOST('search_ref', 'alpha') != '' ?GETPOST('search_ref', 'alpha') : GETPOST('sref', 'alpha'); $search_ref_customer = GETPOST('search_ref_customer', 'alpha'); @@ -169,6 +168,10 @@ if (empty($user->socid)) { $checkedtypetiers = 0; $arrayfields = array( + // Détail commande + 'pr.ref'=> array('label'=>'ProductRef', 'checked'=>1, 'position'=>1), + 'pr.desc'=> array('label'=>'ProductDescription', 'checked'=>1, 'position'=>1), + 'cdet.qty'=> array('label'=>'QtyOrdered', 'checked'=>1, 'position'=>1), 'c.ref'=>array('label'=>"Ref", 'checked'=>1, 'position'=>5), 'c.ref_client'=>array('label'=>"RefCustomerOrder", 'checked'=>-1, 'position'=>10), 'p.ref'=>array('label'=>"ProjectRef", 'checked'=>-1, 'enabled'=>(empty($conf->project->enabled) ? 0 : 1), 'position'=>20), @@ -211,13 +214,6 @@ $arrayfields = array( 'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000) ); -// Détail commande -if (!empty($check_orderdetail)) { - $arrayfields['cdet.qty'] = array('label'=>'QtyOrdered', 'checked'=>1, 'position'=>1); - $arrayfields['pr.desc'] = array('label'=>'ProductDescription', 'checked'=>1, 'position'=>1); - $arrayfields['pr.ref'] = array('label'=>'ProductRef', 'checked'=>1, 'position'=>1); -} - // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; @@ -810,10 +806,8 @@ $sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shippin $sql .= ' c.fk_input_reason, c.import_key'; // Détail commande -if (!empty($check_orderdetail)) { - $sql .= ', cdet.description, cdet.qty, '; - $sql .= ' pr.rowid as product_rowid, pr.ref as product_ref, pr.label as product_label, pr.barcode as product_barcode, pr.tobatch as product_batch, pr.tosell as product_status, pr.tobuy as product_status_buy'; -} +$sql .= ', cdet.description, cdet.qty, '; +$sql .= ' pr.rowid as product_rowid, pr.ref as product_ref, pr.label as product_label, pr.barcode as product_barcode, pr.tobatch as product_batch, pr.tosell as product_status, pr.tobuy as product_status_buy'; if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { $sql .= ", cc.fk_categorie, cc.fk_soc"; @@ -837,13 +831,9 @@ if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { } // Détail commande -if (!empty($check_orderdetail)) { - $sql .= ', '.MAIN_DB_PREFIX.'commandedet as cdet'; - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'commande as c ON cdet.fk_commande=c.rowid'; - $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as pr ON pr.rowid=cdet.fk_product'; -} else { - $sql .= ', '.MAIN_DB_PREFIX.'commande as c'; -} +$sql .= ', '.MAIN_DB_PREFIX.'commandedet as cdet'; +$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'commande as c ON cdet.fk_commande=c.rowid'; +$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as pr ON pr.rowid=cdet.fk_product'; if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_extrafields as ef on (c.rowid = ef.fk_object)"; @@ -1353,11 +1343,6 @@ if ($resql) { print '
'; } - // Détail commande - if (!empty($conf->global->ORDER_ADD_OPTION_SHOW_DETAIL_LIST)) { - print '
 
'; - } - if ($sall) { foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 4707657d3e3..e4e6c8e2839 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1324,6 +1324,9 @@ function get_left_menu_commercial($mainmenu, &$newmenu, $usemenuhider = 1, $left //$newmenu->add("/commande/list.php?leftmenu=orders&search_status=4", $langs->trans("StatusOrderProcessed"), 2, $user->rights->commande->lire); $newmenu->add("/commande/list.php?leftmenu=orders&search_status=-1", $langs->trans("StatusOrderCanceledShort"), 2, $user->rights->commande->lire); } + if ($conf->global->MAIN_FEATURES_LEVEL >= 2 && empty($user->socid)) { + $newmenu->add("/commande/list_line.php?leftmenu=orders", $langs->trans("ListOrderLigne"), 1, $user->rights->commande->lire); + } $newmenu->add("/commande/stats/index.php?leftmenu=orders", $langs->trans("Statistics"), 1, $user->rights->commande->lire); } diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index 78a5e348516..cb64d1b603a 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -96,6 +96,7 @@ OrdersStatisticsSuppliers=Purchase order statistics NumberOfOrdersByMonth=Number of orders by month AmountOfOrdersByMonthHT=Amount of orders by month (excl. tax) ListOfOrders=List of orders +ListOrderLigne=Lines of orders CloseOrder=Close order ConfirmCloseOrder=Are you sure you want to set this order to delivered? Once an order is delivered, it can be set to billed. ConfirmDeleteOrder=Are you sure you want to delete this order? From d7387ecd17ac974351de6dcd5919be717bd9632f Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 23 Aug 2022 12:33:03 +0200 Subject: [PATCH 028/816] optimise --- htdocs/commande/list_line.php | 606 +++------------------------------- 1 file changed, 49 insertions(+), 557 deletions(-) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index 219d8745587..9437daebf33 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -189,9 +189,9 @@ $arrayfields = array( 'c.fk_cond_reglement'=>array('label'=>"PaymentConditionsShort", 'checked'=>-1, 'position'=>67), 'c.fk_mode_reglement'=>array('label'=>"PaymentMode", 'checked'=>-1, 'position'=>68), 'c.fk_input_reason'=>array('label'=>"Channel", 'checked'=>-1, 'position'=>69), - 'c.total_ht'=>array('label'=>"AmountHT", 'checked'=>1, 'position'=>75), + 'cdet.total_ht'=>array('label'=>"AmountHT", 'checked'=>1, 'position'=>75), 'c.total_vat'=>array('label'=>"AmountVAT", 'checked'=>0, 'position'=>80), - 'c.total_ttc'=>array('label'=>"AmountTTC", 'checked'=>0, 'position'=>85), + 'cdet.total_ttc'=>array('label'=>"AmountTTC", 'checked'=>0, 'position'=>85), 'c.multicurrency_code'=>array('label'=>'Currency', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>90), 'c.multicurrency_tx'=>array('label'=>'CurrencyRate', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>95), 'c.multicurrency_total_ht'=>array('label'=>'MulticurrencyAmountHT', 'checked'=>0, 'enabled'=>(empty($conf->multicurrency->enabled) ? 0 : 1), 'position'=>100), @@ -314,458 +314,12 @@ if (empty($reshook)) { $uploaddir = $conf->commande->multidir_output[$conf->entity]; $triggersendname = 'ORDER_SENTBYMAIL'; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; - - if ($massaction == 'confirm_createbills') { // Create bills from orders. - $orders = GETPOST('toselect', 'array'); - $createbills_onebythird = GETPOST('createbills_onebythird', 'int'); - $validate_invoices = GETPOST('validate_invoices', 'int'); - - $errors = array(); - - $TFact = array(); - $TFactThird = array(); - $TFactThirdNbLines = array(); - - $nb_bills_created = 0; - $lastid= 0; - $lastref = ''; - - $db->begin(); - - $nbOrders = is_array($orders) ? count($orders) : 1; - - foreach ($orders as $id_order) { - $cmd = new Commande($db); - if ($cmd->fetch($id_order) <= 0) { - continue; - } - $cmd->fetch_thirdparty(); - - $objecttmp = new Facture($db); - if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) { - // If option "one bill per third" is set, and an invoice for this thirdparty was already created, we re-use it. - $objecttmp = $TFactThird[$cmd->socid]; - } else { - // If we want one invoice per order or if there is no first invoice yet for this thirdparty. - $objecttmp->socid = $cmd->socid; - $objecttmp->thirdparty = $cmd->thirdparty; - - $objecttmp->type = $objecttmp::TYPE_STANDARD; - $objecttmp->cond_reglement_id = !empty($cmd->cond_reglement_id) ? $cmd->cond_reglement_id : $cmd->thirdparty->cond_reglement_id; - $objecttmp->mode_reglement_id = !empty($cmd->mode_reglement_id) ? $cmd->mode_reglement_id : $cmd->thirdparty->mode_reglement_id; - - $objecttmp->fk_project = $cmd->fk_project; - $objecttmp->multicurrency_code = $cmd->multicurrency_code; - if (empty($createbills_onebythird)) { - $objecttmp->ref_client = $cmd->ref_client; - } - - $datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - if (empty($datefacture)) { - $datefacture = dol_now(); - } - - $objecttmp->date = $datefacture; - $objecttmp->origin = 'commande'; - $objecttmp->origin_id = $id_order; - - $objecttmp->array_options = $cmd->array_options; // Copy extrafields - - $res = $objecttmp->create($user); - - if ($res > 0) { - $nb_bills_created++; - $lastref = $objecttmp->ref; - $lastid = $objecttmp->id; - - $TFactThird[$cmd->socid] = $objecttmp; - $TFactThirdNbLines[$cmd->socid] = 0; //init nblines to have lines ordered by expedition and rang - } else { - $langs->load("errors"); - $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->errors[0]); - $error++; - } - } - - if ($objecttmp->id > 0) { - $res = $objecttmp->add_object_linked($objecttmp->origin, $id_order); - - if ($res == 0) { - $errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->errors[0]); - $error++; - } - - if (!$error) { - $lines = $cmd->lines; - if (empty($lines) && method_exists($cmd, 'fetch_lines')) { - $cmd->fetch_lines(); - $lines = $cmd->lines; - } - - $fk_parent_line = 0; - $num = count($lines); - - for ($i = 0; $i < $num; $i++) { - $desc = ($lines[$i]->desc ? $lines[$i]->desc : ''); - // If we build one invoice for several orders, we must put the ref of order on the invoice line - if (!empty($createbills_onebythird)) { - $desc = dol_concatdesc($desc, $langs->trans("Order").' '.$cmd->ref.' - '.dol_print_date($cmd->date, 'day')); - } - - if ($lines[$i]->subprice < 0) { - // Negative line, we create a discount line - $discount = new DiscountAbsolute($db); - $discount->fk_soc = $objecttmp->socid; - $discount->amount_ht = abs($lines[$i]->total_ht); - $discount->amount_tva = abs($lines[$i]->total_tva); - $discount->amount_ttc = abs($lines[$i]->total_ttc); - $discount->tva_tx = $lines[$i]->tva_tx; - $discount->fk_user = $user->id; - $discount->description = $desc; - $discountid = $discount->create($user); - if ($discountid > 0) { - $result = $objecttmp->insert_discount($discountid); - //$result=$discount->link_to_invoice($lineid,$id); - } else { - setEventMessages($discount->error, $discount->errors, 'errors'); - $error++; - break; - } - } else { - // Positive line - $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0); - // Date start - $date_start = false; - if ($lines[$i]->date_debut_prevue) { - $date_start = $lines[$i]->date_debut_prevue; - } - if ($lines[$i]->date_debut_reel) { - $date_start = $lines[$i]->date_debut_reel; - } - if ($lines[$i]->date_start) { - $date_start = $lines[$i]->date_start; - } - //Date end - $date_end = false; - if ($lines[$i]->date_fin_prevue) { - $date_end = $lines[$i]->date_fin_prevue; - } - if ($lines[$i]->date_fin_reel) { - $date_end = $lines[$i]->date_fin_reel; - } - if ($lines[$i]->date_end) { - $date_end = $lines[$i]->date_end; - } - // Reset fk_parent_line for no child products and special product - if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) { - $fk_parent_line = 0; - } - - // Extrafields - if (method_exists($lines[$i], 'fetch_optionals')) { - $lines[$i]->fetch_optionals(); - $array_options = $lines[$i]->array_options; - } - - $objecttmp->context['createfromclone']; - - $rang = ($nbOrders > 1) ? -1 : $lines[$i]->rang; - //there may already be rows from previous orders - if (!empty($createbills_onebythird)) { - $rang = $TFactThirdNbLines[$cmd->socid]; - } - - $result = $objecttmp->addline( - $desc, - $lines[$i]->subprice, - $lines[$i]->qty, - $lines[$i]->tva_tx, - $lines[$i]->localtax1_tx, - $lines[$i]->localtax2_tx, - $lines[$i]->fk_product, - $lines[$i]->remise_percent, - $date_start, - $date_end, - 0, - $lines[$i]->info_bits, - $lines[$i]->fk_remise_except, - 'HT', - 0, - $product_type, - $rang, - $lines[$i]->special_code, - $objecttmp->origin, - $lines[$i]->rowid, - $fk_parent_line, - $lines[$i]->fk_fournprice, - $lines[$i]->pa_ht, - $lines[$i]->label, - $array_options, - 100, - 0, - $lines[$i]->fk_unit - ); - if ($result > 0) { - $lineid = $result; - if (!empty($createbills_onebythird)) //increment rang to keep order - $TFactThirdNbLines[$rcp->socid]++; - } else { - $lineid = 0; - $error++; - break; - } - // Defined the new fk_parent_line - if ($result > 0 && $lines[$i]->product_type == 9) { - $fk_parent_line = $result; - } - } - } - } - } - - //$cmd->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module. - - if (!empty($createbills_onebythird) && empty($TFactThird[$cmd->socid])) { - $TFactThird[$cmd->socid] = $objecttmp; - } else { - $TFact[$objecttmp->id] = $objecttmp; - } - } - - // Build doc with all invoices - $TAllFact = empty($createbills_onebythird) ? $TFact : $TFactThird; - $toselect = array(); - - if (!$error && $validate_invoices) { - $massaction = $action = 'builddoc'; - - foreach ($TAllFact as &$objecttmp) { - $result = $objecttmp->validate($user); - if ($result <= 0) { - $error++; - setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); - break; - } - - $id = $objecttmp->id; // For builddoc action - - // Builddoc - $donotredirect = 1; - $upload_dir = $conf->facture->dir_output; - $permissiontoadd = $user->rights->facture->creer; - - // Call action to build doc - $savobject = $object; - $object = $objecttmp; - include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; - $object = $savobject; - } - - $massaction = $action = 'confirm_createbills'; - } - - if (!$error) { - $db->commit(); - - if ($nb_bills_created == 1) { - $texttoshow = $langs->trans('BillXCreated', '{s1}'); - $texttoshow = str_replace('{s1}', ''.$lastref.'', $texttoshow); - setEventMessages($texttoshow, null, 'mesgs'); - } else { - setEventMessages($langs->trans('BillCreated', $nb_bills_created), null, 'mesgs'); - } - - // Make a redirect to avoid to bill twice if we make a refresh or back - $param = ''; - if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { - $param .= '&contextpage='.urlencode($contextpage); - } - if ($limit > 0 && $limit != $conf->liste_limit) { - $param .= '&limit='.urlencode($limit); - } - if ($sall) { - $param .= '&sall='.urlencode($sall); - } - if ($socid > 0) { - $param .= '&socid='.urlencode($socid); - } - if ($search_status != '') { - $param .= '&search_status='.urlencode($search_status); - } - if ($search_orderday) { - $param .= '&search_orderday='.urlencode($search_orderday); - } - if ($search_ordermonth) { - $param .= '&search_ordermonth='.urlencode($search_ordermonth); - } - if ($search_orderyear) { - $param .= '&search_orderyear='.urlencode($search_orderyear); - } - if ($search_deliveryday) { - $param .= '&search_deliveryday='.urlencode($search_deliveryday); - } - if ($search_deliverymonth) { - $param .= '&search_deliverymonth='.urlencode($search_deliverymonth); - } - if ($search_deliveryyear) { - $param .= '&search_deliveryyear='.urlencode($search_deliveryyear); - } - if ($search_ref) { - $param .= '&search_ref='.urlencode($search_ref); - } - if ($search_company) { - $param .= '&search_company='.urlencode($search_company); - } - if ($search_ref_customer) { - $param .= '&search_ref_customer='.urlencode($search_ref_customer); - } - if ($search_user > 0) { - $param .= '&search_user='.urlencode($search_user); - } - if ($search_sale > 0) { - $param .= '&search_sale='.urlencode($search_sale); - } - if ($search_total_ht != '') { - $param .= '&search_total_ht='.urlencode($search_total_ht); - } - if ($search_total_vat != '') { - $param .= '&search_total_vat='.urlencode($search_total_vat); - } - if ($search_total_ttc != '') { - $param .= '&search_total_ttc='.urlencode($search_total_ttc); - } - if ($search_project_ref >= 0) { - $param .= "&search_project_ref=".urlencode($search_project_ref); - } - if ($show_files) { - $param .= '&show_files='.urlencode($show_files); - } - if ($optioncss != '') { - $param .= '&optioncss='.urlencode($optioncss); - } - if ($billed != '') { - $param .= '&billed='.urlencode($billed); - } - - header("Location: ".$_SERVER['PHP_SELF'].'?'.$param); - exit; - } else { - $db->rollback(); - - $action = 'create'; - $_GET["origin"] = $_POST["origin"]; - $_GET["originid"] = $_POST["originid"]; - if (!empty($errors)) { - setEventMessages(null, $errors, 'errors'); - } else { - setEventMessages("Error", null, 'errors'); - } - $error++; - } - } -} -if ($action == 'validate' && $permissiontoadd) { - if (GETPOST('confirm') == 'yes') { - $objecttmp = new $objectclass($db); - $db->begin(); - $error = 0; - foreach ($toselect as $checked) { - if ($objecttmp->fetch($checked)) { - if ($objecttmp->statut == 0) { - if (!empty($objecttmp->fk_warehouse)) { - $idwarehouse = $objecttmp->fk_warehouse; - } else { - $idwarehouse = 0; - } - if ($objecttmp->valid($user, $idwarehouse)) { - setEventMessage($langs->trans('hasBeenValidated', $objecttmp->ref), 'mesgs'); - } else { - setEventMessage($objecttmp->error, $objecttmp->errors, 'errors'); - $error++; - } - } else { - $langs->load("errors"); - setEventMessage($langs->trans('ErrorIsNotADraft', $objecttmp->ref), 'errors'); - $error++; - } - } else { - dol_print_error($db); - $error++; - } - } - if ($error) { - $db->rollback(); - } else { - $db->commit(); - } - } -} -if ($action == 'shipped' && $permissiontoadd) { - if (GETPOST('confirm') == 'yes') { - $objecttmp = new $objectclass($db); - $db->begin(); - $error = 0; - foreach ($toselect as $checked) { - if ($objecttmp->fetch($checked)) { - if ($objecttmp->statut == 1 || $objecttmp->statut == 2) { - if ($objecttmp->cloture($user)) { - setEventMessage($langs->trans('PassedInClosedStatus', $objecttmp->ref), 'mesgs'); - } else { - setEventMessage($langs->trans('CantBeClosed'), 'errors'); - $error++; - } - } else { - $langs->load("errors"); - setEventMessage($langs->trans('ErrorIsNotADraft', $objecttmp->ref), 'errors'); - $error++; - } - } else { - dol_print_error($db); - $error++; - } - } - if ($error) { - $db->rollback(); - } else { - $db->commit(); - } - } } + // Closed records -if (!$error && $massaction === 'setbilled' && $permissiontoclose) { - $db->begin(); +// if (!$error && $massaction === 'setbilled' && $permissiontoclose) { - $objecttmp = new $objectclass($db); - $nbok = 0; - foreach ($toselect as $toselectid) { - $result = $objecttmp->fetch($toselectid); - if ($result > 0) { - $result = $objecttmp->classifyBilled($user, 0); - if ($result <= 0) { - setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); - $error++; - break; - } else { - $nbok++; - } - } else { - setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); - $error++; - break; - } - } - - if (!$error) { - if ($nbok > 1) { - setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs'); - } else { - setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs'); - } - $db->commit(); - } else { - $db->rollback(); - } -} +// } /* * View @@ -796,7 +350,7 @@ $sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.pho $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= " country.code as country_code,"; -$sql .= ' c.rowid, c.ref, c.total_ht, c.total_tva, c.total_ttc, c.ref_client, c.fk_user_author,'; +$sql .= ' c.rowid, c.ref, c.ref_client, c.fk_user_author,'; $sql .= ' c.fk_multicurrency, c.multicurrency_code, c.multicurrency_tx, c.multicurrency_total_ht, c.multicurrency_total_tva as multicurrency_total_vat, c.multicurrency_total_ttc,'; $sql .= ' c.date_valid, c.date_commande, c.note_public, c.note_private, c.date_livraison as date_delivery, c.fk_statut, c.facture as billed,'; $sql .= ' c.date_creation as date_creation, c.tms as date_update, c.date_cloture as date_cloture,'; @@ -806,7 +360,7 @@ $sql .= ' c.fk_cond_reglement,c.deposit_percent,c.fk_mode_reglement,c.fk_shippin $sql .= ' c.fk_input_reason, c.import_key'; // Détail commande -$sql .= ', cdet.description, cdet.qty, '; +$sql .= ', cdet.rowid, cdet.description, cdet.qty, cdet.total_ht, cdet.total_tva, cdet.total_ttc, '; $sql .= ' pr.rowid as product_rowid, pr.ref as product_ref, pr.label as product_label, pr.barcode as product_barcode, pr.tobatch as product_batch, pr.tosell as product_status, pr.tobuy as product_status_buy'; if (($search_categ_cus > 0) || ($search_categ_cus == -2)) { @@ -959,13 +513,13 @@ if ($search_user > 0) { $sql .= " AND ec.fk_c_type_contact = tc.rowid AND tc.element='commande' AND tc.source='internal' AND ec.element_id = c.rowid AND ec.fk_socpeople = ".((int) $search_user); } if ($search_total_ht != '') { - $sql .= natural_search('c.total_ht', $search_total_ht, 1); + $sql .= natural_search('cdet.total_ht', $search_total_ht, 1); } if ($search_total_vat != '') { - $sql .= natural_search('c.total_tva', $search_total_vat, 1); + $sql .= natural_search('cdet.total_tva', $search_total_vat, 1); } if ($search_total_ttc != '') { - $sql .= natural_search('c.total_ttc', $search_total_ttc, 1); + $sql .= natural_search('cdet.total_ttc', $search_total_ttc, 1); } if ($search_warehouse != '' && $search_warehouse > 0) { $sql .= natural_search('c.fk_warehouse', $search_warehouse, 1); @@ -1231,33 +785,26 @@ if ($resql) { // List of mass actions available $arrayofmassactions = array( - 'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), - 'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), + 'GenerateOrdersSuppliers'=>img_picto('', 'doc', 'class="pictofixedwidth"').$langs->trans("GenerateOrdersSupplie"), ); - if ($permissiontovalidate) { - $arrayofmassactions['prevalidate'] = img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"); - } - if ($permissiontosendbymail) { - $arrayofmassactions['presend'] = img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"); - } - if ($permissiontoclose) { - $arrayofmassactions['preshipped'] = img_picto('', 'dollyrevert', 'class="pictofixedwidth"').$langs->trans("ClassifyShipped"); - } - if ($permissiontocancel) { - $arrayofmassactions['cancelorders'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Cancel"); - } - if (!empty($conf->invoice->enabled) && $user->rights->facture->creer) { - $arrayofmassactions['createbills'] = img_picto('', 'bill', 'class="pictofixedwidth"').$langs->trans("CreateInvoiceForThisCustomer"); - } - if ($permissiontoclose) { - $arrayofmassactions['setbilled'] = img_picto('', 'bill', 'class="pictofixedwidth"').$langs->trans("ClassifyBilled"); - } - if ($permissiontodelete) { - $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); - } - if (in_array($massaction, array('presend', 'predelete', 'createbills'))) { - $arrayofmassactions = array(); - } + // if ($permissiontovalidate) { + // $arrayofmassactions['prevalidate'] = img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"); + // } + // if ($permissiontosendbymail) { + // $arrayofmassactions['presend'] = img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"); + // } + // if ($permissiontoclose) { + // $arrayofmassactions['preshipped'] = img_picto('', 'dollyrevert', 'class="pictofixedwidth"').$langs->trans("ClassifyShipped"); + // } + // if ($permissiontocancel) { + // $arrayofmassactions['cancelorders'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Cancel"); + // } + // if ($permissiontodelete) { + // $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); + // } + // if (in_array($massaction, array('presend', 'predelete', 'createbills'))) { + // $arrayofmassactions = array(); + // } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); $url = DOL_URL_ROOT.'/commande/card.php?action=create'; @@ -1288,61 +835,6 @@ if ($resql) { $trackid = 'ord'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; - if ($massaction == 'prevalidate') { - print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassValidation"), $langs->trans("ConfirmMassValidationQuestion"), "validate", null, '', 0, 200, 500, 1); - } - if ($massaction == 'preshipped') { - print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("CloseOrder"), $langs->trans("ConfirmCloseOrder"), "shipped", null, '', 0, 200, 500, 1); - } - - if ($massaction == 'createbills') { - print ''; - - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print '
'; - print $langs->trans('DateInvoice'); - print ''; - print $form->selectDate('', '', '', '', '', '', 1, 1); - print '
'; - print $langs->trans('CreateOneBillByThird'); - print ''; - print $form->selectyesno('createbills_onebythird', '', 1); - print '
'; - print $langs->trans('ValidateInvoices'); - print ''; - if (!empty($conf->stock->enabled) && !empty($conf->global->STOCK_CALCULATE_ON_BILL)) { - print $form->selectyesno('validate_invoices', 0, 1, 1); - print ' ('.$langs->trans("AutoValidationNotPossibleWhenStockIsDecreasedOnInvoiceValidation").')'; - } else { - print $form->selectyesno('validate_invoices', 0, 1); - } - if (!empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER)) { - print '     '.$langs->trans("IfValidateInvoiceIsNoOrderStayUnbilled").''; - } else { - print '     '.$langs->trans("OptionToSetOrderBilledNotEnabled").''; - } - print '
'; - - print '
'; - print '
'; - print ' '; - print ''; - print '
'; - print '
'; - } - if ($sall) { foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); @@ -1552,7 +1044,7 @@ if ($resql) { $form->selectInputReason($search_fk_input_reason, 'search_fk_input_reason', '', 1, '', 1); print '
'; print ''; @@ -1564,7 +1056,7 @@ if ($resql) { print ''; print ''; print ''; @@ -1778,14 +1270,14 @@ if ($resql) { if (!empty($arrayfields['c.fk_input_reason']['checked'])) { print_liste_field_titre($arrayfields['c.fk_input_reason']['label'], $_SERVER["PHP_SELF"], "c.fk_input_reason", "", $param, '', $sortfield, $sortorder); } - if (!empty($arrayfields['c.total_ht']['checked'])) { - print_liste_field_titre($arrayfields['c.total_ht']['label'], $_SERVER["PHP_SELF"], 'c.total_ht', '', $param, '', $sortfield, $sortorder, 'right '); + if (!empty($arrayfields['cdet.total_ht']['checked'])) { + print_liste_field_titre($arrayfields['cdet.total_ht']['label'], $_SERVER["PHP_SELF"], 'cdet.total_ht', '', $param, '', $sortfield, $sortorder, 'right '); } if (!empty($arrayfields['c.total_vat']['checked'])) { - print_liste_field_titre($arrayfields['c.total_vat']['label'], $_SERVER["PHP_SELF"], 'c.total_tva', '', $param, '', $sortfield, $sortorder, 'right '); + print_liste_field_titre($arrayfields['c.total_vat']['label'], $_SERVER["PHP_SELF"], 'cdet.total_tva', '', $param, '', $sortfield, $sortorder, 'right '); } - if (!empty($arrayfields['c.total_ttc']['checked'])) { - print_liste_field_titre($arrayfields['c.total_ttc']['label'], $_SERVER["PHP_SELF"], 'c.total_ttc', '', $param, '', $sortfield, $sortorder, 'right '); + if (!empty($arrayfields['cdet.total_ttc']['checked'])) { + print_liste_field_titre($arrayfields['cdet.total_ttc']['label'], $_SERVER["PHP_SELF"], 'cdet.total_ttc', '', $param, '', $sortfield, $sortorder, 'right '); } if (!empty($arrayfields['c.multicurrency_code']['checked'])) { print_liste_field_titre($arrayfields['c.multicurrency_code']['label'], $_SERVER['PHP_SELF'], 'c.multicurrency_code', '', $param, '', $sortfield, $sortorder); @@ -1824,9 +1316,9 @@ if ($resql) { $totalarray = array( 'nbfield' => 0, 'val' => array( - 'c.total_ht' => 0, - 'c.total_tva' => 0, - 'c.total_ttc' => 0, + 'cdet.total_ht' => 0, + 'cdet.total_tva' => 0, + 'cdet.total_ttc' => 0, ), 'pos' => array(), ); @@ -2195,18 +1687,18 @@ if ($resql) { } } // Amount HT - if (!empty($arrayfields['c.total_ht']['checked'])) { + if (!empty($arrayfields['cdet.total_ht']['checked'])) { print ''.price($obj->total_ht)."'.price($obj->total_ttc)."'; // With edge and chrome the td overflow is not supported correctly when content is not full text. if ($obj->fk_user_action > 0 && !isset($cache_user_list[$obj->fk_user_action])) { + $userstatic = new User($db); $res = $userstatic->fetch($obj->fk_user_action); if ($res > 0) { $cache_user_list[$obj->fk_user_action] = $userstatic; From 9c6dd0f5df000710aa193195fdfe2f23ba805250 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Mon, 24 Oct 2022 18:24:11 +0200 Subject: [PATCH 044/816] FIX - removefilter --- htdocs/commande/list_line.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index 7ea36fe8d09..98e0016d36f 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -247,6 +247,8 @@ if (empty($reshook)) { // Purge search criteria if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $productonly = ''; + $disablelinefree = ''; $search_categ = ''; $search_user = ''; $search_sale = ''; From 2671bd6433ccf2d60d2af5690a087a9ca8447b4f Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Mon, 24 Oct 2022 18:28:00 +0200 Subject: [PATCH 045/816] FIX - no ligne title or sub-total or comment --- htdocs/commande/list_line.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index 98e0016d36f..4b20250e6de 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -422,6 +422,7 @@ $sql .= $hookmanager->resPrint; $sql .= ' WHERE c.fk_soc = s.rowid'; $sql .= ' AND c.entity IN ('.getEntity('commande').')'; +$sql .= ' AND cdet.product_type <> 9'; if (!empty($productonly)) { $sql .= " AND (cdet.product_type = 0 OR cdet.product_type = 1)"; From 64bc7a93c3e328b57fedcc1cab339ff117c19744 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Mon, 24 Oct 2022 18:43:23 +0200 Subject: [PATCH 046/816] ADD - Option Products to buy only --- htdocs/commande/list_line.php | 6 ++++++ htdocs/langs/en_US/orders.lang | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index 4b20250e6de..a569d7a56e1 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -57,6 +57,7 @@ $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'orderlist'; +$productobuy = GETPOST('productobuy', 'alpha'); $productonly = GETPOST('productonly', 'alpha'); $disablelinefree = GETPOST('disablelinefree', 'alpha'); @@ -247,6 +248,7 @@ if (empty($reshook)) { // Purge search criteria if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $productobuy = ''; $productonly = ''; $disablelinefree = ''; $search_categ = ''; @@ -424,6 +426,9 @@ $sql .= ' WHERE c.fk_soc = s.rowid'; $sql .= ' AND c.entity IN ('.getEntity('commande').')'; $sql .= ' AND cdet.product_type <> 9'; +if (!empty($productobuy)) { + $sql .= " AND pr.tobuy = 1"; +} if (!empty($productonly)) { $sql .= " AND (cdet.product_type = 0 OR cdet.product_type = 1)"; } @@ -842,6 +847,7 @@ if ($resql) { print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'order', 0, $newcardbutton, '', $limit, 0, 0, 1); + print ''; print ''; print ''; diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index a465fc41ea6..f988cd62f19 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -97,7 +97,8 @@ NumberOfOrdersByMonth=Number of orders by month AmountOfOrdersByMonthHT=Amount of orders by month (excl. tax) ListOfOrders=List of orders ListOrderLigne=Lines of orders -productonly=Lines products only +productobuy=Products to buy only +productonly=Products only disablelinefree=No lines free CloseOrder=Close order ConfirmCloseOrder=Are you sure you want to set this order to delivered? Once an order is delivered, it can be set to billed. From 60acbe8186b3015ff02f24d4612ad21c1ce40149 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 26 Oct 2022 12:45:09 +0200 Subject: [PATCH 047/816] FIX - contextpage --- htdocs/commande/list_line.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index a569d7a56e1..70aef999c72 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -56,7 +56,7 @@ $massaction = GETPOST('massaction', 'alpha'); $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); -$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'orderlist'; +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'orderlistdet'; $productobuy = GETPOST('productobuy', 'alpha'); $productonly = GETPOST('productonly', 'alpha'); $disablelinefree = GETPOST('disablelinefree', 'alpha'); From 78063b864ab65bc4c1c8ee28be4ddadffd39dd1b Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 26 Oct 2022 14:01:54 +0200 Subject: [PATCH 048/816] FIX - Delete button ADD order --- htdocs/commande/list_line.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_line.php index 70aef999c72..42e4ce98b00 100644 --- a/htdocs/commande/list_line.php +++ b/htdocs/commande/list_line.php @@ -829,7 +829,7 @@ if ($resql) { if (!empty($socid)) { $url .= '&socid='.$socid; } - $newcardbutton = dolGetButtonTitle($langs->trans('NewOrder'), '', 'fa fa-plus-circle', $url, '', $contextpage == 'orderlist' && $permissiontoadd); + $newcardbutton = '';//dolGetButtonTitle($langs->trans('NewOrder'), '', 'fa fa-plus-circle', $url, '', $contextpage == 'orderlistdet' && $permissiontoadd); // Lines of title fields print '
'; From 1a9f1e557455f9d76defe1d1e2a662ab8bfa1e37 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 26 Oct 2022 14:04:25 +0200 Subject: [PATCH 049/816] rename file --- htdocs/commande/{list_line.php => list_det.php} | 0 htdocs/core/menus/init_menu_auguria.sql | 2 +- htdocs/core/menus/standard/eldy.lib.php | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename htdocs/commande/{list_line.php => list_det.php} (100%) diff --git a/htdocs/commande/list_line.php b/htdocs/commande/list_det.php similarity index 100% rename from htdocs/commande/list_line.php rename to htdocs/commande/list_det.php diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index 27dd621ed59..5c479e900bd 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -178,7 +178,7 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled && $leftmenu=="orders"', __HANDLER__, 'left', 1207__+MAX_llx_menu__, 'commercial', '', 1202__+MAX_llx_menu__, '/commande/list.php?mainmenu=commercial&leftmenu=orders&search_status=4', 'StatusOrderProcessed', 1, 'orders', '$user->rights->commande->lire', '', 2, 6, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled && $leftmenu=="orders"', __HANDLER__, 'left', 1208__+MAX_llx_menu__, 'commercial', '', 1202__+MAX_llx_menu__, '/commande/list.php?mainmenu=commercial&leftmenu=orders&search_status=-1', 'StatusOrderCanceledShort', 1, 'orders', '$user->rights->commande->lire', '', 2, 7, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled', __HANDLER__, 'left', 1209__+MAX_llx_menu__, 'commercial', '', 1200__+MAX_llx_menu__, '/commande/stats/index.php?mainmenu=commercial&leftmenu=orders', 'Statistics', 1, 'orders', '$user->rights->commande->lire', '', 2, 4, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled && $conf->global->MAIN_FEATURES_LEVEL >= 2 && empty($user->socid)', __HANDLER__, 'left', 1210__+MAX_llx_menu__, 'commercial', '', 1200__+MAX_llx_menu__, '/commande/list_line.php?mainmenu=commercial&leftmenu=orders', 'ListOrderLigne', 1, 'orders', '$user->rights->commande->lire', '', 2, 1, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->commande->enabled && $conf->global->MAIN_FEATURES_LEVEL >= 2 && empty($user->socid)', __HANDLER__, 'left', 1210__+MAX_llx_menu__, 'commercial', '', 1200__+MAX_llx_menu__, '/commande/list_det.php?mainmenu=commercial&leftmenu=orders', 'ListOrderLigne', 1, 'orders', '$user->rights->commande->lire', '', 2, 1, __ENTITY__); -- Commercial - Supplier's proposals insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->supplier_proposal->enabled', __HANDLER__, 'left', 1650__+MAX_llx_menu__, 'commercial', 'propals_supplier', 3__+MAX_llx_menu__, '/supplier_proposal/index.php?leftmenu=propals_supplier', 'SupplierProposalsShort', 0, 'supplier_proposal', '$user->rights->supplier_proposal->lire', '', 2, 4, __ENTITY__); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index cdea369e47c..62cd8055cc1 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1338,7 +1338,7 @@ function get_left_menu_commercial($mainmenu, &$newmenu, $usemenuhider = 1, $left $newmenu->add("/commande/list.php?leftmenu=orders&search_status=-1", $langs->trans("StatusOrderCanceledShort"), 2, $user->hasRight('commande', 'lire')); } if ($conf->global->MAIN_FEATURES_LEVEL >= 2 && empty($user->socid)) { - $newmenu->add("/commande/list_line.php?leftmenu=orders", $langs->trans("ListOrderLigne"), 1, $user->hasRight('commande', 'lire')); + $newmenu->add("/commande/list_det.php?leftmenu=orders", $langs->trans("ListOrderLigne"), 1, $user->hasRight('commande', 'lire')); } $newmenu->add("/commande/stats/index.php?leftmenu=orders", $langs->trans("Statistics"), 1, $user->hasRight('commande', 'lire')); } From e1ee0b7d66a224ca1baffb7d60ae65fc82be59e2 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 26 Oct 2022 15:34:04 +0200 Subject: [PATCH 050/816] FIX - /td --- htdocs/commande/list_det.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index 42e4ce98b00..089c5dedbe1 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -2098,8 +2098,9 @@ if ($resql) { } print ''; } + print '
'.$obj->qty.''; @@ -1283,6 +1288,9 @@ if ($resql) { if (!empty($arrayfields['cdet.total_ttc']['checked'])) { print_liste_field_titre($arrayfields['cdet.total_ttc']['label'], $_SERVER["PHP_SELF"], 'cdet.total_ttc', '', $param, '', $sortfield, $sortorder, 'right '); } + if (!empty($arrayfields['c.fk_warehouse']['checked'])) { + print_liste_field_titre($arrayfields['c.fk_warehouse']['label'], "", '', '', $param, '', $sortfield, $sortorder); + } if (!empty($arrayfields['c.multicurrency_code']['checked'])) { print_liste_field_titre($arrayfields['c.multicurrency_code']['label'], $_SERVER['PHP_SELF'], 'c.multicurrency_code', '', $param, '', $sortfield, $sortorder); } @@ -1734,7 +1742,18 @@ if ($resql) { } $totalarray['val']['cdet.total_ttc'] += $obj->total_ttc; } - + // Warehouse + if (!empty($arrayfields['c.fk_warehouse']['checked'])) { + print ''; + if ($obj->warehouse > 0) { + print img_picto('', 'stock', 'class="paddingrightonly"'); + } + $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'], $obj->warehouse, 'none'); + print "'.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."!!!'.dol_print_date($db->jdate($objp->dl), 'day').'!!!'; print price($objp->total_ht); print ''.dol_print_date($db->jdate($objp->df), 'day').''.$langs->trans('DateInvoice').": ".dol_print_date($db->jdate($objp->df), 'day').'!!!'.dol_print_date($db->jdate($objp->dl), 'day').''.$langs->trans('DateMaxPayment').": ".dol_print_date($db->jdate($objp->dl), 'day').'!!!
'; + print '
'; + } + $product_static->price = $obj->price; + // Output Kanban + print $product_static->getKanbanView(''); + if ($i == ($imaxinloop - 1)) { + 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->rowid, $arrayofselected)) { - $selected = 1; + // Action column + if (!empty($conf->global->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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; - print $product_static->id; - print "'; - print $product_static->getNomUrl(1); - print "'; - print $product_static->getNomUrl(1); - print "'; + print $product_static->id; + print "' . $product_thumbnail_html . ''.$obj->label.''; - $s = ''; - if ($obj->fk_product_type == 0) { - $s .= img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"'); - } else { - $s .= img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"'); - } - print $s; - print ''.$obj->barcode.''; - - if (preg_match('/([^a-z]+)[a-z]$/i', $obj->duration)) { - $duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); - $duration_unit = substr($obj->duration, -1); - - if ((float) $duration_value > 1) { - $dur = array("i"=>$langs->trans("Minutes"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years")); - } elseif ((float) $duration_value > 0) { - $dur = array("i"=>$langs->trans("Minute"), "h"=>$langs->trans("Hour"), "d"=>$langs->trans("Day"), "w"=>$langs->trans("Week"), "m"=>$langs->trans("Month"), "y"=>$langs->trans("Year")); + // Ref + if (!empty($arrayfields['p.ref']['checked'])) { + print ''; + print $product_static->getNomUrl(1); + print "'; + print $product_static->getNomUrl(1); + print "'; - print $product_static->getLibFinished(); - print ''; - print $obj->weight; - print '' . $product_thumbnail_html . ''; - if ($product_static->weight != '') { - print measuringUnitString(0, 'weight', $product_static->weight_units); - } - print ''; - print $obj->length; - print ''; - if ($product_static->length != '') { - print measuringUnitString(0, 'size', $product_static->length_units); - } - print ''; - print $obj->width; - print ''; - if ($product_static->width != '') { - print measuringUnitString(0, 'size', $product_static->width_units); - } - print ''; - print $obj->height; - print ''; - if ($product_static->height != '') { - print measuringUnitString(0, 'size', $product_static->height_units); - } - print ''; - print $obj->surface; - print ''; - if ($product_static->surface != '') { - print measuringUnitString(0, 'surface', $product_static->surface_units); - } - print ''; - print $obj->volume; - print ''; - if ($product_static->volume != '') { - print measuringUnitString(0, 'volume', $product_static->volume_units); - } - print ''; - if (!empty($obj->cu_label)) { - print $langs->trans($obj->cu_label); - } - print ''; - if ($obj->tosell && $usercancreadprice) { - if ($obj->price_base_type == 'TTC') { - print ''.price($obj->price_ttc).' '.$langs->trans("TTC").''; + // Label + if (!empty($arrayfields['p.label']['checked'])) { + print ''.$obj->label.''; + $s = ''; + if ($obj->fk_product_type == 0) { + $s .= img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"'); } else { - print ''.price($obj->price).' '.$langs->trans("HT").''; + $s .= img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"'); + } + print $s; + print ''.$obj->barcode.''; - if (empty($productpricescache[$obj->rowid][$objp->price_level])) { - $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price; - $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc; - $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type; + if (preg_match('/([^a-z]+)[a-z]$/i', $obj->duration)) { + $duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); + $duration_unit = substr($obj->duration, -1); + + if ((float) $duration_value > 1) { + $dur = array("i"=>$langs->trans("Minutes"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years")); + } elseif ((float) $duration_value > 0) { + $dur = array("i"=>$langs->trans("Minute"), "h"=>$langs->trans("Hour"), "d"=>$langs->trans("Day"), "w"=>$langs->trans("Week"), "m"=>$langs->trans("Month"), "y"=>$langs->trans("Year")); + } + print $duration_value; + print ((!empty($duration_unit) && isset($dur[$duration_unit]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : ''); + } elseif (!preg_match('/^[a-z]$/i', $obj->duration)) { // If duration is a simple char (like 's' of 'm'), we do not show value + print $obj->duration; + } + + print ''; + print $product_static->getLibFinished(); + print ''; + print $obj->weight; + print ''; + if ($product_static->weight != '') { + print measuringUnitString(0, 'weight', $product_static->weight_units); + } + print ''; + print $obj->length; + print ''; + if ($product_static->length != '') { + print measuringUnitString(0, 'size', $product_static->length_units); + } + print ''; + print $obj->width; + print ''; + if ($product_static->width != '') { + print measuringUnitString(0, 'size', $product_static->width_units); + } + print ''; + print $obj->height; + print ''; + if ($product_static->height != '') { + print measuringUnitString(0, 'size', $product_static->height_units); + } + print ''; + print $obj->surface; + print ''; + if ($product_static->surface != '') { + print measuringUnitString(0, 'surface', $product_static->surface_units); + } + print ''; + print $obj->volume; + print ''; + if ($product_static->volume != '') { + print measuringUnitString(0, 'volume', $product_static->volume_units); + } + print ''; + if (!empty($obj->cu_label)) { + print $langs->trans($obj->cu_label); + } + print ''; + if ($obj->tosell && $usercancreadprice) { + if ($obj->price_base_type == 'TTC') { + print ''.price($obj->price_ttc).' '.$langs->trans("TTC").''; + } else { + print ''.price($obj->price).' '.$langs->trans("HT").''; + } + } + print ''; + if (!empty($productpricescache[$obj->rowid])) { + if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') { + print ''.price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC").''; + } else { + print ''.price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT").''; + } + } + print ''; + if ($obj->tobuy && $obj->minsellprice != '' && $usercancreadprice) { + //print price($obj->minsellprice).' '.$langs->trans("HT"); + if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) { + if ($product_fourn->product_fourn_price_id > 0) { + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { + $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1); + print ''.$form->textwithpicto(price($product_fourn->fourn_unitprice * (1 - $product_fourn->fourn_remise_percent / 100) - $product_fourn->fourn_remise).' '.$langs->trans("HT"), $htmltext).''; + } else { + print ''.price($product_fourn->fourn_unitprice).' '.$langs->trans("HT").''; + } + } + } + } + print ''; + if ($obj->tobuy && $usercancreadprice) { + if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) { + $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList); + print $form->textwithpicto(count($productFournList), $htmltext); + } + } + print ''; + print vatrate($obj->tva_tx, true); + print ''; + if ($usercancreadprice) { + print ''.price($product_static->pmp, 1, $langs).""; + } + print ''; + //print $obj->cost_price; + if ($usercancreadprice) { + print ''.price($obj->cost_price).' '.$langs->trans("HT").''; + } + print ''; + if ($obj->fk_product_type != 1) { + print $obj->seuil_stock_alerte; + } + print ''; + if ($obj->fk_product_type != 1) { + print $obj->desiredstock; + } + print ''; + if ($obj->fk_product_type != 1) { + if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) { + print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; + } + if ($usercancreadprice) { + print price(price2num($product_static->stock_reel, 'MS')); + } + } + print ''; + if ($obj->fk_product_type != 1) { + if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) { + print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; + } + if ($usercancreadprice) { + print price(price2num($product_static->stock_theorique, 'MS')); + } + } + print ''; + print $product_static->getLibStatut(1, 2); + print ''.getCountry($obj->fk_country, 0, $db).''; + if (!empty($obj->fk_state)) { + print getState($obj->fk_state, 0, $db); + } + print ''.$obj->accountancy_code_sell.''.$obj->accountancy_code_sell_intra.''.$obj->accountancy_code_sell_export.''.$obj->accountancy_code_buy.''.$obj->accountancy_code_buy_intra.''.$obj->accountancy_code_buy_export.''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { + print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); } else { - dol_print_error($db); + print $product_static->LibStatut($obj->tosell, 5, 0); + } + print ''; + if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { + print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); + } else { + print $product_static->LibStatut($obj->tobuy, 5, 1); + } + print ''; - if (!empty($productpricescache[$obj->rowid])) { - if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') { - print ''.price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC").''; - } else { - print ''.price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT").''; - } - } - 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->rowid, $arrayofselected)) { + $selected = 1; } + print ''; + } + print ''; - if ($obj->tobuy && $obj->minsellprice != '' && $usercancreadprice) { - //print price($obj->minsellprice).' '.$langs->trans("HT"); - if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) { - if ($product_fourn->product_fourn_price_id > 0) { - if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { - $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1); - print ''.$form->textwithpicto(price($product_fourn->fourn_unitprice * (1 - $product_fourn->fourn_remise_percent / 100) - $product_fourn->fourn_remise).' '.$langs->trans("HT"), $htmltext).''; - } else { - print ''.price($product_fourn->fourn_unitprice).' '.$langs->trans("HT").''; - } - } - } - } - print '
'; - if ($obj->tobuy && $usercancreadprice) { - if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) { - $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList); - print $form->textwithpicto(count($productFournList), $htmltext); - } - } - print ''; - print vatrate($obj->tva_tx, true); - print ''; - if ($usercancreadprice) { - print ''.price($product_static->pmp, 1, $langs).""; - } - print ''; - //print $obj->cost_price; - if ($usercancreadprice) { - print ''.price($obj->cost_price).' '.$langs->trans("HT").''; - } - print ''; - if ($obj->fk_product_type != 1) { - print $obj->seuil_stock_alerte; - } - print ''; - if ($obj->fk_product_type != 1) { - print $obj->desiredstock; - } - print ''; - if ($obj->fk_product_type != 1) { - if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) { - print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; - } - if ($usercancreadprice) { - print price(price2num($product_static->stock_reel, 'MS')); - } - } - print ''; - if ($obj->fk_product_type != 1) { - if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) { - print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; - } - if ($usercancreadprice) { - print price(price2num($product_static->stock_theorique, 'MS')); - } - } - print ''; - print $product_static->getLibStatut(1, 2); - print ''.getCountry($obj->fk_country, 0, $db).''; - if (!empty($obj->fk_state)) { - print getState($obj->fk_state, 0, $db); - } - print ''.$obj->accountancy_code_sell.''.$obj->accountancy_code_sell_intra.''.$obj->accountancy_code_sell_export.''.$obj->accountancy_code_buy.''.$obj->accountancy_code_buy_intra.''.$obj->accountancy_code_buy_export.''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { - print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); - } else { - print $product_static->LibStatut($obj->tosell, 5, 0); - } - print ''; - if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { - print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); - } else { - print $product_static->LibStatut($obj->tobuy, 5, 1); - } - 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->rowid, $arrayofselected)) { - $selected = 1; - } - print ''; - } - print '
'; + $selected = 0; + if (in_array($lines[$i]->id, $arrayofselected)) { + $selected = 1; + } + print ''; + + print '
'; @@ -987,6 +1016,8 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + print ''; + // Action column print ''; print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); print "\n"; @@ -1062,7 +1094,7 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third if (count($tasksarray) > 0) { // Show all lines in taskarray (recursive function to go down on tree) $j = 0; $level = 0; - $nboftaskshown = projectLinesa($j, 0, $tasksarray, $level, true, 0, $tasksrole, $object->id, 1, $object->id, $filterprogresscalc, ($object->usage_bill_time ? 1 : 0), $arrayfields); + $nboftaskshown = projectLinesa($j, 0, $tasksarray, $level, true, 0, $tasksrole, $object->id, 1, $object->id, $filterprogresscalc, ($object->usage_bill_time ? 1 : 0), $arrayfields, $arrayofselected); } else { $colspan = 10; if ($object->usage_bill_time) { From ccf40855d8f61981d2a083c98de38a6e07cc4464 Mon Sep 17 00:00:00 2001 From: Milen Karaganski Date: Wed, 7 Dec 2022 14:04:54 +0200 Subject: [PATCH 072/816] Removed "Clone" option from massactions list (work in progress) --- htdocs/projet/tasks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index c619b25a37b..c891179617d 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -554,7 +554,7 @@ if ($id > 0 || !empty($ref)) { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; $arrayofmassactions = array( - 'clone'=>img_picto('', 'rightarrow', 'class="pictofixedwidth"').$langs->trans("Clone"), + //'clone'=>img_picto('', 'rightarrow', 'class="pictofixedwidth"').$langs->trans("Clone"), ); if ($permissiontodelete) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); From 6b6cfb13395bb6e5d706691c02f17e425b3073f7 Mon Sep 17 00:00:00 2001 From: Milen Karaganski Date: Wed, 7 Dec 2022 16:57:22 +0200 Subject: [PATCH 073/816] Add mass action to clone selected tasks to another project --- htdocs/core/actions_massactions.inc.php | 60 +++++++++++++++++++ htdocs/core/class/html.form.class.php | 2 +- htdocs/core/tpl/massactions_pre.tpl.php | 12 ++++ htdocs/langs/en_US/main.lang | 3 + htdocs/langs/en_US/projects.lang | 3 +- htdocs/projet/class/project.class.php | 80 +++++++++++++++++++++++++ htdocs/projet/tasks.php | 7 ++- 7 files changed, 162 insertions(+), 5 deletions(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index ec2ecabcf0d..40ecab72a60 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1707,6 +1707,66 @@ if (!$error && ($massaction == 'increaseholiday' || ($action == 'increaseholiday } } +//if (!$error && $massaction == 'clonetasks' && $user->rights->projet->creer) { +if (!$error && ($massaction == 'clonetasks' || ($action == 'clonetasks' && $confirm == 'yes'))) { + $num = 0; + + dol_include_once('/projet/class/task.class.php'); + + $origin_task = new Task($db); + $clone_task = new Task($db); + + foreach (GETPOST('selected') as $task) { + $origin_task->fetch($task, $ref = '', $loadparentdata = 0); + + $defaultref = ''; + $obj = empty($conf->global->PROJECT_TASK_ADDON) ? 'mod_task_simple' : $conf->global->PROJECT_TASK_ADDON; + if (!empty($conf->global->PROJECT_TASK_ADDON) && is_readable(DOL_DOCUMENT_ROOT . "/core/modules/project/task/" . $conf->global->PROJECT_TASK_ADDON . ".php")) { + require_once DOL_DOCUMENT_ROOT . "/core/modules/project/task/" . $conf->global->PROJECT_TASK_ADDON . '.php'; + $modTask = new $obj; + $defaultref = $modTask->getNextValue(0, $clone_task); + } + + if (!$error) { + $clone_task->fk_project = GETPOST('projectid', 'int'); + $clone_task->ref = $defaultref; + $clone_task->label = $origin_task->label; + $clone_task->description = $origin_task->description; + $clone_task->planned_workload = $origin_task->planned_workload; + $clone_task->fk_task_parent = $origin_task->fk_task_parent; + $clone_task->date_c = dol_now(); + $clone_task->date_start = $origin_task->date_start; + $clone_task->date_end = $origin_task->date_end; + $clone_task->progress = $origin_task->progress; + + // Fill array 'array_options' with data from add form + $ret = $extrafields->setOptionalsFromPost(null, $clone_task); + + $taskid = $clone_task->create($user); + + if ($taskid > 0) { + $result = $clone_task->add_contact(GETPOST("userid", 'int'), 'TASKEXECUTIVE', 'internal'); + $num++; + } else { + if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { + $langs->load("projects"); + setEventMessages($langs->trans('NewTaskRefSuggested'), '', 'warnings'); + $duplicate_code_error = true; + } else { + setEventMessages($clone_task->error, $clone_task->errors, 'errors'); + } + $action = 'list'; + $error++; + } + } + } + + if (!$error) { + setEventMessage($langs->trans('NumberOfTasksCloned', $num)); + header("Refresh: 1;URL=".DOL_URL_ROOT.'/projet/tasks.php?id=' . GETPOST('projectid', 'int')); + } +} + $parameters['toselect'] = (empty($toselect) ? array() : $toselect); $parameters['uploaddir'] = $uploaddir; $parameters['massaction'] = $massaction; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9e26170f214..6df62ded8bd 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -7286,7 +7286,7 @@ class Form $out .= $this->selectProjectsList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss); } - if (empty($nooutput)) print $out; + if (!empty($nooutput)) print $out; else return $out; } diff --git a/htdocs/core/tpl/massactions_pre.tpl.php b/htdocs/core/tpl/massactions_pre.tpl.php index 5124a1dce35..e0293210cf6 100644 --- a/htdocs/core/tpl/massactions_pre.tpl.php +++ b/htdocs/core/tpl/massactions_pre.tpl.php @@ -40,6 +40,18 @@ if ($massaction == 'predelete') { print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassDeletion"), $langs->trans("ConfirmMassDeletionQuestion", count($toselect)), "delete", null, '', 0, 200, 500, 1); } +if ($massaction == 'preclonetasks') { + $selected = ''; + foreach (GETPOST('toselect') as $tmpselected) { + $selected .= '&selected[]=' . $tmpselected; + } + + $formquestion = array( + array('type' => 'other', 'name' => 'projectid', 'label' => $langs->trans('Project') .': ', 'value' => $form->selectProjects('', 'projectid', '', '', '', '', '', '', '', 1, 1)), + ); + print $form->formconfirm($_SERVER['PHP_SELF'] . '?id=' . $object->id . $selected . '', $langs->trans('ConfirmMassClone'), '', 'clonetasks', $formquestion, '', 1, 300, 590); +} + if ($massaction == 'preaffecttag' && isModEnabled('category')) { require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $categ = new Categorie($db); diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 87b4f8f3036..47a11b949aa 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -897,6 +897,9 @@ MassFilesArea=Area for files built by mass actions ShowTempMassFilesArea=Show area of files built by mass actions ConfirmMassDeletion=Bulk Delete confirmation ConfirmMassDeletionQuestion=Are you sure you want to delete the %s selected record(s)? +ConfirmMassClone=Bulk clone confirmation +ConfirmMassCloneQuestion=Select project to clone to +ConfirmMassCloneToOneProject=Clone to project %s RelatedObjects=Related Objects ClassifyBilled=Classify billed ClassifyUnbilled=Classify unbilled diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 2407d4b2d86..43eecc60b7b 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -258,6 +258,7 @@ RecordsClosed=%s project(s) closed SendProjectRef=Information project %s ModuleSalaryToDefineHourlyRateMustBeEnabled=Module 'Salaries' must be enabled to define employee hourly rate to have time spent valorized NewTaskRefSuggested=Task ref already used, a new task ref is required +NumberOfTasksCloned=%s task(s) cloned TimeSpentInvoiced=Time spent billed TimeSpentForIntervention=Time spent TimeSpentForInvoice=Time spent @@ -297,4 +298,4 @@ EnablePublicLeadForm=Enable the public form for contact NewLeadbyWeb=Your message or request has been recorded. We will answer or contact your soon. NewLeadForm=New contact form LeadFromPublicForm=Online lead from public form -ExportAccountingReportButtonLabel=Get report \ No newline at end of file +ExportAccountingReportButtonLabel=Get report diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 9c8b4ebee26..90057832c23 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -747,6 +747,86 @@ class Project extends CommonObject } } + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = 'SELECT '; + $sql .= $this->getFieldList('t'); + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { + $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + } else { + $sql .= ' WHERE 1 = 1'; + } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key.'='.$value; + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; + } else { + $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= ' '.$this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of elements for type, linked to a project diff --git a/htdocs/projet/tasks.php b/htdocs/projet/tasks.php index c891179617d..1fdf9939447 100644 --- a/htdocs/projet/tasks.php +++ b/htdocs/projet/tasks.php @@ -553,9 +553,10 @@ if ($id > 0 || !empty($ref)) { // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; - $arrayofmassactions = array( - //'clone'=>img_picto('', 'rightarrow', 'class="pictofixedwidth"').$langs->trans("Clone"), - ); + $arrayofmassactions = array(); + if ($user->rights->projet->creer) { + $arrayofmassactions['preclonetasks'] = img_picto('', 'rightarrow', 'class="pictofixedwidth"').$langs->trans("Clone"); + } if ($permissiontodelete) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } From f0f66327b938927b0d255f4ed28a1f79fa83adc5 Mon Sep 17 00:00:00 2001 From: Milen Karaganski Date: Wed, 7 Dec 2022 17:47:01 +0200 Subject: [PATCH 074/816] Fix syntax error --- htdocs/projet/class/project.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 90057832c23..7f0da4a6c98 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -792,7 +792,7 @@ class Project extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode("'.$filtermode.'", $sqlwhere).')'; } if (!empty($sortfield)) { From 5770d01c75af41c097e7fed679e844a44074b45b Mon Sep 17 00:00:00 2001 From: Milen Karaganski Date: Wed, 7 Dec 2022 17:57:43 +0200 Subject: [PATCH 075/816] Fix syntax error --- htdocs/projet/class/project.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 7f0da4a6c98..7ab69e070a3 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -792,7 +792,7 @@ class Project extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode("'.$filtermode.'", $sqlwhere).')'; + $sql .= ' AND ('.implode('"'.$filtermode.'"', $sqlwhere).')'; } if (!empty($sortfield)) { From 52ec95d7bff99e25342d2d26a484a2b3fccad402 Mon Sep 17 00:00:00 2001 From: Milen Karaganski Date: Wed, 7 Dec 2022 18:08:10 +0200 Subject: [PATCH 076/816] Removed unnecessary fetchAll() method from project class --- htdocs/projet/class/project.class.php | 80 --------------------------- 1 file changed, 80 deletions(-) diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 7ab69e070a3..9c8b4ebee26 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -747,86 +747,6 @@ class Project extends CommonObject } } - /** - * Load list of objects in memory from the database. - * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK - */ - public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') - { - global $conf; - - dol_syslog(__METHOD__, LOG_DEBUG); - - $records = array(); - - $sql = 'SELECT '; - $sql .= $this->getFieldList('t'); - $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; - if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; - } else { - $sql .= ' WHERE 1 = 1'; - } - // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; - } else { - $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode('"'.$filtermode.'"', $sqlwhere).')'; - } - - if (!empty($sortfield)) { - $sql .= $this->db->order($sortfield, $sortorder); - } - if (!empty($limit)) { - $sql .= ' '.$this->db->plimit($limit, $offset); - } - - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - $i = 0; - while ($i < ($limit ? min($limit, $num) : $num)) { - $obj = $this->db->fetch_object($resql); - - $record = new self($this->db); - $record->setVarsFromFetchObj($obj); - - $records[$record->id] = $record; - - $i++; - } - $this->db->free($resql); - - return $records; - } else { - $this->errors[] = 'Error '.$this->db->lasterror(); - dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); - - return -1; - } - } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of elements for type, linked to a project From 7c352c9cefe8e241c0dd862d9c148dff11519b33 Mon Sep 17 00:00:00 2001 From: atm-lena Date: Fri, 9 Dec 2022 17:00:11 +0100 Subject: [PATCH 077/816] BOM : calculate total cost of lines --- htdocs/bom/class/bom.class.php | 3 ++- htdocs/bom/tpl/objectline_view.tpl.php | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 0e57bebd922..4dfb47a3887 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1073,7 +1073,8 @@ class BOM extends CommonObject if ($res>0) { $bom_child->calculateCosts(); $line->childBom[] = $bom_child; - $this->total_cost += $bom_child->total_cost * $line->qty; + $line->total_cost = price2num( $bom_child->total_cost * $line->qty, 'MT'); + $this->total_cost += $line->total_cost; } else { $this->error = $bom_child->error; return -2; diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 61b394a3b0f..3897b875652 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -239,13 +239,13 @@ if ($resql) { // Cost if (!empty($sub_bom->id)) { $sub_bom->calculateCosts(); - print ''; + print ''; $total_cost+= $sub_bom->total_cost * $sub_bom_line->qty * $line->qty; } elseif ($sub_bom_product->cost_price > 0) { - print ''; + print ''; $total_cost+= $sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty; } elseif ($sub_bom_product->pmp > 0) { // PMP if cost price isn't defined - print ''; + print ''; $total_cost.= $sub_bom_product->pmp * $sub_bom_line->qty * $line->qty; } else { // Minimum purchase price if cost price and PMP aren't defined $sql_supplier_price = 'SELECT MIN(price) AS min_price, quantity AS qty FROM '.MAIN_DB_PREFIX.'product_fournisseur_price'; @@ -255,7 +255,7 @@ if ($resql) { $obj = $object->db->fetch_object($resql_supplier_price); $line_cost = $obj->min_price/$obj->qty * $sub_bom_line->qty * $line->qty; - print ''; + print ''; $total_cost+= $line_cost; } } From 92bff0fcfbbba88af2b422d4cefa6b4c3d38cd8f Mon Sep 17 00:00:00 2001 From: atm-lena Date: Mon, 12 Dec 2022 11:41:54 +0100 Subject: [PATCH 078/816] Missing Unit TD for sub-bom lines --- htdocs/bom/tpl/objectline_view.tpl.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 3897b875652..bb83e62c07f 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -218,11 +218,16 @@ if ($resql) { } // Qty + $label = $sub_bom_product->getLabelOfUnit('long'); if ($sub_bom_line->qty_frozen > 0) { print ''; + print ''; print ''; } else { print ''; + print ''; + print ''; print ''; } From 88ab5d72030ee0f5d1b2b306456907d0175b055b Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Tue, 13 Dec 2022 15:48:00 +0100 Subject: [PATCH 079/816] NEW Quadratus export with attachments in accountancy export --- htdocs/accountancy/bookkeeping/list.php | 96 ++++++---- .../class/accountancyexport.class.php | 177 +++++++++++++++++- htdocs/accountancy/tpl/export_journal.tpl.php | 8 +- htdocs/langs/en_US/accountancy.lang | 2 + htdocs/langs/fr_FR/accountancy.lang | 2 + 5 files changed, 233 insertions(+), 52 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index f0e95c3efb7..2d48bc706ea 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -715,58 +715,62 @@ if ($action == 'export_fileconfirm' && $user->hasRight('accounting', 'mouvements } } - $mimetype = $accountancyexport->getMimeType($formatexportset); - - top_httphead($mimetype, 1); - - // Output data on screen - $accountancyexport->export($object->lines, $formatexportset); - $notifiedexportdate = GETPOST('notifiedexportdate', 'alpha'); $notifiedvalidationdate = GETPOST('notifiedvalidationdate', 'alpha'); + $withAttachment = !empty(trim(GETPOST('notifiedexportfull', 'alphanohtml'))) ? 1 : 0; - if (!empty($accountancyexport->errors)) { - dol_print_error('', '', $accountancyexport->errors); - } elseif (!empty($notifiedexportdate) || !empty($notifiedvalidationdate)) { - // Specify as export : update field date_export or date_validated - $error = 0; - $db->begin(); + // Output data on screen or download + $result = $accountancyexport->export($object->lines, $formatexportset, $withAttachment); - if (is_array($object->lines)) { - foreach ($object->lines as $movement) { - $now = dol_now(); + $error = 0; + if ($result < 0) { + $error++; + } else { + if (!empty($notifiedexportdate) || !empty($notifiedvalidationdate)) { + if (is_array($object->lines)) { + // Specify as export : update field date_export or date_validated + $db->begin(); - $sql = " UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping"; - $sql .= " SET"; - if (!empty($notifiedexportdate) && !empty($notifiedvalidationdate)) { - $sql .= " date_export = '".$db->idate($now)."'"; - $sql .= ", date_validated = '".$db->idate($now)."'"; - } elseif (!empty($notifiedexportdate)) { - $sql .= " date_export = '".$db->idate($now)."'"; - } elseif (!empty($notifiedvalidationdate)) { - $sql .= " date_validated = '".$db->idate($now)."'"; + foreach ($object->lines as $movement) { + $now = dol_now(); + + $sql = " UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping"; + $sql .= " SET"; + if (!empty($notifiedexportdate) && !empty($notifiedvalidationdate)) { + $sql .= " date_export = '".$db->idate($now)."'"; + $sql .= ", date_validated = '".$db->idate($now)."'"; + } elseif (!empty($notifiedexportdate)) { + $sql .= " date_export = '".$db->idate($now)."'"; + } elseif (!empty($notifiedvalidationdate)) { + $sql .= " date_validated = '".$db->idate($now)."'"; + } + $sql .= " WHERE rowid = ".((int) $movement->id); + + dol_syslog("/accountancy/bookkeeping/list.php Function export_file Specify movements as exported", LOG_DEBUG); + + $result = $db->query($sql); + if (!$result) { + $error++; + break; + } } - $sql .= " WHERE rowid = ".((int) $movement->id); - dol_syslog("/accountancy/bookkeeping/list.php Function export_file Specify movements as exported", LOG_DEBUG); - - $result = $db->query($sql); - if (!$result) { + if (!$error) { + $db->commit(); + } else { $error++; - break; + $accountancyexport->errors[] = $langs->trans('NotAllExportedMovementsCouldBeRecordedAsExportedOrValidated'); + $db->rollback(); } } } - - if (!$error) { - $db->commit(); - } else { - $error++; - $db->rollback(); - dol_print_error('', $langs->trans("NotAllExportedMovementsCouldBeRecordedAsExportedOrValidated")); - } } - exit; + + if ($error) { + setEventMessages('', $accountancyexport->errors, 'errors'); + header('Location: '.$_SERVER['PHP_SELF']); + } + exit(); // download or show errors } } @@ -854,7 +858,17 @@ if ($action == 'export_file') { $form_question['separator3'] = array('name'=>'separator3', 'type'=>'separator'); } - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 350, 600); + // add documents in an archive for accountancy export (Quadratus) + if(getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV') == AccountancyExport::$EXPORT_TYPE_QUADRATUS) { + $form_question['notifiedexportfull'] = array( + 'name' => 'notifiedexportfull', + 'type' => 'checkbox', + 'label' => $langs->trans('NotifiedExportFull'), + 'value' => 'false', + ); + } + + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', $langs->trans('ConfirmExportFile'), 'export_fileconfirm', $form_question, '', 1, 400, 600); } //if ($action == 'delbookkeepingyear') { diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 3c45315ffa9..76b6782c174 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -36,6 +36,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; /** @@ -313,9 +314,10 @@ class AccountancyExport * * @param array $TData Array with data * @param int $formatexportset Id of export format - * @return void + * @param int $withAttachment [=0] Not add files or 1 to have attached in an archive (ex : Quadratus) + * @return int <0 if KO, >0 OK */ - public function export(&$TData, $formatexportset) + public function export(&$TData, $formatexportset, $withAttachment = 0) { global $conf, $langs; global $search_date_end; // Used into /accountancy/tpl/export_journal.tpl.php @@ -325,8 +327,44 @@ class AccountancyExport $type_export = 'general_ledger'; global $db; // The tpl file use $db + $completefilename = ''; + $exportFile = null; + $exportFileName = ''; + $exportFilePath = ''; + $archiveFileList = array(); + if ($withAttachment == 1) { + // PHP ZIP extension must be enabled + if (!extension_loaded('zip')) { + $langs->load('install'); + $this->errors[] = $langs->trans('ErrorPHPDoesNotSupport', 'ZIP');; + return -1; + } + } else { + $mimetype = $this->getMimeType($formatexportset); + top_httphead($mimetype, 1); + } include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php'; + if ($withAttachment == 1 && !empty($completefilename)) { + // create export file + $tmpDir = !empty($conf->accounting->multidir_temp[$conf->entity]) ? $conf->accounting->multidir_temp[$conf->entity] : $conf->accounting->dir_temp; + $exportFileFullName = $completefilename; + $exportFileBaseName = basename($exportFileFullName); + $exportFileName = pathinfo($exportFileBaseName, PATHINFO_FILENAME); + $exportFilePath = $tmpDir.'/'.$exportFileFullName; + $exportFile = fopen($exportFilePath, 'w'); + if (!$exportFile) { + $this->errors[] = $langs->trans('ErrorFileNotFound', $exportFilePath); + return -1; + } + $archiveFileList[0] = array( + 'path' => $exportFilePath, + 'name' => $exportFileFullName, + ); + // archive name and path + $archiveFullName = $exportFileName.'.zip'; + $archivePath = $tmpDir.'/'.$archiveFullName; + } switch ($formatexportset) { case self::$EXPORT_TYPE_CONFIGURABLE: @@ -345,7 +383,7 @@ class AccountancyExport $this->exportCiel($TData); break; case self::$EXPORT_TYPE_QUADRATUS: - $this->exportQuadratus($TData); + $archiveFileList = $this->exportQuadratus($TData, $exportFile, $archiveFileList, $withAttachment); break; case self::$EXPORT_TYPE_WINFIC: $this->exportWinfic($TData); @@ -399,6 +437,69 @@ class AccountancyExport } break; } + + // create and download export file or archive + if ($withAttachment == 1) { + $error = 0; + + // close export file + if ($exportFile) { + fclose($exportFile); + } + + if (!empty($archiveFullName) && !empty($archivePath) && !empty($archiveFileList)) { + // archive files + $downloadFileMimeType = 'application/zip'; + $downloadFileFullName = $archiveFullName; + $downloadFilePath = $archivePath; + + // create archive + $archive = new ZipArchive(); + $res = $archive->open($archivePath, ZipArchive::OVERWRITE | ZipArchive::CREATE); + if ($res !== true) { + $error++; + $this->errors[] = $langs->trans('ErrorFileNotFound', $archivePath); + } + if (!$error) { + // add files + foreach ($archiveFileList as $archiveFileArr) { + $res = $archive->addFile($archiveFileArr['path'], $archiveFileArr['name']); + if (!$res) { + $error++; + $this->errors[] = $langs->trans('ErrorArchiveAddFile', $archiveFileArr['name']); + break; + } + } + } + if (!$error) { + // close archive + $archive->close(); + } + } elseif (!empty($exportFileFullName) && !empty($exportFilePath)) { + // only one file to download + $downloadFileMimeType = 'text/csv'; + $downloadFileFullName = $exportFileFullName; + $downloadFilePath = $exportFilePath; + } + + if (!$error) { + // download export file + if (!empty($downloadFileMimeType) && !empty($downloadFileFullName) && !empty($downloadFilePath)) { + header('Content-Type: '.$downloadFileMimeType); + header('Content-Disposition: attachment; filename='.$downloadFileFullName); + header('Cache-Control: Public, must-revalidate'); + header('Pragma: public'); + header('Content-Length: '.dol_filesize($downloadFilePath)); + readfileLowMemory($downloadFilePath); + } + } + + if ($error) { + return -1; + } + } + + return 1; } @@ -584,10 +685,13 @@ class AccountancyExport * Help : https://docplayer.fr/20769649-Fichier-d-entree-ascii-dans-quadracompta.html * In QuadraCompta | Use menu : "Outils" > "Suivi des dossiers" > "Import ASCII(Compta)" * - * @param array $TData data - * @return void + * @param array $TData Data + * @param resource $exportFile [=null] File resource to export or print if null + * @param array $archiveFileList [=array()] Archive file list : array of ['path', 'name'] + * @param bool $withAttachment [=0] Not add files or 1 to have attached in an archive + * @return array Archive file list : array of ['path', 'name'] */ - public function exportQuadratus(&$TData) + public function exportQuadratus(&$TData, $exportFile = null, $archiveFileList = array(), $withAttachment = 0) { global $conf, $db; @@ -637,7 +741,11 @@ class AccountancyExport $Tab['end_line'] = $end_line; - print implode($Tab); + if ($exportFile) { + fwrite($exportFile, implode($Tab)); + } else { + print implode($Tab); + } } $Tab = array(); @@ -708,12 +816,63 @@ class AccountancyExport // We need to keep the 10 lastest number of invoice doc_ref not the beginning part that is the unusefull almost same part // $Tab['num_piece3'] = str_pad(self::trunc($data->piece_num, 10), 10); $Tab['num_piece3'] = substr(self::trunc($data->doc_ref, 20), -10); - $Tab['filler4'] = str_repeat(' ', 73); + $Tab['reserved'] = str_repeat(' ', 10); // position 159 + $Tab['currency_amount'] = str_repeat(' ', 13); // position 169 + // get document file + $attachmentFileName = ''; + if ($withAttachment == 1) { + $attachmentFileKey = trim($data->piece_num); + if (!isset($archiveFileList[$attachmentFileKey])) { + $objectDirPath = ''; + $objectFileName = dol_sanitizeFileName($data->doc_ref); + if ($data->doc_type == 'customer_invoice') { + $objectDirPath = !empty($conf->facture->multidir_output[$conf->entity]) ? $conf->facture->multidir_output[$conf->entity] : $conf->facture->dir_output; + } elseif ($data->doc_type == 'expense_report') { + $objectDirPath = !empty($conf->expensereport->multidir_output[$conf->entity]) ? $conf->expensereport->multidir_output[$conf->entity] : $conf->factureexpensereport->dir_output; + } elseif ($data->doc_type == 'supplier_invoice') { + $objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output; + } + $arrayofinclusion = array(); + $arrayofinclusion[] = '^'.preg_quote($objectFileName, '/').'\.pdf$'; + $fileFoundList = dol_dir_list($objectDirPath.'/'.$objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, true); + if (!empty($fileFoundList)) { + $attachmentFileNameTrunc = str_pad(self::trunc($data->piece_num, 8), 8, '0', STR_PAD_LEFT); + foreach ($fileFoundList as $fileFound) { + if (strstr($fileFound['name'], $objectFileName)) { + $fileFoundPath = $objectDirPath.'/'.$objectFileName.'/'.$fileFound['name']; + if (file_exists($fileFoundPath)) { + $archiveFileList[$attachmentFileKey] = array( + 'path' => $fileFoundPath, + 'name' => $attachmentFileNameTrunc.'.pdf', + ); + break; + } + } + } + } + } + + if (isset($archiveFileList[$attachmentFileKey])) { + $attachmentFileName = $archiveFileList[$attachmentFileKey]['name']; + } + } + if (dol_strlen($attachmentFileName) == 12) { + $Tab['attachment'] = $attachmentFileName; // position 182 + } else { + $Tab['attachment'] = str_repeat(' ', 12); // position 182 + } + $Tab['filler4'] = str_repeat(' ', 38); $Tab['end_line'] = $end_line; - print implode($Tab); + if ($exportFile) { + fwrite($exportFile, implode($Tab)); + } else { + print implode($Tab); + } } + + return $archiveFileList; } /** diff --git a/htdocs/accountancy/tpl/export_journal.tpl.php b/htdocs/accountancy/tpl/export_journal.tpl.php index 22537a60a39..833b81fc8c0 100644 --- a/htdocs/accountancy/tpl/export_journal.tpl.php +++ b/htdocs/accountancy/tpl/export_journal.tpl.php @@ -33,7 +33,9 @@ $siren = getDolGlobalString('MAIN_INFO_SIREN'); $date_export = "_".dol_print_date(dol_now(), '%Y%m%d%H%M%S'); $endaccountingperiod = dol_print_date(dol_now(), '%Y%m%d'); -header('Content-Type: text/csv'); +if (!isset($withAttachments) || $withAttachments == 1) { + header('Content-Type: text/csv'); +} include_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php'; $accountancyexport = new AccountancyExport($db); @@ -66,4 +68,6 @@ if (($accountancyexport->getFormatCode($formatexportset) == 'fec' || $accountanc $completefilename = ($code ? $code."_" : "").($prefix ? $prefix."_" : "").$filename.($nodateexport ? "" : $date_export).".".$format; } -header('Content-Disposition: attachment;filename='.$completefilename); +if (!isset($withAttachments) || $withAttachments == 1) { + header('Content-Disposition: attachment;filename=' . $completefilename); +} diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index e988764d8ba..5ea3c692aee 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -342,6 +342,7 @@ ACCOUNTING_ENABLE_LETTERING=Enable the lettering function in the accounting NotExportLettering=Do not export the lettering when generating the file NotifiedExportDate=Flag exported lines as Exported (to modify a line, you will need to delete the whole transaction and re-transfert it into accounting) NotifiedValidationDate=Validate and Lock the exported entries (same effect than the "%s" feature, modification and deletion of the lines will DEFINITELY not be possible) +NotifiedExportFull=Export documents ? DateValidationAndLock=Date validation and lock ConfirmExportFile=Confirmation of the generation of the accounting export file ? ExportDraftJournal=Export draft journal @@ -442,6 +443,7 @@ AccountancyErrorMismatchLetterCode=Mismatch in reconcile code AccountancyErrorMismatchBalanceAmount=The balance (%s) is not equal to 0 AccountancyErrorLetteringBookkeeping=Errors have occurred concerning the transactions: %s ErrorAccountNumberAlreadyExists=The accounting number %s already exists +ErrorArchiveAddFile=Can't put "%s" file in archive ## Import ImportAccountingEntries=Accounting entries diff --git a/htdocs/langs/fr_FR/accountancy.lang b/htdocs/langs/fr_FR/accountancy.lang index 53edef4c0a1..0d2b7bb69a2 100644 --- a/htdocs/langs/fr_FR/accountancy.lang +++ b/htdocs/langs/fr_FR/accountancy.lang @@ -337,6 +337,7 @@ ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS=Désactiver la liaison et le transf ## Export NotifiedExportDate=Marquer les lignes exportées comme Exportées (pour modifier une ligne, vous devrez supprimer toute la transaction et la retransférer en comptabilité) NotifiedValidationDate=Validez et verrouillez les entrées exportées (même effet que la fonctionnalité "%s", la modification et la suppression des lignes ne seront définitivement plus possibles) +NotifiedExportFull=Exporter les pièces ? DateValidationAndLock=Validation et verrouillage de la date ConfirmExportFile=Confirmation de la génération du fichier d'export comptable ? ExportDraftJournal=Exporter le journal brouillon @@ -437,6 +438,7 @@ AccountancyErrorMismatchLetterCode=Non-concordance dans le code de réconciliati AccountancyErrorMismatchBalanceAmount=Le solde (%s) n'est pas égal à 0 AccountancyErrorLetteringBookkeeping=Des erreurs sont survenues concernant les transactions : %s ErrorAccountNumberAlreadyExists=Le code comptable %s existe déjà +ErrorArchiveAddFile=Impossible d'ajouter le fichier "%s" dans l'archive ## Import ImportAccountingEntries=Écritures comptables From 6dedeb368d1f18d610dcd21ac4de81d30eb8bbfd Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Tue, 13 Dec 2022 15:51:23 +0100 Subject: [PATCH 080/816] NEW Quadratus export with attachments in accountancy export --- htdocs/accountancy/tpl/export_journal.tpl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/accountancy/tpl/export_journal.tpl.php b/htdocs/accountancy/tpl/export_journal.tpl.php index 833b81fc8c0..4dc4dedbe0e 100644 --- a/htdocs/accountancy/tpl/export_journal.tpl.php +++ b/htdocs/accountancy/tpl/export_journal.tpl.php @@ -33,7 +33,7 @@ $siren = getDolGlobalString('MAIN_INFO_SIREN'); $date_export = "_".dol_print_date(dol_now(), '%Y%m%d%H%M%S'); $endaccountingperiod = dol_print_date(dol_now(), '%Y%m%d'); -if (!isset($withAttachments) || $withAttachments == 1) { +if (empty($withAttachment)) { header('Content-Type: text/csv'); } @@ -68,6 +68,6 @@ if (($accountancyexport->getFormatCode($formatexportset) == 'fec' || $accountanc $completefilename = ($code ? $code."_" : "").($prefix ? $prefix."_" : "").$filename.($nodateexport ? "" : $date_export).".".$format; } -if (!isset($withAttachments) || $withAttachments == 1) { +if (empty($withAttachment)) { header('Content-Disposition: attachment;filename=' . $completefilename); } From 787618d9d6927a25faa0ae6bdf8f9fa67dedb67f Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Tue, 13 Dec 2022 16:36:49 +0100 Subject: [PATCH 081/816] NEW Copyrights --- htdocs/accountancy/bookkeeping/list.php | 3 ++- htdocs/accountancy/class/accountancyexport.class.php | 3 ++- htdocs/accountancy/tpl/export_journal.tpl.php | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 2d48bc706ea..2f255dec734 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -1,9 +1,10 @@ * Copyright (C) 2013-2016 Florian Henry - * Copyright (C) 2013-2022 Alexandre Spangaro + * Copyright (C) 2013-2022 Open-DSI * Copyright (C) 2016-2017 Laurent Destailleur * Copyright (C) 2018-2021 Frédéric France + * Copyright (C) 2022 Progiseize * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 76b6782c174..e101c09abd3 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -5,13 +5,14 @@ * Copyright (C) 2015 Florian Henry * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Pierre-Henry Favre - * Copyright (C) 2016-2021 Alexandre Spangaro + * Copyright (C) 2016-2022 Open-DSI * Copyright (C) 2013-2017 Olivier Geffroy * Copyright (C) 2017 Elarifr. Ari Elbaz * Copyright (C) 2017-2019 Frédéric France * Copyright (C) 2017 André Schild * Copyright (C) 2020 Guillaume Alexandre * Copyright (C) 2022 Joachim Kueter + * Copyright (C) 2022 Progiseize * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/htdocs/accountancy/tpl/export_journal.tpl.php b/htdocs/accountancy/tpl/export_journal.tpl.php index 4dc4dedbe0e..f57d54fcfbd 100644 --- a/htdocs/accountancy/tpl/export_journal.tpl.php +++ b/htdocs/accountancy/tpl/export_journal.tpl.php @@ -1,6 +1,7 @@ +/* Copyright (C) 2015-2022 Open-DSI * Copyright (C) 2016 Charlie Benke + * Copyright (C) 2022 Progiseize * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From fb16a97d6d4e743c8f8a44884399a81badba2a88 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Tue, 13 Dec 2022 18:13:24 +0100 Subject: [PATCH 082/816] FIX stickler-ci --- htdocs/accountancy/bookkeeping/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 2f255dec734..781b20edc2e 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -860,7 +860,7 @@ if ($action == 'export_file') { } // add documents in an archive for accountancy export (Quadratus) - if(getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV') == AccountancyExport::$EXPORT_TYPE_QUADRATUS) { + if (getDolGlobalString('ACCOUNTING_EXPORT_MODELCSV') == AccountancyExport::$EXPORT_TYPE_QUADRATUS) { $form_question['notifiedexportfull'] = array( 'name' => 'notifiedexportfull', 'type' => 'checkbox', From b597a43b21a7488bd271f05d99da65539a3f0d96 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 14 Dec 2022 08:37:30 +0000 Subject: [PATCH 083/816] Fixing style errors. --- htdocs/bom/class/bom.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 4dfb47a3887..7f9a1aa09c6 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1073,7 +1073,7 @@ class BOM extends CommonObject if ($res>0) { $bom_child->calculateCosts(); $line->childBom[] = $bom_child; - $line->total_cost = price2num( $bom_child->total_cost * $line->qty, 'MT'); + $line->total_cost = price2num($bom_child->total_cost * $line->qty, 'MT'); $this->total_cost += $line->total_cost; } else { $this->error = $bom_child->error; From 1ebd2135e0f15c34fa62674ec9b19a7fcf4e6412 Mon Sep 17 00:00:00 2001 From: atm-lena Date: Thu, 15 Dec 2022 15:00:27 +0100 Subject: [PATCH 084/816] Fix stickler error --- htdocs/bom/tpl/objectline_view.tpl.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index bb83e62c07f..f9b39c517e9 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -221,12 +221,15 @@ if ($resql) { $label = $sub_bom_product->getLabelOfUnit('long'); if ($sub_bom_line->qty_frozen > 0) { print ''; - print ''; + print ''; print ''; } else { print ''; print ''; + if($label !== '') print $langs->trans($label); + print ''; print ''; print ''; } From ae3b9970dd60791dd86a53774aeafc5004145e5e Mon Sep 17 00:00:00 2001 From: Milen Karaganski Date: Sat, 17 Dec 2022 18:02:42 +0200 Subject: [PATCH 085/816] fix html.form.class.php --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 6df62ded8bd..9e26170f214 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -7286,7 +7286,7 @@ class Form $out .= $this->selectProjectsList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss); } - if (!empty($nooutput)) print $out; + if (empty($nooutput)) print $out; else return $out; } From 48b4caaa70178498146b230b9c1fceb826502c1c Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 19 Dec 2022 09:41:39 +0000 Subject: [PATCH 086/816] Fixing style errors. --- htdocs/bom/tpl/objectline_view.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index f9b39c517e9..85bd4d6b02a 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -228,7 +228,7 @@ if ($resql) { } else { print ''; print ''; print ''; print ''; From f90b887ec257c2580c9a8db36c4f39254fd8be13 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 19 Dec 2022 13:48:08 +0100 Subject: [PATCH 087/816] NEW mode view for list adherent --- htdocs/adherents/class/adherent.class.php | 36 ++ htdocs/adherents/list.php | 541 +++++++++++----------- 2 files changed, 319 insertions(+), 258 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 4c68b3e91ec..ec2cd91813d 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -3167,4 +3167,40 @@ class Adherent extends CommonObject return $nbko; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + + $return = '
'; + $return .= '
'; + $return .= ''; + + if (property_exists($this, 'photo') || !empty($this->photo)) { + $return.= Form::showphoto('memberphoto', $this, 0, 60, 0, 'photokanban photoref photowithmargin photologintooltip', 'small', 0, 1); + } else { + $return .= img_picto('', 'user'); + } + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + if (property_exists($this, 'type')) { + $return .= '
'.$this->type.''; + } + if (method_exists($this, 'getmorphylib')) { + $return .= '
'.$this->getmorphylib('', 2).''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index c2b81860210..6ef559deb75 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -47,6 +47,7 @@ $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'memberslist'; // To manage different context of search +$mode = GETPOST('mode', 'alpha'); // Search fields @@ -535,6 +536,9 @@ if ($search_type > 0) { } $param = ''; +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -636,6 +640,8 @@ if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'pr $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', 'creer')) { $newcardbutton .= dolGetButtonTitle($langs->trans('NewMember'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/adherents/card.php?action=create'); } @@ -650,6 +656,8 @@ print ''; print ''; print ''; print ''; +print ''; + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -988,276 +996,293 @@ while ($i < min($num, $limit)) { } $memberstatic->company = $companyname; - print '
'; - - // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; - } - - if (!empty($conf->global->MAIN_SHOW_TECHNICAL_ID)) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Ref - if (!empty($arrayfields['d.ref']['checked'])) { - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Civility - if (!empty($arrayfields['d.civility']['checked'])) { - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Firstname - if (!empty($arrayfields['d.firstname']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Lastname - if (!empty($arrayfields['d.lastname']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Gender - if (!empty($arrayfields['d.gender']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Company - if (!empty($arrayfields['d.company']['checked'])) { - print '\n"; - } - // Login - if (!empty($arrayfields['d.login']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Nature (Moral/Physical) - if (!empty($arrayfields['d.morphy']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Type label - if (!empty($arrayfields['t.libelle']['checked'])) { $membertypestatic->id = $obj->type_id; $membertypestatic->label = $obj->type; - print ''; - if (!$i) { - $totalarray['nbfield']++; + $memberstatic->type = $membertypestatic->label; + $memberstatic->photo = $obj->photo; + // Output Kanban + print $memberstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print ''; + print ''; } - } - // Address - if (!empty($arrayfields['d.address']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Zip - if (!empty($arrayfields['d.zip']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Town - if (!empty($arrayfields['d.town']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['state.nom']['checked'])) { - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['country.code_iso']['checked'])) { - $tmparray = getCountry($obj->country, 'all'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Phone pro - if (!empty($arrayfields['d.phone']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Phone perso - if (!empty($arrayfields['d.phone_perso']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Phone mobile - if (!empty($arrayfields['d.phone_mobile']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // EMail - if (!empty($arrayfields['d.email']['checked'])) { - print '\n"; - } - // End of subscription date - $datefin = $db->jdate($obj->datefin); - if (!empty($arrayfields['d.datefin']['checked'])) { - print ''; + + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + + if (!empty($conf->global->MAIN_SHOW_TECHNICAL_ID)) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Ref + if (!empty($arrayfields['d.ref']['checked'])) { + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Civility + if (!empty($arrayfields['d.civility']['checked'])) { + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Firstname + if (!empty($arrayfields['d.firstname']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Lastname + if (!empty($arrayfields['d.lastname']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Gender + if (!empty($arrayfields['d.gender']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Company + if (!empty($arrayfields['d.company']['checked'])) { + print '\n"; + } + // Login + if (!empty($arrayfields['d.login']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Nature (Moral/Physical) + if (!empty($arrayfields['d.morphy']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Type label + if (!empty($arrayfields['t.libelle']['checked'])) { + $membertypestatic->id = $obj->type_id; + $membertypestatic->label = $obj->type; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Address + if (!empty($arrayfields['d.address']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Zip + if (!empty($arrayfields['d.zip']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Town + if (!empty($arrayfields['d.town']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['state.nom']['checked'])) { + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['country.code_iso']['checked'])) { + $tmparray = getCountry($obj->country, 'all'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Phone pro + if (!empty($arrayfields['d.phone']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Phone perso + if (!empty($arrayfields['d.phone_perso']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Phone mobile + if (!empty($arrayfields['d.phone_mobile']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // EMail + if (!empty($arrayfields['d.email']['checked'])) { + print '\n"; + } + // End of subscription date + $datefin = $db->jdate($obj->datefin); + if (!empty($arrayfields['d.datefin']['checked'])) { + print ''; + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Date creation + if (!empty($arrayfields['d.datec']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; } } - print ''; - } - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - // Date creation - if (!empty($arrayfields['d.datec']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Birth - if (!empty($arrayfields['d.birth']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['d.tms']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status - if (!empty($arrayfields['d.statut']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['d.import_key']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Action column - if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; } - print ''; - } - if (!$i) { - $totalarray['nbfield']++; - } + // Date modification + if (!empty($arrayfields['d.tms']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status + if (!empty($arrayfields['d.statut']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['d.import_key']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } - print ''."\n"; + print ''."\n"; + } $i++; } From 517af503ed225d26e7a76df5e9891031fff2aa91 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Mon, 19 Dec 2022 14:27:22 +0100 Subject: [PATCH 088/816] NEW category of operation for crabe PDF model --- .../modules/facture/doc/pdf_crabe.modules.php | 57 +++++++++++++++++++ .../facture/doc/pdf_sponge.modules.php | 20 ++++--- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index ee4cc9b5d0d..30a61fbb1d3 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -132,6 +132,11 @@ class pdf_crabe extends ModelePDFFactures */ public $posxprogress; + /** + * @var int Category of operation + */ + public $categoryOfOperation = -1; // unknown by default + /** * Constructor @@ -402,11 +407,37 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right // Set $this->atleastonediscount if you have at least one discount + // and determine category of operation + $categoryOfOperation = 0; + $nbProduct = 0; + $nbService = 0; for ($i = 0; $i < $nblines; $i++) { if ($object->lines[$i]->remise_percent) { $this->atleastonediscount++; } + + // determine category of operation + if ($categoryOfOperation < 2) { + $lineProductType = $object->lines[$i]->product_type; + if ($lineProductType == Product::TYPE_PRODUCT) { + $nbProduct++; + } elseif ($lineProductType == Product::TYPE_SERVICE) { + $nbService++; + } + if ($nbProduct > 0 && $nbService > 0) { + // mixed products and services + $categoryOfOperation = 2; + } + } } + // determine category of operation + if ($categoryOfOperation <= 0) { + // only services + if ($nbProduct == 0 && $nbService > 0) { + $categoryOfOperation = 1; + } + } + $this->categoryOfOperation = $categoryOfOperation; if (empty($this->atleastonediscount)) { // retrieve space not used by discount $delta = ($this->posxprogress - $this->posxdiscount); $this->posxpicture += $delta; @@ -1128,6 +1159,10 @@ class pdf_crabe extends ModelePDFFactures } $posxval = 52; + $posxend = 110; // End of x for text on left side + if ($this->page_largeur < 210) { // To work with US executive format + $posxend -= 10; + } // Show payments conditions if ($object->type != 2 && ($object->cond_reglement_code || $object->cond_reglement)) { @@ -1145,6 +1180,21 @@ class pdf_crabe extends ModelePDFFactures $posy = $pdf->GetY() + 3; // We need spaces for 2 lines payment conditions } + // Show category of operations + if (getDolGlobalInt('INVOICE_CATEGORY_OF_OPERATION') == 2 && $this->categoryOfOperation >= 0) { + $pdf->SetFont('', 'B', $default_font_size - 2); + $pdf->SetXY($this->marge_gauche, $posy); + $categoryOfOperationTitle = $outputlangs->transnoentities("MentionCategoryOfOperations").' : '; + $pdf->MultiCell($posxval - $this->marge_gauche, 4, $categoryOfOperationTitle, 0, 'L'); + + $pdf->SetFont('', '', $default_font_size - 2); + $pdf->SetXY($posxval, $posy); + $categoryOfOperationLabel = $outputlangs->transnoentities("MentionCategoryOfOperations" . $this->categoryOfOperation); + $pdf->MultiCell($posxend - $posxval, 4, $categoryOfOperationLabel, 0, 'L'); + + $posy = $pdf->GetY() + 3; // for 2 lines + } + if ($object->type != 2) { // Check a payment mode is defined if (empty($object->mode_reglement_code) @@ -1659,6 +1709,13 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetFont('', '', $default_font_size - 2); if (empty($hidetop)) { + // Show category of operations + if (getDolGlobalInt('INVOICE_CATEGORY_OF_OPERATION') == 1 && $this->categoryOfOperation >= 0) { + $categoryOfOperations = $outputlangs->transnoentities("MentionCategoryOfOperations") . ' : ' . $outputlangs->transnoentities("MentionCategoryOfOperations" . $this->categoryOfOperation); + $pdf->SetXY($this->marge_gauche, $tab_top - 4); + $pdf->MultiCell(($pdf->GetStringWidth($categoryOfOperations)) + 4, 2, $categoryOfOperations); + } + $titre = $outputlangs->transnoentities("AmountInCurrency", $outputlangs->transnoentitiesnoconv("Currency".$currency)); $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 3), $tab_top - 4); $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index adf47af3cce..072ddb566bd 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -445,15 +445,17 @@ class pdf_sponge extends ModelePDFFactures } // determine category of operation - $lineProductType = $object->lines[$i]->product_type; - if ($lineProductType == Product::TYPE_PRODUCT) { - $nbProduct++; - } elseif ($lineProductType == Product::TYPE_SERVICE) { - $nbService++; - } - if ($nbProduct > 0 && $nbService > 0) { - // mixed products and services - $categoryOfOperation = 2; + if ($categoryOfOperation < 2) { + $lineProductType = $object->lines[$i]->product_type; + if ($lineProductType == Product::TYPE_PRODUCT) { + $nbProduct++; + } elseif ($lineProductType == Product::TYPE_SERVICE) { + $nbService++; + } + if ($nbProduct > 0 && $nbService > 0) { + // mixed products and services + $categoryOfOperation = 2; + } } } // determine category of operation From abd5a86f348256fa6ab2eb09b93bed678f0ff9d2 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 19 Dec 2022 15:19:12 +0100 Subject: [PATCH 089/816] mode Kanban for subscription list --- htdocs/adherents/class/subscription.class.php | 32 ++ htdocs/adherents/subscription/list.php | 275 ++++++++++-------- 2 files changed, 187 insertions(+), 120 deletions(-) diff --git a/htdocs/adherents/class/subscription.class.php b/htdocs/adherents/class/subscription.class.php index b3cfe027197..411fdb2181f 100644 --- a/htdocs/adherents/class/subscription.class.php +++ b/htdocs/adherents/class/subscription.class.php @@ -505,4 +505,36 @@ class Subscription extends CommonObject dol_print_error($this->db); } } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + + $return .= '
'; + $return .= ''.(property_exists($this, 'fk_adherent')? $this->fk_adherent: $this->ref ).''; + if (property_exists($this, 'dateh') || property_exists($this, 'datef')) { + $return .= '
'.dol_print_date($this->dateh, 'day').' - '.dol_print_date($this->datef, 'day').''; + } + + if (property_exists($this, 'fk_bank')) { + $return .= '
'.$this->fk_bank.''; + } + if (property_exists($this, 'amount')) { + $return .= '
'.price($this->amount).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index 1523bd4ee90..5aa19c6c6d0 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -37,6 +37,8 @@ $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'); + $statut = (GETPOSTISSET("statut") ?GETPOST("statut", "alpha") : 1); $search_ref = GETPOST('search_ref', 'alpha'); @@ -253,6 +255,9 @@ if (!empty($date_select)) { } $param = ''; +if (!empty($mode)) { + $param .='&mode='.urlencode($mode); +} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -298,6 +303,9 @@ if (in_array($massaction, array('presend', 'predelete'))) { $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->rights->adherent->cotisation->creer) { $newcardbutton .= dolGetButtonTitle($langs->trans('NewSubscription'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/adherents/list.php?status=-1,1'); } @@ -313,6 +321,8 @@ print ''; print ''; print ''; print ''; +print ''; + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, $subscription->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -506,144 +516,169 @@ while ($i < min($num, $limit)) { $adht->fetch($typeid); $adherent->need_subscription = $adht->subscription; - - print '
'; - - // Ref - if (!empty($arrayfields['d.ref']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; + + if ($mode == 'kanban') { + if ($i == 0) { + print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Lastname - if (!empty($arrayfields['d.lastname']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Firstname - if (!empty($arrayfields['d.firstname']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Login - if (!empty($arrayfields['d.login']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Label - if (!empty($arrayfields['t.libelle']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Banque - if (!empty($arrayfields['d.bank']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; + // Output Kanban + print $subscription->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print ''; + print ''; } } - // Date start - if (!empty($arrayfields['c.dateadh']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; + else { + print ''; + + // Ref + if (!empty($arrayfields['d.ref']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Date end - if (!empty($arrayfields['c.datef']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; + // Type + if (!empty($arrayfields['d.fk_type']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Price - if (!empty($arrayfields['d.amount']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; + + // Lastname + if (!empty($arrayfields['d.lastname']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'd.amount'; + // Firstname + if (!empty($arrayfields['d.firstname']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - if (empty($totalarray['val']['d.amount'])) { - $totalarray['val']['d.amount'] = $obj->subscription; - } else { - $totalarray['val']['d.amount'] += $obj->subscription; + + // Login + if (!empty($arrayfields['d.login']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Label + if (!empty($arrayfields['t.libelle']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Banque + if (!empty($arrayfields['d.bank']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date start + if (!empty($arrayfields['c.dateadh']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date end + if (!empty($arrayfields['c.datef']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Price + if (!empty($arrayfields['d.amount']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'd.amount'; + } + if (empty($totalarray['val']['d.amount'])) { + $totalarray['val']['d.amount'] = $obj->subscription; + } else { + $totalarray['val']['d.amount'] += $obj->subscription; + } + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Date creation + if (!empty($arrayfields['c.datec']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['c.tms']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Action column + print ''; if (!$i) { $totalarray['nbfield']++; } - } - // Date modification - if (!empty($arrayfields['c.tms']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Action column - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - print "\n"; + print "\n"; + } $i++; } From 0c75e5bb2d81adb5cfa356e528c0cf77ec2c94c2 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 19 Dec 2022 15:19:18 +0100 Subject: [PATCH 090/816] mode Kanban for subscription list --- htdocs/adherents/class/subscription.class.php | 2 +- htdocs/adherents/subscription/list.php | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/htdocs/adherents/class/subscription.class.php b/htdocs/adherents/class/subscription.class.php index 411fdb2181f..12e19fd9c3a 100644 --- a/htdocs/adherents/class/subscription.class.php +++ b/htdocs/adherents/class/subscription.class.php @@ -525,7 +525,7 @@ class Subscription extends CommonObject if (property_exists($this, 'dateh') || property_exists($this, 'datef')) { $return .= '
'.dol_print_date($this->dateh, 'day').' - '.dol_print_date($this->datef, 'day').''; } - + if (property_exists($this, 'fk_bank')) { $return .= '
'.$this->fk_bank.''; } diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index 5aa19c6c6d0..501bd9c80e5 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -516,13 +516,13 @@ while ($i < min($num, $limit)) { $adht->fetch($typeid); $adherent->need_subscription = $adht->subscription; - + if ($mode == 'kanban') { if ($i == 0) { print '
'; } - } - - else { + } else { print ''; // Ref From aed3f841bc1424304bc44e71449456d38ea3a2f7 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 20 Dec 2022 11:27:55 +0100 Subject: [PATCH 091/816] New View mode for Adherent Type list --- .../adherents/class/adherent_type.class.php | 42 +++++++++++ htdocs/adherents/type.php | 71 ++++++++++++------- 2 files changed, 89 insertions(+), 24 deletions(-) diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 4516b132982..25211f11bd9 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -927,4 +927,46 @@ class AdherentType extends CommonObject return ''; } + + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return void HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs,$user; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + if ($user->rights->adherent->configurer) { + $return .= 'ref.'">'.img_edit().''; + } else { + $return .= ' '; + } + if (property_exists($this, 'vote')) { + $return .= '
'.$langs->trans("VoteAllowed").' : '.yn($this->vote).''; + } + if (property_exists($this, 'amount')) { + if (is_null($this->amount) || $this->amount === '') { + $return .= '
'; + } else { + $return .= '
'.$langs->trans("Amount").''; + $return .= ' : '.price($this->amount).''; + } + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + print $return; + } } diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 257e7266e5a..6a2dbdb125d 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -44,6 +44,7 @@ $action = GETPOST('action', 'aZ09'); $cancel = GETPOST('cancel', 'alpha'); $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'); +$mode = GETPOST('mode', 'alopha'); $sall = GETPOST("sall", "alpha"); $filter = GETPOST("filter", 'alpha'); @@ -248,6 +249,9 @@ if (!$rowid && $action != 'create' && $action != 'edit') { $i = 0; $param = ''; + if (!empty($mode)) { + $param .= '&mode'.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.$contextpage; } @@ -256,6 +260,9 @@ if (!$rowid && $action != 'create' && $action != 'edit') { } $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->rights->adherent->configurer) { $newcardbutton .= dolGetButtonTitle($langs->trans('NewMemberType'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/adherents/type.php?action=create'); } @@ -269,6 +276,8 @@ if (!$rowid && $action != 'create' && $action != 'edit') { print ''; print ''; print ''; + print ''; + print_barre_liste($langs->trans("MembersTypes"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'members', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -302,32 +311,46 @@ if (!$rowid && $action != 'create' && $action != 'edit') { $membertype->amount = $objp->amount; $membertype->caneditamount = $objp->caneditamount; - print '
'; - print ''; - print ''; - print ''; + } } else { - print $langs->trans("MorAndPhy"); + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if ($user->rights->adherent->configurer) { + print ''; + } else { + print ''; + } + print ""; } - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - if ($user->rights->adherent->configurer) { - print ''; - } else { - print ''; - } - print ""; $i++; } From 54bd44e14af1744946b0d8d8148080b84be49422 Mon Sep 17 00:00:00 2001 From: kkhelifa Date: Tue, 20 Dec 2022 11:43:42 +0100 Subject: [PATCH 092/816] NEW : notify also the contributor affected to a ticket if a new message public is post (add global TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_ALSO_CONTRIBUTOR) --- htdocs/ticket/class/ticket.class.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 2a3160b3b67..10c0541c168 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2449,6 +2449,16 @@ class Ticket extends CommonObject $assigned_user_dont_have_email = $assigned_user->getFullName($langs); } } + if (!empty($conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_ALSO_CONTRIBUTOR)) { + $contactList = $object->liste_contact(-1, 'internal', 0, 'CONTRIBUTOR'); + if (is_array($contactList)) { + foreach ($contactList as $contactArray) { + if (!empty($contactArray['email'])) { + $sendto[] = dolGetFirstLastname($contactArray['firstname'], $contactArray['lastname']) . " <" . $contactArray['email'] . ">"; + } + } + } + } if (empty($sendto)) { if (!empty($conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL)) { $sendto[] = $conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL; From a849283e378b883ec59c6702efa1dcd2cbc2010e Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 20 Dec 2022 12:41:54 +0100 Subject: [PATCH 093/816] update return type --- htdocs/adherents/class/adherent_type.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 25211f11bd9..e0311aacd34 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -933,7 +933,7 @@ class AdherentType extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return void HTML Code for Kanban thumb. + * @return string HTML Code for Kanban thumb. */ public function getKanbanView($option = '') { @@ -967,6 +967,6 @@ class AdherentType extends CommonObject $return .= ''; $return .= ''; $return .= ''; - print $return; + return $return; } } From 0582653a679d0da3399f399ed39d634d46c99d57 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Wed, 21 Dec 2022 10:55:03 +0100 Subject: [PATCH 094/816] FIX : get multicurrency infos of propal when create order from propal with "WORKFLOW_PROPAL_AUTOCREATE_ORDER" conf --- htdocs/commande/class/commande.class.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 54e50baa9f7..2e20567e4c5 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1355,6 +1355,27 @@ class Commande extends CommonOrder $this->origin = $object->element; $this->origin_id = $object->id; + // Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate) + if (!empty($conf->multicurrency->enabled)) { + if (!empty($object->multicurrency_code)) { + $this->multicurrency_code = $object->multicurrency_code; + } + if (!empty($conf->global->MULTICURRENCY_USE_ORIGIN_TX) && !empty($object->multicurrency_tx)) { + $this->multicurrency_tx = $object->multicurrency_tx; + } + + if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) { + list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $this->date_commande); + } else { + $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); + } + if (empty($this->fk_multicurrency)) { + $this->multicurrency_code = $conf->currency; + $this->fk_multicurrency = 0; + $this->multicurrency_tx = 1; + } + } + // get extrafields from original line $object->fetch_optionals(); From 3b9d39c1d2fae893b272532167353a64ba866ba1 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 21 Dec 2022 10:00:26 +0000 Subject: [PATCH 095/816] Fixing style errors. --- htdocs/commande/class/commande.class.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 2e20567e4c5..12054c3ccb8 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1355,7 +1355,7 @@ class Commande extends CommonOrder $this->origin = $object->element; $this->origin_id = $object->id; - // Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate) + // Multicurrency (test on $this->multicurrency_tx because we should take the default rate only if not using origin rate) if (!empty($conf->multicurrency->enabled)) { if (!empty($object->multicurrency_code)) { $this->multicurrency_code = $object->multicurrency_code; @@ -1364,16 +1364,16 @@ class Commande extends CommonOrder $this->multicurrency_tx = $object->multicurrency_tx; } - if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) { - list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $this->date_commande); - } else { - $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); - } - if (empty($this->fk_multicurrency)) { - $this->multicurrency_code = $conf->currency; - $this->fk_multicurrency = 0; - $this->multicurrency_tx = 1; - } + if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) { + list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $this->date_commande); + } else { + $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); + } + if (empty($this->fk_multicurrency)) { + $this->multicurrency_code = $conf->currency; + $this->fk_multicurrency = 0; + $this->multicurrency_tx = 1; + } } // get extrafields from original line From 471260738ab41260459150b7ad3ccefbb9af4574 Mon Sep 17 00:00:00 2001 From: IC-Florian <71641704+IC-Florian@users.noreply.github.com> Date: Wed, 21 Dec 2022 12:03:32 +0100 Subject: [PATCH 096/816] FIX : Product list in setup.php in new Module --- htdocs/modulebuilder/template/admin/setup.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/modulebuilder/template/admin/setup.php b/htdocs/modulebuilder/template/admin/setup.php index 1c46028b142..37fa410f1e7 100644 --- a/htdocs/modulebuilder/template/admin/setup.php +++ b/htdocs/modulebuilder/template/admin/setup.php @@ -55,6 +55,7 @@ global $langs, $user; // Libraries require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; require_once '../lib/mymodule.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; //require_once "../class/myclass.class.php"; // Translations From a48d1ae8e392cc2b2ad9d9c324983d1e6193c1b1 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Wed, 21 Dec 2022 12:31:24 +0100 Subject: [PATCH 097/816] FIX : multicurrency_tx and not currency_tx --- htdocs/compta/facture/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index c0d7cf53a5d..4f3d9230899 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2929,8 +2929,8 @@ if ($action == 'create') { $remise_absolue = (!empty($expesrc->remise_absolue) ? $expesrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0)); if (!empty($conf->multicurrency->enabled)) { - $currency_code = (!empty($expesrc->currency_code) ? $expesrc->currency_code : (!empty($soc->currency_code) ? $soc->currency_code : $objectsrc->multicurrency_code)); - $currency_tx = (!empty($expesrc->currency_tx) ? $expesrc->currency_tx : (!empty($soc->currency_tx) ? $soc->currency_tx : $objectsrc->currency_tx)); + $currency_code = (!empty($expesrc->multicurrency_code) ? $expesrc->multicurrency_code : (!empty($soc->multicurrency_code) ? $soc->multicurrency_code : $objectsrc->multicurrency_code)); + $currency_tx = (!empty($expesrc->multicurrency_tx) ? $expesrc->multicurrency_tx : (!empty($soc->multicurrency_tx) ? $soc->multicurrency_tx : $objectsrc->multicurrency_tx)); } //Replicate extrafields From c033a4778e68f8371ff7a4983a0751de0ed6b591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Llu=C3=ADs?= Date: Wed, 21 Dec 2022 13:17:18 +0100 Subject: [PATCH 098/816] New filter for Signed+Billed in proposals New filter for Signed+Billed in proposals --- htdocs/core/class/html.formpropal.class.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index e23e71a8124..d9c458161bc 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -132,6 +132,14 @@ class FormPropal print ''; $i++; } + //Option for Signed+Billed + if ($selected != '' && $selected == "2,4") { + print ''; print ''; print ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($showempty < 0 ? (string) $showempty : '-1'), $morecss); From 3004c3cd920b815651aaa36c491cd4444d7fb1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josep=20Llu=C3=ADs?= Date: Wed, 21 Dec 2022 13:22:56 +0100 Subject: [PATCH 099/816] Update html.formpropal.class.php --- htdocs/core/class/html.formpropal.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index d9c458161bc..48551926e1f 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -1,5 +1,6 @@ + * Copyright (C) 2022 Josep Lluís Amador * * 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 80d6c262029ec69caec69db358fa4fbae5cc89ec Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 21 Dec 2022 12:31:33 +0000 Subject: [PATCH 100/816] Fixing style errors. --- htdocs/core/class/html.formpropal.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index 48551926e1f..fbbf2c97fb7 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -135,12 +135,12 @@ class FormPropal } //Option for Signed+Billed if ($selected != '' && $selected == "2,4") { - print ''; + print ''; print ''; print ajax_combobox($htmlname, array(), 0, 0, 'resolve', ($showempty < 0 ? (string) $showempty : '-1'), $morecss); From 69b0cf9bcfeeab25166131128b3f229477255771 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Wed, 21 Dec 2022 14:05:54 +0100 Subject: [PATCH 101/816] FIX : include class multicurrency --- htdocs/commande/class/commande.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 12054c3ccb8..d56eeb2af0e 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1281,6 +1281,7 @@ class Commande extends CommonOrder { global $conf, $hookmanager; + dol_include_once('/multicurrency/class/multicurrency.class.php'); dol_include_once('/core/class/extrafields.class.php'); $error = 0; From 2c7e0afabd7c04cbde50fcd9734edc75ac60cb35 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Wed, 21 Dec 2022 17:17:33 +0100 Subject: [PATCH 102/816] FIX : travis --- htdocs/commande/class/commande.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index d56eeb2af0e..33de271b45d 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1366,7 +1366,9 @@ class Commande extends CommonOrder } if (!empty($this->multicurrency_code) && empty($this->multicurrency_tx)) { - list($this->fk_multicurrency, $this->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $this->date_commande); + $tmparray = MultiCurrency::getIdAndTxFromCode($this->db, $this->multicurrency_code, $this->date_commande); + $this->fk_multicurrency = $tmparray[0]; + $this->multicurrency_tx = $tmparray[1]; } else { $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); } From 20cd8348394af379df498ee23fa0391176745322 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 22 Dec 2022 10:15:21 +0000 Subject: [PATCH 103/816] Fixing style errors. --- htdocs/product/list.php | 1339 +++++++++++++++++++-------------------- 1 file changed, 667 insertions(+), 672 deletions(-) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index c4473a9376a..f7634c7311b 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -675,7 +675,7 @@ if (GETPOST('delprod')) { $param = ''; if (!empty($mode)) { - $param = "&mode=".urlencode($mode); + $param = "&mode=".urlencode($mode); } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); @@ -788,26 +788,26 @@ $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 ($type === "") { - $perm = ($user->rights->produit->creer || $user->rights->service->creer); - } elseif ($type == Product::TYPE_SERVICE) { - $perm = $user->rights->service->creer; - } elseif ($type == Product::TYPE_PRODUCT) { - $perm = $user->rights->produit->creer; - } +if ($type === "") { + $perm = ($user->rights->produit->creer || $user->rights->service->creer); +} elseif ($type == Product::TYPE_SERVICE) { + $perm = $user->rights->service->creer; +} elseif ($type == Product::TYPE_PRODUCT) { + $perm = $user->rights->produit->creer; +} $oldtype = $type; $params = array(); - if ($type === "") { - $params['forcenohideoftext'] = 1; - } - if ($type === "") { - $newcardbutton .= dolGetButtonTitle($langs->trans('NewProduct'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=0', '', $perm, $params); - $type = Product::TYPE_SERVICE; - } +if ($type === "") { + $params['forcenohideoftext'] = 1; +} +if ($type === "") { + $newcardbutton .= dolGetButtonTitle($langs->trans('NewProduct'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type=0', '', $perm, $params); + $type = Product::TYPE_SERVICE; +} $label = 'NewProduct'; - if ($type == Product::TYPE_SERVICE) { - $label = 'NewService'; - } +if ($type == Product::TYPE_SERVICE) { + $label = 'NewService'; +} $newcardbutton .= dolGetButtonTitle($langs->trans($label), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/product/card.php?action=create&type='.$type, '', $perm, $params); @@ -1337,679 +1337,99 @@ print "\n"; $totalarray = array(); $totalarray['nbfield'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); - while ($i < $imaxinloop) { - $obj = $db->fetch_object($resql); +while ($i < $imaxinloop) { + $obj = $db->fetch_object($resql); - // Multilangs - if (getDolGlobalInt('MAIN_MULTILANGS')) { // If multilang is enabled - $sql = "SELECT label"; - $sql .= " FROM ".MAIN_DB_PREFIX."product_lang"; - $sql .= " WHERE fk_product = ".((int) $obj->rowid); - $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'"; - $sql .= " LIMIT 1"; - - $result = $db->query($sql); - if ($result) { - $objtp = $db->fetch_object($result); - if (!empty($objtp->label)) { - $obj->label = $objtp->label; - } + // Multilangs + if (getDolGlobalInt('MAIN_MULTILANGS')) { // If multilang is enabled + $sql = "SELECT label"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_lang"; + $sql .= " WHERE fk_product = ".((int) $obj->rowid); + $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'"; + $sql .= " LIMIT 1"; + $result = $db->query($sql); + if ($result) { + $objtp = $db->fetch_object($result); + if (!empty($objtp->label)) { + $obj->label = $objtp->label; } } } +} $parameters = array('staticdata' => $obj); // Note that $action and $object may have been modified by hook // do product_static fetch in hook if wanted or anything else $reshook = $hookmanager->executeHooks('loadStaticObject', $parameters, $product_static, $action); - if (empty($reshook)) { - $product_static->id = $obj->rowid; - $product_static->ref = $obj->ref; - $product_static->ref_fourn = empty($obj->ref_supplier) ? '' : $obj->ref_supplier; // deprecated - $product_static->ref_supplier = empty($obj->ref_supplier) ? '' : $obj->ref_supplier; - $product_static->label = $obj->label; - $product_static->finished = $obj->finished; - $product_static->type = $obj->fk_product_type; - $product_static->status_buy = $obj->tobuy; - $product_static->status = $obj->tosell; - $product_static->status_batch = $obj->tobatch; - $product_static->entity = $obj->entity; - $product_static->pmp = $obj->pmp; - $product_static->accountancy_code_sell = $obj->accountancy_code_sell; - $product_static->accountancy_code_sell_export = $obj->accountancy_code_sell_export; - $product_static->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra; - $product_static->accountancy_code_buy = $obj->accountancy_code_buy; - $product_static->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra; - $product_static->accountancy_code_buy_export = $obj->accountancy_code_buy_export; - $product_static->length = $obj->length; - $product_static->length_units = $obj->length_units; - $product_static->width = $obj->width; - $product_static->width_units = $obj->width_units; - $product_static->height = $obj->height; - $product_static->height_units = $obj->height_units; - $product_static->weight = $obj->weight; - $product_static->weight_units = $obj->weight_units; - $product_static->volume = $obj->volume; - $product_static->volume_units = $obj->volume_units; - $product_static->surface = $obj->surface; - $product_static->surface_units = $obj->surface_units; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { - $product_static->fk_unit = $obj->fk_unit; - } +if (empty($reshook)) { + $product_static->id = $obj->rowid; + $product_static->ref = $obj->ref; + $product_static->ref_fourn = empty($obj->ref_supplier) ? '' : $obj->ref_supplier; // deprecated + $product_static->ref_supplier = empty($obj->ref_supplier) ? '' : $obj->ref_supplier; + $product_static->label = $obj->label; + $product_static->finished = $obj->finished; + $product_static->type = $obj->fk_product_type; + $product_static->status_buy = $obj->tobuy; + $product_static->status = $obj->tosell; + $product_static->status_batch = $obj->tobatch; + $product_static->entity = $obj->entity; + $product_static->pmp = $obj->pmp; + $product_static->accountancy_code_sell = $obj->accountancy_code_sell; + $product_static->accountancy_code_sell_export = $obj->accountancy_code_sell_export; + $product_static->accountancy_code_sell_intra = $obj->accountancy_code_sell_intra; + $product_static->accountancy_code_buy = $obj->accountancy_code_buy; + $product_static->accountancy_code_buy_intra = $obj->accountancy_code_buy_intra; + $product_static->accountancy_code_buy_export = $obj->accountancy_code_buy_export; + $product_static->length = $obj->length; + $product_static->length_units = $obj->length_units; + $product_static->width = $obj->width; + $product_static->width_units = $obj->width_units; + $product_static->height = $obj->height; + $product_static->height_units = $obj->height_units; + $product_static->weight = $obj->weight; + $product_static->weight_units = $obj->weight_units; + $product_static->volume = $obj->volume; + $product_static->volume_units = $obj->volume_units; + $product_static->surface = $obj->surface; + $product_static->surface_units = $obj->surface_units; + if (!empty($conf->global->PRODUCT_USE_UNITS)) { + $product_static->fk_unit = $obj->fk_unit; + } - // STOCK_DISABLE_OPTIM_LOAD can be set to force load_stock whatever is permissions on stock. - if ((isModEnabled('stock') && $user->rights->stock->lire && $search_type != 1) || !empty($conf->global->STOCK_DISABLE_OPTIM_LOAD)) { // To optimize call of load_stock - if ($product_static->type != 1 || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { // Not a service - $option = 'nobatch'; - if (empty($arrayfields['stock_virtual']['checked'])) { - $option .= ',novirtual'; - } - $product_static->load_stock($option); // Load stock_reel + stock_warehouse. This can also call load_virtual_stock() + // STOCK_DISABLE_OPTIM_LOAD can be set to force load_stock whatever is permissions on stock. + if ((isModEnabled('stock') && $user->rights->stock->lire && $search_type != 1) || !empty($conf->global->STOCK_DISABLE_OPTIM_LOAD)) { // To optimize call of load_stock + if ($product_static->type != 1 || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { // Not a service + $option = 'nobatch'; + if (empty($arrayfields['stock_virtual']['checked'])) { + $option .= ',novirtual'; } + $product_static->load_stock($option); // Load stock_reel + stock_warehouse. This can also call load_virtual_stock() } } +} $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('product', 'lire'); - if ($product_static->isService()) { - $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'lire'); - } - if ($mode == 'Kanban') { - if ($i == 0) { - print ''; - } - } else { - print ''; - - // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Ref - if (!empty($arrayfields['p.rowid']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Ref - if (!empty($arrayfields['p.ref']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Ref supplier - if (!empty($arrayfields['pfp.ref_fourn']['checked'])) { - print '\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Thumbnail - if (!empty($arrayfields['thumbnail']['checked'])) { - $product_thumbnail_html = ''; - if (!empty($product_static->entity)) { - $product_thumbnail = $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80); - if ($product_static->nbphoto > 0) { - $product_thumbnail_html = $product_thumbnail; - } - } - - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Label - if (!empty($arrayfields['p.label']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Type - if (!empty($arrayfields['p.fk_product_type']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Barcode - if (!empty($arrayfields['p.barcode']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Duration - if (!empty($arrayfields['p.duration']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Finished - if (!empty($arrayfields['p.finished']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Weight - if (!empty($arrayfields['p.weight']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Weight units - if (!empty($arrayfields['p.weight_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Length - if (!empty($arrayfields['p.length']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Length units - if (!empty($arrayfields['p.length_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Width - if (!empty($arrayfields['p.width']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Width units - if (!empty($arrayfields['p.width_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Height - if (!empty($arrayfields['p.height']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Height units - if (!empty($arrayfields['p.height_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Surface - if (!empty($arrayfields['p.surface']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Surface units - if (!empty($arrayfields['p.surface_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Volume - if (!empty($arrayfields['p.volume']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Volume units - if (!empty($arrayfields['p.volume_units']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Unit - if (!empty($arrayfields['cu.label']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Sell price - if (!empty($arrayfields['p.sellprice']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - - // Multiprices - if (!empty($conf->global->PRODUIT_MULTIPRICES)) { - if (! isset($productpricescache)) { - $productpricescache=array(); - } - if (! isset($productpricescache[$obj->rowid])) { - $productpricescache[$obj->rowid] = array(); - } - - if ($obj->tosell && $usercancreadprice) { - // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array - // then reuse the cache array if we need prices for other price levels - $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type"; - $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p"; - $sqlp .= " WHERE fk_product = ".((int) $obj->rowid); - $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; - $resultp = $db->query($sqlp); - if ($resultp) { - $nump = $db->num_rows($resultp); - $j = 0; - while ($j < $nump) { - $objp = $db->fetch_object($resultp); - - if (empty($productpricescache[$obj->rowid][$objp->price_level])) { - $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price; - $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc; - $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type; - } - - $j++; - } - - $db->free($resultp); - } else { - dol_print_error($db); - } - } - - foreach ($arraypricelevel as $key => $value) { - if (!empty($arrayfields['p.sellprice'.$key]['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - - } - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - } +if ($product_static->isService()) { + $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'lire'); +} +if ($mode == 'Kanban') { + if ($i == 0) { + print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Number of buy prices - if (!empty($arrayfields['p.numbuyprice']['checked'])) { - print ''; - } - - // VAT or Sell Tax Rate - if (!empty($arrayfields['p.tva_tx']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // WAP - if (!empty($arrayfields['p.pmp']['checked'])) { - print ''; - } - // Cost price - if (!empty($arrayfields['p.cost_price']['checked'])) { - print ''; - } - - // Limit alert - if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Desired stock - if (!empty($arrayfields['p.desiredstock']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Stock real - if (!empty($arrayfields['p.stock']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Stock virtual - if (!empty($arrayfields['stock_virtual']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Lot/Serial - if (!empty($arrayfields['p.tobatch']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['p.fk_country']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['p.fk_state']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Accountancy code sell - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Accountancy code buy - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, '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; - // Date creation - if (!empty($arrayfields['p.datec']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['p.tms']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Status (to sell) - if (!empty($arrayfields['p.tosell']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status (to buy) - if (!empty($arrayfields['p.tobuy']['checked'])) { - print ''; - if (!$i) { - $totalarray['nbfield']++; - } + $product_static->price = $obj->price; + // Output Kanban + print $product_static->getKanbanView(''); + if ($i == ($imaxinloop - 1)) { + print ''; + print ''; } +} else { + print ''; // Action column - if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print '\n"; $totalarray['nbfield']++; } } + // Ref + if (!empty($arrayfields['p.rowid']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Ref + if (!empty($arrayfields['p.ref']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Ref supplier + if (!empty($arrayfields['pfp.ref_fourn']['checked'])) { + print '\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Thumbnail + if (!empty($arrayfields['thumbnail']['checked'])) { + $product_thumbnail_html = ''; + if (!empty($product_static->entity)) { + $product_thumbnail = $product_static->show_photos('product', $conf->product->multidir_output[$product_static->entity], 1, 1, 0, 0, 0, 80); + if ($product_static->nbphoto > 0) { + $product_thumbnail_html = $product_thumbnail; + } + } + + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Label + if (!empty($arrayfields['p.label']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Type + if (!empty($arrayfields['p.fk_product_type']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Barcode + if (!empty($arrayfields['p.barcode']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Duration + if (!empty($arrayfields['p.duration']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Finished + if (!empty($arrayfields['p.finished']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Weight + if (!empty($arrayfields['p.weight']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Weight units + if (!empty($arrayfields['p.weight_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Length + if (!empty($arrayfields['p.length']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Length units + if (!empty($arrayfields['p.length_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Width + if (!empty($arrayfields['p.width']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Width units + if (!empty($arrayfields['p.width_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Height + if (!empty($arrayfields['p.height']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Height units + if (!empty($arrayfields['p.height_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Surface + if (!empty($arrayfields['p.surface']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Surface units + if (!empty($arrayfields['p.surface_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Volume + if (!empty($arrayfields['p.volume']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Volume units + if (!empty($arrayfields['p.volume_units']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Unit + if (!empty($arrayfields['cu.label']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Sell price + if (!empty($arrayfields['p.sellprice']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + + // Multiprices + if (!empty($conf->global->PRODUIT_MULTIPRICES)) { + if (! isset($productpricescache)) { + $productpricescache=array(); + } + if (! isset($productpricescache[$obj->rowid])) { + $productpricescache[$obj->rowid] = array(); + } + + if ($obj->tosell && $usercancreadprice) { + // Make 1 request for all price levels (without filter on price_level) and saved result into an cache array + // then reuse the cache array if we need prices for other price levels + $sqlp = "SELECT p.rowid, p.fk_product, p.price, p.price_ttc, p.price_level, p.date_price, p.price_base_type"; + $sqlp .= " FROM ".MAIN_DB_PREFIX."product_price as p"; + $sqlp .= " WHERE fk_product = ".((int) $obj->rowid); + $sqlp .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; + $resultp = $db->query($sqlp); + if ($resultp) { + $nump = $db->num_rows($resultp); + $j = 0; + while ($j < $nump) { + $objp = $db->fetch_object($resultp); + + if (empty($productpricescache[$obj->rowid][$objp->price_level])) { + $productpricescache[$obj->rowid][$objp->price_level]['price'] = $objp->price; + $productpricescache[$obj->rowid][$objp->price_level]['price_ttc'] = $objp->price_ttc; + $productpricescache[$obj->rowid][$objp->price_level]['price_base_type'] = $objp->price_base_type; + } + + $j++; + } + + $db->free($resultp); + } else { + dol_print_error($db); + } + } + + foreach ($arraypricelevel as $key => $value) { + if (!empty($arrayfields['p.sellprice'.$key]['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } +} + } + + // Better buy price +if (!empty($arrayfields['p.minbuyprice']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + + // Number of buy prices +if (!empty($arrayfields['p.numbuyprice']['checked'])) { + print ''; +} + + // VAT or Sell Tax Rate +if (!empty($arrayfields['p.tva_tx']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + + // WAP +if (!empty($arrayfields['p.pmp']['checked'])) { + print ''; +} + // Cost price +if (!empty($arrayfields['p.cost_price']['checked'])) { + print ''; +} + + // Limit alert +if (!empty($arrayfields['p.seuil_stock_alerte']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Desired stock +if (!empty($arrayfields['p.desiredstock']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Stock real +if (!empty($arrayfields['p.stock']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Stock virtual +if (!empty($arrayfields['stock_virtual']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Lot/Serial +if (!empty($arrayfields['p.tobatch']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Country +if (!empty($arrayfields['p.fk_country']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // State +if (!empty($arrayfields['p.fk_state']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Accountancy code sell +if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} +if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_intra']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} +if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_sell_export']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Accountancy code buy +if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} +if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_intra']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} +if (!empty($arrayfields[$alias_product_perentity . '.accountancy_code_buy_export']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, '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; + // Date creation +if (!empty($arrayfields['p.datec']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Date modification +if (!empty($arrayfields['p.tms']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + + // Status (to sell) +if (!empty($arrayfields['p.tosell']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + // Status (to buy) +if (!empty($arrayfields['p.tobuy']['checked'])) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} + + // Action column +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if (!$i) { + $totalarray['nbfield']++; + } +} print "\n"; - + } $i++; } From 53ba5c0a4939e019a34e265bb8528e0b163cd781 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 22 Dec 2022 10:22:57 +0000 Subject: [PATCH 104/816] Fixing style errors. --- htdocs/adherents/type.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 0d8b37bbeb9..3796522e70e 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -264,9 +264,8 @@ if (!$rowid && $action != 'create' && $action != 'edit') { $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', 'configurer')) { + if ($user->hasRight('adherent', 'configurer')) { $newcardbutton .= dolGetButtonTitle($langs->trans('NewMemberType'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/adherents/type.php?action=create'); } @@ -327,8 +326,7 @@ if (!$rowid && $action != 'create' && $action != 'edit') { print ''; print ''; } - } - else { + } else { print ''; print ''; // IBAN - print ''; // BIC - print ''; if (!empty($conf->prelevement->enabled)) { From 2aa271d96eea915d56f5230689b25b2a0ffe539c Mon Sep 17 00:00:00 2001 From: Eric Seigne Date: Wed, 28 Dec 2022 17:50:16 +0100 Subject: [PATCH 120/816] avoid editretainedwarranty if invoice is not draft --- htdocs/compta/facture/card.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index c0d7cf53a5d..d682a17d91b 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -4517,13 +4517,13 @@ if ($action == 'create') { print '
 '; $searchpicto = $form->showFilterButtons(); @@ -1055,6 +1086,7 @@ if ($action == 'create' && $user->rights->projet->creer && (empty($object->third $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; + print '
'.price($sub_bom->total_cost * $sub_bom_line->qty * $line->qty).''.price2num($sub_bom->total_cost * $sub_bom_line->qty * $line->qty, 'MT').''.price($sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty).''.price2num($sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty, 'MT').''.price($sub_bom_product->pmp * $sub_bom_line->qty * $line->qty).''.price2num($sub_bom_product->pmp * $sub_bom_line->qty * $line->qty, 'MT').''.price($line_cost).''.price2num($line_cost, 'MT').''.price($sub_bom_line->qty, 0, '', 0, 0).''.($label !== '') ? $langs->trans($label) : '' . ''.$langs->trans('Yes').''.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; + print ''.($label !== '') ? $langs->trans($label) : '' . ' '.price($sub_bom_line->qty, 0, '', 0, 0).''.($label !== '') ? $langs->trans($label) : '' . ''; + if ($label !== '') print $langs->trans($label); + print ''.$langs->trans('Yes').''.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; - print ''.($label !== '') ? $langs->trans($label) : '' . ' '.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; - if($label !== '') print $langs->trans($label); + if ($label !== '') print $langs->trans($label); 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->rowid, $arrayofselected)) { - $selected = 1; - } - print ''; + if ($mode == 'kanban') { + if ($i == 0) { + print '
'; + print '
'; } - print '
'.$obj->rowid.'"; - print $memberstatic->getNomUrl(-1, 0, 'card', 'ref', '', -1, 0, 1); - print ""; - print $obj->civility; - print "'; - print $memberstatic->getNomUrl(0, 0, 'card', 'firstname'); - //print $obj->firstname; - print "'; - print $memberstatic->getNomUrl(0, 0, 'card', 'lastname'); - //print $obj->lastname; - print "'; - if ($obj->gender) { - print $langs->trans("Gender".$obj->gender); - } - print ''; - print $companynametoshow; - print "'.$obj->login."'; - print $memberstatic->getmorphylib('', 2); - print "'; - print $membertypestatic->getNomUrl(1, 32); - print '
'; - print $obj->address; - print ''; - print $obj->zip; - print ''; - print $obj->town; - print '".$obj->state_name."'; - print dol_escape_htmltag($tmparray['label']); - print ''; - print $obj->phone; - print ''; - print $obj->phone_perso; - print ''; - print $obj->phone_mobile; - print ''; - print dol_print_email($obj->email, 0, 0, 1, 64, 1, 1); - print "'; - if ($datefin) { - print dol_print_date($datefin, 'day'); - if ($memberstatic->hasDelay()) { - $textlate = ' ('.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24) >= 0 ? '+' : '').ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24).' '.$langs->trans("days").')'; - print " ".img_warning($langs->trans("SubscriptionLate").$textlate); + } else { + 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - } else { - if (!empty($obj->subscription)) { - print ''.$langs->trans("SubscriptionNotReceived").''; - if ($obj->statut > 0) { - print " ".img_warning(); + print ''.$obj->rowid.'"; + print $memberstatic->getNomUrl(-1, 0, 'card', 'ref', '', -1, 0, 1); + print ""; + print $obj->civility; + print "'; + print $memberstatic->getNomUrl(0, 0, 'card', 'firstname'); + //print $obj->firstname; + print "'; + print $memberstatic->getNomUrl(0, 0, 'card', 'lastname'); + //print $obj->lastname; + print "'; + if ($obj->gender) { + print $langs->trans("Gender".$obj->gender); + } + print ''; + print $companynametoshow; + print "'.$obj->login."'; + print $memberstatic->getmorphylib('', 2); + print "'; + print $membertypestatic->getNomUrl(1, 32); + print ''; + print $obj->address; + print ''; + print $obj->zip; + print ''; + print $obj->town; + print '".$obj->state_name."'; + print dol_escape_htmltag($tmparray['label']); + print ''; + print $obj->phone; + print ''; + print $obj->phone_perso; + print ''; + print $obj->phone_mobile; + print ''; + print dol_print_email($obj->email, 0, 0, 1, 64, 1, 1); + print "'; + if ($datefin) { + print dol_print_date($datefin, 'day'); + if ($memberstatic->hasDelay()) { + $textlate = ' ('.$langs->trans("DateReference").' > '.$langs->trans("DateToday").' '.(ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24) >= 0 ? '+' : '').ceil($conf->adherent->subscription->warning_delay / 60 / 60 / 24).' '.$langs->trans("days").')'; + print " ".img_warning($langs->trans("SubscriptionLate").$textlate); } } else { - print ' '; + if (!empty($obj->subscription)) { + print ''.$langs->trans("SubscriptionNotReceived").''; + if ($obj->statut > 0) { + print " ".img_warning(); + } + } else { + print ' '; + } + } + print ''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - print dol_print_date($db->jdate($obj->birth), 'day', 'tzuser'); - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - print $memberstatic->LibStatut($obj->statut, $obj->subscription, $datefin, 5); - print ''; - print dol_escape_htmltag($obj->import_key); - 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->rowid, $arrayofselected)) { - $selected = 1; + // Birth + if (!empty($arrayfields['d.birth']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->birth), 'day', 'tzuser'); + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + print $memberstatic->LibStatut($obj->statut, $obj->subscription, $datefin, 5); + print ''; + print dol_escape_htmltag($obj->import_key); + 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
'.$subscription->getNomUrl(1).'
'; + print '
'; } - } - // Type - if (!empty($arrayfields['d.fk_type']['checked'])) { - print '
'; - if ($typeid > 0) { - print $adht->getNomUrl(1); - } - print ''.$adherent->getNomUrl(-1, 0, 'card', 'lastname').''.$adherent->firstname.''.$adherent->login.''; - print $obj->note; - print ''; + + //fetch informations needs on this mode + $subscription->fk_adherent = $adherent->getNomUrl(1); + $subscription->fk_type = $adht->getNomUrl(1); + $subscription->amount = $obj->subscription; if ($obj->fk_account > 0) { $accountstatic->id = $obj->fk_account; $accountstatic->fetch($obj->fk_account); - //$accountstatic->label=$obj->label; - print $accountstatic->getNomUrl(1); + $subscription->fk_bank = $accountstatic->getNomUrl(1); } - print "
'.dol_print_date($db->jdate($obj->dateadh), 'day')."
'.$subscription->getNomUrl(1).''.dol_print_date($db->jdate($obj->datef), 'day')."'; + if ($typeid > 0) { + print $adht->getNomUrl(1); + } + print ''.price($obj->subscription).''.$adherent->getNomUrl(-1, 0, 'card', 'lastname').''.$adherent->firstname.''.$adherent->login.''; + print $obj->note; + print ''; + if ($obj->fk_account > 0) { + $accountstatic->id = $obj->fk_account; + $accountstatic->fetch($obj->fk_account); + //$accountstatic->label=$obj->label; + print $accountstatic->getNomUrl(1); + } + print "'.dol_print_date($db->jdate($obj->dateadh), 'day')."'.dol_print_date($db->jdate($obj->datef), 'day')."'.price($obj->subscription).''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + 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)) { + $selected = 1; + } + print ''; } - } - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - // Date creation - if (!empty($arrayfields['c.datec']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - 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)) { - $selected = 1; - } - print ''; - } - print '
'; print '
'; } - + //fetch informations needs on this mode $subscription->fk_adherent = $adherent->getNomUrl(1); $subscription->fk_type = $adht->getNomUrl(1); @@ -538,9 +538,7 @@ while ($i < min($num, $limit)) { print '
'; print '
'; - print $membertype->getNomUrl(1); - //'.img_object($langs->trans("ShowType"),'group').' '.$objp->rowid.' - print ''.dol_escape_htmltag($objp->label).''; - if ($objp->morphy == 'phy') { - print $langs->trans("Physical"); - } elseif ($objp->morphy == 'mor') { - print $langs->trans("Moral"); + if ($mode == 'kanban') { + if ($i == 0) { + print '
'; + print '
'; + } + //output kanban + $membertype->label = $objp->label; + $membertype->getKanbanView(''); + if ($i == ($imaxinloop - 1)) { + print '
'; + print '
'; + print $membertype->getNomUrl(1); + //'.img_object($langs->trans("ShowType"),'group').' '.$objp->rowid.' + print ''.dol_escape_htmltag($objp->label).''; + if ($objp->morphy == 'phy') { + print $langs->trans("Physical"); + } elseif ($objp->morphy == 'mor') { + print $langs->trans("Moral"); + } else { + print $langs->trans("MorAndPhy"); + } + print ''.yn($objp->subscription).''.(is_null($objp->amount) || $objp->amount === '' ? '' : price($objp->amount)).''.yn($objp->caneditamount).''.yn($objp->vote).''.$membertype->getLibStatut(5).'rowid.'">'.img_edit().' 
'.yn($objp->subscription).''.(is_null($objp->amount) || $objp->amount === '' ? '' : price($objp->amount)).''.yn($objp->caneditamount).''.yn($objp->vote).''.$membertype->getLibStatut(5).'rowid.'">'.img_edit().' 
'; - print '
'; - } - $product_static->price = $obj->price; - // Output Kanban - print $product_static->getKanbanView(''); - if ($i == ($imaxinloop - 1)) { - 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->rowid, $arrayofselected)) { - $selected = 1; - } - print ''; - } - print ''; - print $product_static->id; - print "'; - print $product_static->getNomUrl(1); - print "'; - print $product_static->getNomUrl(1); - print "' . $product_thumbnail_html . ''.$obj->label.''; - $s = ''; - if ($obj->fk_product_type == 0) { - $s .= img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"'); - } else { - $s .= img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"'); - } - print $s; - print ''.$obj->barcode.''; - - if (preg_match('/([^a-z]+)[a-z]$/i', $obj->duration)) { - $duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); - $duration_unit = substr($obj->duration, -1); - - if ((float) $duration_value > 1) { - $dur = array("i"=>$langs->trans("Minutes"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years")); - } elseif ((float) $duration_value > 0) { - $dur = array("i"=>$langs->trans("Minute"), "h"=>$langs->trans("Hour"), "d"=>$langs->trans("Day"), "w"=>$langs->trans("Week"), "m"=>$langs->trans("Month"), "y"=>$langs->trans("Year")); - } - print $duration_value; - print ((!empty($duration_unit) && isset($dur[$duration_unit]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : ''); - } elseif (!preg_match('/^[a-z]$/i', $obj->duration)) { // If duration is a simple char (like 's' of 'm'), we do not show value - print $obj->duration; - } - - print ''; - print $product_static->getLibFinished(); - print ''; - print $obj->weight; - print ''; - if ($product_static->weight != '') { - print measuringUnitString(0, 'weight', $product_static->weight_units); - } - print ''; - print $obj->length; - print ''; - if ($product_static->length != '') { - print measuringUnitString(0, 'size', $product_static->length_units); - } - print ''; - print $obj->width; - print ''; - if ($product_static->width != '') { - print measuringUnitString(0, 'size', $product_static->width_units); - } - print ''; - print $obj->height; - print ''; - if ($product_static->height != '') { - print measuringUnitString(0, 'size', $product_static->height_units); - } - print ''; - print $obj->surface; - print ''; - if ($product_static->surface != '') { - print measuringUnitString(0, 'surface', $product_static->surface_units); - } - print ''; - print $obj->volume; - print ''; - if ($product_static->volume != '') { - print measuringUnitString(0, 'volume', $product_static->volume_units); - } - print ''; - if (!empty($obj->cu_label)) { - print $langs->trans($obj->cu_label); - } - print ''; - if ($obj->tosell && $usercancreadprice) { - if ($obj->price_base_type == 'TTC') { - print ''.price($obj->price_ttc).' '.$langs->trans("TTC").''; - } else { - print ''.price($obj->price).' '.$langs->trans("HT").''; - } - } - print ''; - if (!empty($productpricescache[$obj->rowid])) { - if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') { - print ''.price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC").''; - } else { - print ''.price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT").''; - } - } - print '
'; + print '
'; } - - // Better buy price - if (!empty($arrayfields['p.minbuyprice']['checked'])) { - print '
'; - if ($product_static->status_buy && $obj->bestpurchaseprice != '' && $usercancreadprice) { - if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) { - if ($product_fourn->product_fourn_price_id > 0) { - if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { - $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1); - print ''.$form->textwithpicto(price($product_fourn->fourn_unitprice * (1 - $product_fourn->fourn_remise_percent / 100) - $product_fourn->fourn_remise).' '.$langs->trans("HT"), $htmltext).''; - } else { - print ''.price($product_fourn->fourn_unitprice).' '.$langs->trans("HT").''; - - } - } - print ''; - if ($product_static->status_buy && $usercancreadprice) { - if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) { - $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList); - print $form->textwithpicto(count($productFournList), $htmltext); - } - } - print ''; - print vatrate($obj->tva_tx, true); - print ''; - if ($usercancreadprice) { - print ''.price($product_static->pmp, 1, $langs).""; - } - print ''; - //print $obj->cost_price; - if ($usercancreadprice) { - print ''.price($obj->cost_price).' '.$langs->trans("HT").''; - } - print ''; - if ($product_static->type != 1) { - print $obj->seuil_stock_alerte; - } - print ''; - if ($product_static->type != 1) { - print $obj->desiredstock; - } - print ''; - if ($product_static->type != 1) { - if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) { - print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; - } - if ($usercancreadprice) { - print price(price2num($product_static->stock_reel, 'MS')); - } - } - print ''; - if ($product_static->type != 1) { - if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) { - print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; - } - if ($usercancreadprice) { - print price(price2num($product_static->stock_theorique, 'MS')); - } - } - print ''; - print $product_static->getLibStatut(1, 2); - print ''.getCountry($obj->fk_country, 0, $db).''; - if (!empty($obj->fk_state)) { - print getState($obj->fk_state, 0, $db); - } - print ''.$product_static->accountancy_code_sell.''.$product_static->accountancy_code_sell_intra.''.$product_static->accountancy_code_sell_export.''.$product_static->accountancy_code_buy.''.$product_static->accountancy_code_buy_intra.''.$product_static->accountancy_code_buy_export.''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { - print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); - } else { - print $product_static->LibStatut($product_static->status, 5, 0); - } - print ''; - if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { - print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); - } else { - print $product_static->LibStatut($product_static->status_buy, 5, 1); - } - 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; @@ -2023,9 +1443,584 @@ print "
'; + print $product_static->id; + print "'; + print $product_static->getNomUrl(1); + print "'; + print $product_static->getNomUrl(1); + print "' . $product_thumbnail_html . ''.$obj->label.''; + $s = ''; + if ($obj->fk_product_type == 0) { + $s .= img_picto($langs->trans("Product"), 'product', 'class="paddingleftonly paddingrightonly colorgrey"'); + } else { + $s .= img_picto($langs->trans("Service"), 'service', 'class="paddingleftonly paddingrightonly colorgrey"'); + } + print $s; + print ''.$obj->barcode.''; + + if (preg_match('/([^a-z]+)[a-z]$/i', $obj->duration)) { + $duration_value = substr($obj->duration, 0, dol_strlen($obj->duration) - 1); + $duration_unit = substr($obj->duration, -1); + + if ((float) $duration_value > 1) { + $dur = array("i"=>$langs->trans("Minutes"), "h"=>$langs->trans("Hours"), "d"=>$langs->trans("Days"), "w"=>$langs->trans("Weeks"), "m"=>$langs->trans("Months"), "y"=>$langs->trans("Years")); + } elseif ((float) $duration_value > 0) { + $dur = array("i"=>$langs->trans("Minute"), "h"=>$langs->trans("Hour"), "d"=>$langs->trans("Day"), "w"=>$langs->trans("Week"), "m"=>$langs->trans("Month"), "y"=>$langs->trans("Year")); + } + print $duration_value; + print ((!empty($duration_unit) && isset($dur[$duration_unit]) && $duration_value != '') ? ' '.$langs->trans($dur[$duration_unit]) : ''); + } elseif (!preg_match('/^[a-z]$/i', $obj->duration)) { // If duration is a simple char (like 's' of 'm'), we do not show value + print $obj->duration; + } + + print ''; + print $product_static->getLibFinished(); + print ''; + print $obj->weight; + print ''; + if ($product_static->weight != '') { + print measuringUnitString(0, 'weight', $product_static->weight_units); + } + print ''; + print $obj->length; + print ''; + if ($product_static->length != '') { + print measuringUnitString(0, 'size', $product_static->length_units); + } + print ''; + print $obj->width; + print ''; + if ($product_static->width != '') { + print measuringUnitString(0, 'size', $product_static->width_units); + } + print ''; + print $obj->height; + print ''; + if ($product_static->height != '') { + print measuringUnitString(0, 'size', $product_static->height_units); + } + print ''; + print $obj->surface; + print ''; + if ($product_static->surface != '') { + print measuringUnitString(0, 'surface', $product_static->surface_units); + } + print ''; + print $obj->volume; + print ''; + if ($product_static->volume != '') { + print measuringUnitString(0, 'volume', $product_static->volume_units); + } + print ''; + if (!empty($obj->cu_label)) { + print $langs->trans($obj->cu_label); + } + print ''; + if ($obj->tosell && $usercancreadprice) { + if ($obj->price_base_type == 'TTC') { + print ''.price($obj->price_ttc).' '.$langs->trans("TTC").''; + } else { + print ''.price($obj->price).' '.$langs->trans("HT").''; + } + } + print ''; + if (!empty($productpricescache[$obj->rowid])) { + if ($productpricescache[$obj->rowid][$key]['price_base_type'] == 'TTC') { + print ''.price($productpricescache[$obj->rowid][$key]['price_ttc']).' '.$langs->trans("TTC").''; + } else { + print ''.price($productpricescache[$obj->rowid][$key]['price']).' '.$langs->trans("HT").''; + } + } + print ''; + if ($product_static->status_buy && $obj->bestpurchaseprice != '' && $usercancreadprice) { + if ($product_fourn->find_min_price_product_fournisseur($obj->rowid) > 0) { + if ($product_fourn->product_fourn_price_id > 0) { + if ((isModEnabled("fournisseur") && !empty($user->rights->fournisseur->lire) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || (isModEnabled("supplier_order") && !empty($user->rights->supplier_order->lire)) || (isModEnabled("supplier_invoice") && !empty($user->rights->supplier_invoice->lire))) { + $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1); + print ''.$form->textwithpicto(price($product_fourn->fourn_unitprice * (1 - $product_fourn->fourn_remise_percent / 100) - $product_fourn->fourn_remise).' '.$langs->trans("HT"), $htmltext).''; + } else { + print ''.price($product_fourn->fourn_unitprice).' '.$langs->trans("HT").''; + } + } + print ''; + if ($product_static->status_buy && $usercancreadprice) { + if (count($productFournList = $product_fourn->list_product_fournisseur_price($obj->rowid)) > 0) { + $htmltext = $product_fourn->display_price_product_fournisseur(1, 1, 0, 1, $productFournList); + print $form->textwithpicto(count($productFournList), $htmltext); + } + } + print ''; + print vatrate($obj->tva_tx, true); + print ''; + if ($usercancreadprice) { + print ''.price($product_static->pmp, 1, $langs).""; + } + print ''; + //print $obj->cost_price; + if ($usercancreadprice) { + print ''.price($obj->cost_price).' '.$langs->trans("HT").''; + } + print ''; + if ($product_static->type != 1) { + print $obj->seuil_stock_alerte; + } + print ''; + if ($product_static->type != 1) { + print $obj->desiredstock; + } + print ''; + if ($product_static->type != 1) { + if ($obj->seuil_stock_alerte != '' && $product_static->stock_reel < (float) $obj->seuil_stock_alerte) { + print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; + } + if ($usercancreadprice) { + print price(price2num($product_static->stock_reel, 'MS')); + } + } + print ''; + if ($product_static->type != 1) { + if ($obj->seuil_stock_alerte != '' && $product_static->stock_theorique < (float) $obj->seuil_stock_alerte) { + print img_warning($langs->trans("StockLowerThanLimit", $obj->seuil_stock_alerte)).' '; + } + if ($usercancreadprice) { + print price(price2num($product_static->stock_theorique, 'MS')); + } + } + print ''; + print $product_static->getLibStatut(1, 2); + print ''.getCountry($obj->fk_country, 0, $db).''; + if (!empty($obj->fk_state)) { + print getState($obj->fk_state, 0, $db); + } + print ''.$product_static->accountancy_code_sell.''.$product_static->accountancy_code_sell_intra.''.$product_static->accountancy_code_sell_export.''.$product_static->accountancy_code_buy.''.$product_static->accountancy_code_buy_intra.''.$product_static->accountancy_code_buy_export.''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { + print ajax_object_onoff($product_static, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell'); + } else { + print $product_static->LibStatut($product_static->status, 5, 0); + } + print ''; + if (!empty($conf->use_javascript_ajax) && $user->hasRight("produit", "creer") && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) { + print ajax_object_onoff($product_static, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy'); + } else { + print $product_static->LibStatut($product_static->status_buy, 5, 1); + } + 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
'; print $membertype->getNomUrl(1); From 2a68836375fd0cdb9f1b03068fcfdfac0f61711b Mon Sep 17 00:00:00 2001 From: IC-Florian <71641704+IC-Florian@users.noreply.github.com> Date: Thu, 22 Dec 2022 14:52:03 +0100 Subject: [PATCH 105/816] New require for product in generateOutputField --- htdocs/core/class/html.formsetup.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 1cfddb588fd..4f88c597178 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -1103,6 +1103,9 @@ class FormSetupItem $out.= $this->langs->trans("NorProspectNorCustomer"); } } elseif ($this->type == 'product') { + if (!class_exists("Product")){ + require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + } $product = new Product($this->db); $resprod = $product->fetch($this->fieldValue); if ($resprod > 0) { From 56d05c09b2fd02450831083af0ec5ca560478378 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 22 Dec 2022 13:52:39 +0000 Subject: [PATCH 106/816] Fixing style errors. --- htdocs/core/class/html.formsetup.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 4f88c597178..611455f003f 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -1103,9 +1103,9 @@ class FormSetupItem $out.= $this->langs->trans("NorProspectNorCustomer"); } } elseif ($this->type == 'product') { - if (!class_exists("Product")){ - require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; - } + if (!class_exists("Product")) { + require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + } $product = new Product($this->db); $resprod = $product->fetch($this->fieldValue); if ($resprod > 0) { From 1b03c423b94427c6eef855b9678b797c984c5f37 Mon Sep 17 00:00:00 2001 From: ksar <35605507+ksar-ksar@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:13:11 +0100 Subject: [PATCH 107/816] FIX #23281 --- htdocs/admin/perms.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/perms.php b/htdocs/admin/perms.php index d2f0d79e4f3..60f8c9d064a 100644 --- a/htdocs/admin/perms.php +++ b/htdocs/admin/perms.php @@ -226,7 +226,7 @@ if ($result) { // Tick if ($obj->bydefault == 1) { print ''; - print ''; + print ''; //print img_edit_remove(); print img_picto('', 'switch_on'); print ''; From 298c97d5a65a0c1512d1b5ab44cbea3320db2c90 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Fri, 23 Dec 2022 12:43:26 +0100 Subject: [PATCH 108/816] NEW copyrights --- htdocs/accountancy/bookkeeping/list.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 781b20edc2e..bdd0fefe191 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -1,7 +1,8 @@ * Copyright (C) 2013-2016 Florian Henry - * Copyright (C) 2013-2022 Open-DSI + * Copyright (C) 2013-2022 Alexandre Spangaro + * Copyright (C) 2022 Lionel Vessiller * Copyright (C) 2016-2017 Laurent Destailleur * Copyright (C) 2018-2021 Frédéric France * Copyright (C) 2022 Progiseize From 92d9d31b8ce8dc956b30658d459a295366c4f70e Mon Sep 17 00:00:00 2001 From: Randall Mora <50120822+randallmoraes@users.noreply.github.com> Date: Fri, 23 Dec 2022 13:18:04 -0600 Subject: [PATCH 109/816] Update functions.lib.php Agrega el tipo de moneda CRC (colones Costa Rica) para que se muestre al incio como simbolo de moneda. Adds the CRC currency (Costa Rican colones) so that it is displayed at the beginning as a currency symbol. --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 00defaf909c..cf5b77ff63e 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5762,7 +5762,7 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $ $currency_code = $conf->currency; } - $listofcurrenciesbefore = array('AUD', 'CAD', 'CNY', 'COP', 'CLP', 'GBP', 'HKD', 'MXN', 'PEN', 'USD'); + $listofcurrenciesbefore = array('AUD', 'CAD', 'CNY', 'COP', 'CLP', 'GBP', 'HKD', 'MXN', 'PEN', 'USD', 'CRC); $listoflanguagesbefore = array('nl_NL'); if (in_array($currency_code, $listofcurrenciesbefore) || in_array($outlangs->defaultlang, $listoflanguagesbefore)) { $cursymbolbefore .= $outlangs->getCurrencySymbol($currency_code); From 07a1f8e65188d5b352aa233cfca13128de8c1bf8 Mon Sep 17 00:00:00 2001 From: Amael <41053833+Amael-PE@users.noreply.github.com> Date: Mon, 26 Dec 2022 00:05:34 +0100 Subject: [PATCH 110/816] FIX #23334 Implement a price equivalent in command Implement a price equivalent when dealing with minimum prices and foreign currencies. Added in command/card.php for add and update. --- htdocs/commande/card.php | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index d394df997ff..051f047241a 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -629,6 +629,15 @@ if (empty($reshook)) { $idprod = GETPOST('idprod', 'int'); $tva_tx = ''; } + + $price_equivalent = $price_ht; + $currency_tx = $object->multicurrency_tx; + + // Check if we have a foreing currency + // If so, we update the pu_equiv as the equivalent price in base currency + if ($price_ht == '' && $price_ht_devise != '' && $currency_tx != '') { + $price_equivalent = $price_ht_devise * $currency_tx; + } $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS'); @@ -916,7 +925,7 @@ if (empty($reshook)) { $info_bits |= 0x01; } - if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min)))) { + if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && (!empty($price_min) && (price2num($price_equivalent) * (1 - price2num($remise_percent) / 100) < price2num($price_min)))) { $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)); setEventMessages($mesg, null, 'errors'); } else { @@ -990,6 +999,15 @@ if (empty($reshook)) { $pu_ht = price2num(GETPOST('price_ht'), '', 2); $vat_rate = (GETPOST('tva_tx') ?GETPOST('tva_tx') : 0); $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2); + + $pu_equivalent = $pu_ht; + $currency_tx = $object->multicurrency_tx; + + // Check if we have a foreing currency + // If so, we update the pu_equiv as the equivalent price in base currency + if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { + $pu_equivalent = $pu_ht_devise * $currency_tx; + } // Define info_bits $info_bits = 0; @@ -1039,7 +1057,7 @@ if (empty($reshook)) { $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : ''); - if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && ($price_min && (price2num($pu_ht) * (1 - $remise_percent / 100) < price2num($price_min)))) { + if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && ($price_min && (price2num($pu_equivalent) * (1 - $remise_percent / 100) < price2num($price_min)))) { setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors'); $error++; } From 58d3cdb13cc55fe5d221270d4c8babe107639fa3 Mon Sep 17 00:00:00 2001 From: Amael <41053833+Amael-PE@users.noreply.github.com> Date: Mon, 26 Dec 2022 00:31:38 +0100 Subject: [PATCH 111/816] FIX #23334 Implement a price equivalent in propal Implement a price equivalent when dealing with minimum prices and foreign currencies. Added in comm/propal/card.php as it was done in command/card.php for add and update. --- htdocs/comm/propal/card.php | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index da4c756705f..9461927bec5 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1116,7 +1116,17 @@ if (empty($reshook)) { $date_start = dol_mktime(GETPOST('date_start'.$predef.'hour'), GETPOST('date_start'.$predef.'min'), GETPOST('date_start'.$predef.'sec'), GETPOST('date_start'.$predef.'month'), GETPOST('date_start'.$predef.'day'), GETPOST('date_start'.$predef.'year')); $date_end = dol_mktime(GETPOST('date_end'.$predef.'hour'), GETPOST('date_end'.$predef.'min'), GETPOST('date_end'.$predef.'sec'), GETPOST('date_end'.$predef.'month'), GETPOST('date_end'.$predef.'day'), GETPOST('date_end'.$predef.'year')); + + // Prepare a price equivlanet for mimum price check + $pu_equivalent = $pu_ht; + $currency_tx = $object->multicurrency_tx; + // Check if we have a foreing currency + // If so, we update the pu_equiv as the equivalent price in base currency + if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { + $pu_equivalent = $pu_ht_devise * $currency_tx; + } + // Local Taxes $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $tva_npr); $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $tva_npr); @@ -1125,8 +1135,9 @@ if (empty($reshook)) { if ($tva_npr) { $info_bits |= 0x01; } - - if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min)))) { + + // Check minimum price + if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && (!empty($price_min) && (price2num($pu_equivalent) * (1 - price2num($remise_percent) / 100) < price2num($price_min)))) { $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)); setEventMessages($mesg, null, 'errors'); } else { @@ -1218,6 +1229,16 @@ if (empty($reshook)) { $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear')); $remise_percent = price2num(GETPOST('remise_percent'), '', 2); + + // Prepare pu_equivament for checking the minimun price + $pu_equivalent = $pu_ht; + $currency_tx = $object->multicurrency_tx; + + // Check if we have a foreing currency + // If so, we update the pu_equiv as the equivalent price in base currency + if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { + $pu_equivalent = $pu_ht_devise * $currency_tx; + } // Extrafields $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line); @@ -1250,7 +1271,7 @@ if (empty($reshook)) { } $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : ''); - if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && ($price_min && (price2num($pu_ht) * (1 - $remise_percent / 100) < price2num($price_min)))) { + if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && ($price_min && (price2num($pu_equivalent) * (1 - $remise_percent / 100) < price2num($price_min)))) { setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors'); $error++; } From 50e2545bea8bbb7d3632fe54d81c655cb51831b7 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 25 Dec 2022 23:41:03 +0000 Subject: [PATCH 112/816] Fixing style errors. --- htdocs/comm/propal/card.php | 12 ++++++------ htdocs/commande/card.php | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 9461927bec5..4881209e386 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1116,7 +1116,7 @@ if (empty($reshook)) { $date_start = dol_mktime(GETPOST('date_start'.$predef.'hour'), GETPOST('date_start'.$predef.'min'), GETPOST('date_start'.$predef.'sec'), GETPOST('date_start'.$predef.'month'), GETPOST('date_start'.$predef.'day'), GETPOST('date_start'.$predef.'year')); $date_end = dol_mktime(GETPOST('date_end'.$predef.'hour'), GETPOST('date_end'.$predef.'min'), GETPOST('date_end'.$predef.'sec'), GETPOST('date_end'.$predef.'month'), GETPOST('date_end'.$predef.'day'), GETPOST('date_end'.$predef.'year')); - + // Prepare a price equivlanet for mimum price check $pu_equivalent = $pu_ht; $currency_tx = $object->multicurrency_tx; @@ -1126,7 +1126,7 @@ if (empty($reshook)) { if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { $pu_equivalent = $pu_ht_devise * $currency_tx; } - + // Local Taxes $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $tva_npr); $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $tva_npr); @@ -1135,7 +1135,7 @@ if (empty($reshook)) { if ($tva_npr) { $info_bits |= 0x01; } - + // Check minimum price if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && (!empty($price_min) && (price2num($pu_equivalent) * (1 - price2num($remise_percent) / 100) < price2num($price_min)))) { $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)); @@ -1229,7 +1229,7 @@ if (empty($reshook)) { $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear')); $remise_percent = price2num(GETPOST('remise_percent'), '', 2); - + // Prepare pu_equivament for checking the minimun price $pu_equivalent = $pu_ht; $currency_tx = $object->multicurrency_tx; @@ -1237,8 +1237,8 @@ if (empty($reshook)) { // Check if we have a foreing currency // If so, we update the pu_equiv as the equivalent price in base currency if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { - $pu_equivalent = $pu_ht_devise * $currency_tx; - } + $pu_equivalent = $pu_ht_devise * $currency_tx; + } // Extrafields $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line); diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 051f047241a..e48b3183006 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -629,14 +629,14 @@ if (empty($reshook)) { $idprod = GETPOST('idprod', 'int'); $tva_tx = ''; } - + $price_equivalent = $price_ht; $currency_tx = $object->multicurrency_tx; // Check if we have a foreing currency // If so, we update the pu_equiv as the equivalent price in base currency if ($price_ht == '' && $price_ht_devise != '' && $currency_tx != '') { - $price_equivalent = $price_ht_devise * $currency_tx; + $price_equivalent = $price_ht_devise * $currency_tx; } $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS'); @@ -999,14 +999,14 @@ if (empty($reshook)) { $pu_ht = price2num(GETPOST('price_ht'), '', 2); $vat_rate = (GETPOST('tva_tx') ?GETPOST('tva_tx') : 0); $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2); - + $pu_equivalent = $pu_ht; $currency_tx = $object->multicurrency_tx; // Check if we have a foreing currency // If so, we update the pu_equiv as the equivalent price in base currency if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { - $pu_equivalent = $pu_ht_devise * $currency_tx; + $pu_equivalent = $pu_ht_devise * $currency_tx; } // Define info_bits From ffae98085bcaa3b54e9d3439bff7e4ab71506fab Mon Sep 17 00:00:00 2001 From: daraelmin Date: Mon, 26 Dec 2022 22:36:05 +0100 Subject: [PATCH 113/816] New box box_members_by_tags.php --- htdocs/adherents/class/adherent.class.php | 2 +- .../adherents/class/adherentstats.class.php | 78 +++++ htdocs/core/boxes/box_members_by_tags.php | 279 ++++++++++++++++++ htdocs/core/boxes/modules_boxes.php | 1 + htdocs/langs/en_US/boxes.lang | 1 + 5 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 htdocs/core/boxes/box_members_by_tags.php diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 6aaac503060..15df4f7225d 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -3203,4 +3203,4 @@ class Adherent extends CommonObject return $nbko; } -} +} \ No newline at end of file diff --git a/htdocs/adherents/class/adherentstats.class.php b/htdocs/adherents/class/adherentstats.class.php index 9aa2fe2e8ad..ed86cae8704 100644 --- a/htdocs/adherents/class/adherentstats.class.php +++ b/htdocs/adherents/class/adherentstats.class.php @@ -181,4 +181,82 @@ class AdherentStats extends Stats return $this->_getAllByYear($sql); } + + + + /** + * Return count of member by status group by adh type, total and average + * + * @param int $numberYears Years to scan + * @return array Array with total of draft, pending, uptodate, expired, resiliated for each member type + */ + public function countMembersByTagAndStatus($tag_id, $numberYears = 2) + { + global $user; + + $now = dol_now(); + $endYear = date('Y'); + $startYear = $endYear - $numberYears; + + $sql = "SELECT c.rowid as fk_categorie, c.label as label"; + $sql .= ", COUNT(".$this->db->ifsql("d.statut = ".Adherent::STATUS_DRAFT, "'members_draft'", 'NULL').") as members_draft"; + $sql .= ", COUNT(".$this->db->ifsql("d.statut = ".Adherent::STATUS_VALIDATED." AND (d.datefin IS NULL AND t.subscription = '1')", "'members_pending'", 'NULL').") as members_pending"; + $sql .= ", COUNT(".$this->db->ifsql("d.statut = ".Adherent::STATUS_VALIDATED." AND (d.datefin >= '".$this->db->idate($now)."' OR t.subscription = 0)", "'members_uptodate'", 'NULL').") as members_uptodate"; + $sql .= ", COUNT(".$this->db->ifsql("d.statut = ".Adherent::STATUS_VALIDATED." AND (d.datefin < '".$this->db->idate($now)."' AND t.subscription = 1)", "'members_expired'", 'NULL').") as members_expired"; + $sql .= ", COUNT(".$this->db->ifsql("d.statut = ".Adherent::STATUS_EXCLUDED, "'members_excluded'", 'NULL').") as members_excluded"; + $sql .= ", COUNT(".$this->db->ifsql("d.statut = ".Adherent::STATUS_RESILIATED, "'members_resiliated'", 'NULL').") as members_resiliated"; + $sql .= " FROM ".MAIN_DB_PREFIX."categorie as c"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_member as ct ON c.rowid = ct.fk_categorie"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."adherent as d ON d.rowid = ct.fk_member"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."adherent_type as t ON t.rowid = d.fk_adherent_type"; + $sql .= " WHERE c.entity IN (".getEntity('member_type').")"; + $sql .= " AND d.entity IN (" . getEntity('adherent') . ")"; + $sql .= " AND t.entity IN (" . getEntity('adherent') . ")"; + $sql .= " AND d.datefin > '".$this->db->idate(dol_get_first_day($startYear))."'"; + $sql .= " AND c.fk_parent = 0"; + $sql .= " GROUP BY c.rowid"; + + dol_syslog("box_members_by_type::select nb of members per type", LOG_DEBUG); + $result = $this->db->query($sql); + + if ($result) { + $num = $this->db->num_rows($result); + $i = 0; + $MembersCountArray = []; + $totalstatus = array( + 'label' => 'Total', + 'members_draft' => 0, + 'members_pending' => 0, + 'members_uptodate' => 0, + 'members_expired' => 0, + 'members_excluded' => 0, + 'members_resiliated' => 0 + ); + while ($i < $num) { + $objp = $this->db->fetch_object($result); + $MembersCountArray[$objp->fk_categorie] = array( + 'label' => $objp->label, + 'members_draft' => (int) $objp->members_draft, + 'members_pending' => (int) $objp->members_pending, + 'members_uptodate' => (int) $objp->members_uptodate, + 'members_expired' => (int) $objp->members_expired, + 'members_excluded' => (int) $objp->members_excluded, + 'members_resiliated' => (int) $objp->members_resiliated + ); + $totalrow = 0; + foreach ($MembersCountArray[$objp->fk_categorie] as $key=>$nb) { + if ($key!='label') { + $totalrow += $nb; + $totalstatus[$key] += $nb; + } + } + $MembersCountArray[$objp->fk_categorie]['total_adhtype'] = $totalrow; + $i++; + } + $this->db->free($result); + $MembersCountArray['total'] = $totalstatus; + $MembersCountArray['total']['all'] = array_sum($totalstatus); + } + return $MembersCountArray; + } } diff --git a/htdocs/core/boxes/box_members_by_tags.php b/htdocs/core/boxes/box_members_by_tags.php new file mode 100644 index 00000000000..cd7a499c867 --- /dev/null +++ b/htdocs/core/boxes/box_members_by_tags.php @@ -0,0 +1,279 @@ + + * Copyright (C) 2004-2017 Laurent Destailleur + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2015-2020 Frederic France + * Copyright (C) 2021-2022 Waël Almoman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/boxes/box_members_by_tags.php + * \ingroup adherent + * \brief Module to show box of members + */ + +include_once DOL_DOCUMENT_ROOT . '/core/boxes/modules_boxes.php'; + + +/** + * Class to manage the box to show last modofied members + */ +class box_members_by_tags extends ModeleBoxes +{ + public $boxcode = "box_members_by_tags"; + public $boximg = "object_user"; + public $boxlabel = "BoxTitleMembersByTags"; + public $depends = array("adherent", "categorie"); + + /** + * @var DoliDB Database handler. + */ + public $db; + + public $param; + public $enabled = 1; + + public $info_box_head = array(); + public $info_box_contents = array(); + + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param string $param More parameters + */ + public function __construct($db, $param = '') + { + global $conf, $user; + + $this->db = $db; + + // disable module for such cases + $listofmodulesforexternal = explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL); + if (!in_array('adherent', $listofmodulesforexternal) && !empty($user->socid)) { + $this->enabled = 0; // disabled for external users + } + + $this->hidden = !(isModEnabled('adherent') && $user->rights->adherent->lire); + } + + /** + * Load data into info_box_contents array to show array later. + * + * @param int $max Maximum number of records to load + * @return void + */ + public function loadBox($max = 5) + { + global $user, $langs, $conf; + $langs->load("boxes"); + + $this->max = $max; + + include_once DOL_DOCUMENT_ROOT . '/adherents/class/adherent.class.php'; + $staticmember = new Adherent($this->db); + + $year = date('Y'); + $numberyears = empty(getDolGlobalInt("MAIN_NB_OF_YEAR_IN_WIDGET_GRAPH")) ? 2 : getDolGlobalInt("MAIN_NB_OF_YEAR_IN_WIDGET_GRAPH"); + + $this->info_box_head = array('text' => $langs->trans("BoxTitleMembersByTags").' ('.$year-$numberyears.' - '.$year.')'); + + if ($user->rights->adherent->lire) { + require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherentstats.class.php'; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + $stats = new AdherentStats($this->db, $user->socid, $user->id); + + // Show array + $sumMembers= $stats->countMembersByTagAndStatus($tag_id, $numberyears); + echo "
";print_r($sumMembers);echo "
"; + if ($sumMembers) { + $line = 0; + $this->info_box_contents[$line][] = array( + 'td' => 'class=""', + 'text' => '', + ); + // Members Status To Valid + $labelstatus = $staticmember->LibStatut($staticmember::STATUS_DRAFT, 0, 0, 1); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right tdoverflowmax100" width="10%" title="'.dol_escape_htmltag($labelstatus).'"', + 'text' => $labelstatus + ); + // Waiting for subscription + $labelstatus = $staticmember->LibStatut($staticmember::STATUS_VALIDATED, 1, 0, 1); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right tdoverflowmax100" width="10%" title="'.dol_escape_htmltag($labelstatus).'"', + 'text' => $labelstatus, + ); + // Up to date + $labelstatus = $staticmember->LibStatut($staticmember::STATUS_VALIDATED, 1, dol_now() + 86400, 1); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right tdoverflowmax100" width="10%" title="'.dol_escape_htmltag($labelstatus).'"', + 'text' => $labelstatus, + ); + // Expired + $labelstatus = $staticmember->LibStatut($staticmember::STATUS_VALIDATED, 1, dol_now() - 86400, 1); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right tdoverflowmax100" width="10%" title="'.dol_escape_htmltag($labelstatus).'"', + 'text' => $labelstatus + ); + // Excluded + $labelstatus = $staticmember->LibStatut($staticmember::STATUS_EXCLUDED, 0, 0, 1); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right tdoverflowmax100" width="10%" title="'.dol_escape_htmltag($labelstatus).'"', + 'text' => $labelstatus + ); + // Resiliated + $labelstatus = $staticmember->LibStatut($staticmember::STATUS_RESILIATED, 0, 0, 1); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right tdoverflowmax100" width="10%" title="'.dol_escape_htmltag($labelstatus).'"', + 'text' => $labelstatus + ); + // Total row + $labelstatus = $staticmember->LibStatut($staticmember::STATUS_RESILIATED, 0, 0, 1); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right tdoverflowmax100" width="10%" title="'.dol_escape_htmltag($langs->trans("Total")).'"', + 'text' => $langs->trans("Total") + ); + $line++; + foreach ($sumMembers as $key => $data) { + $adhtype = new AdherentType($this->db); + $adhtype->id = $key; + + if ($key=='total') { + break; + } + $adhtype->label = $data['label']; + $AdherentType[$key] = $adhtype; + + $this->info_box_contents[$line][] = array( + 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', + 'text' => $adhtype->getNomUrl(1, dol_size(32)), + 'asis' => 1, + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => (isset($data['members_draft']) && $data['members_draft'] > 0 ? $data['members_draft'] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_DRAFT, 1, 0, 3), + 'asis' => 1, + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => (isset($data['members_pending']) && $data['members_pending'] > 0 ? $data['members_pending'] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, $now, 3), + 'asis' => 1, + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => (isset($data['members_uptodate']) && $data['members_uptodate'] > 0 ? $data['members_uptodate'] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_VALIDATED, 0, 0, 3), + 'asis' => 1, + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => (isset($data['members_expired']) && $data['members_expired'] > 0 ? $data['members_expired'] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, 1, 3), + 'asis' => 1, + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => (isset($data['members_excluded']) && $data['members_excluded'] > 0 ? $data['members_excluded'] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_EXCLUDED, 1, $now, 3), + 'asis' => 1, + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => (isset($data['members_resiliated']) && $data['members_resiliated'] > 0 ? $data['members_resiliated'] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_RESILIATED, 1, 0, 3), + 'asis' => 1, + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => (isset($data['total_adhtype']) && $data['total_adhtype'] > 0 ? $data['total_adhtype'] : ''), + 'asis' => 1, + ); + $line++; + } + + if (count($sumMembers) == 0) { + $this->info_box_contents[$line][0] = array( + 'td' => 'class="center" colspan="6"', + 'text' => $langs->trans("NoRecordedMembersByType") + ); + } else { + $this->info_box_contents[$line][] = array( + 'tr' => 'class="liste_total"', + 'td' => 'class="liste_total"', + 'text' => $langs->trans("Total") + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="liste_total right"', + 'text' => $sumMembers['total']['members_draft'].' '.$staticmember->LibStatut(Adherent::STATUS_DRAFT, 1, 0, 3), + 'asis' => 1 + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="liste_total right"', + 'text' => $sumMembers['total']['members_pending'].' '.$staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, $now, 3), + 'asis' => 1 + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="liste_total right"', + 'text' => $sumMembers['total']['members_uptodate'].' '.$staticmember->LibStatut(Adherent::STATUS_VALIDATED, 0, 0, 3), + 'asis' => 1 + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="liste_total right"', + 'text' => $sumMembers['total']['members_expired'].' '.$staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, 1, 3), + 'asis' => 1 + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="liste_total right"', + 'text' => $sumMembers['total']['members_excluded'].' '.$staticmember->LibStatut(Adherent::STATUS_EXCLUDED, 1, 0, 3), + 'asis' => 1 + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="liste_total right"', + 'text' => $sumMembers['total']['members_resiliated'].' '.$staticmember->LibStatut(Adherent::STATUS_RESILIATED, 1, 0, 3), + 'asis' => 1 + ); + $this->info_box_contents[$line][] = array( + 'td' => 'class="liste_total right"', + 'text' => $sumMembers['total']['all'], + 'asis' => 1 + ); + } + } else { + $this->info_box_contents[0][0] = array( + 'td' => '', + 'maxlength' => 500, + 'text' => ($this->db->error() . ' sql=' . $sql) + ); + } + } else { + $this->info_box_contents[0][0] = array( + 'td' => 'class="nohover opacitymedium left"', + 'text' => $langs->trans("ReadPermissionNotAllowed") + ); + } + } + + /** + * Method to show box + * + * @param array $head Array with properties of box title + * @param array $contents Array with properties of box lines + * @param int $nooutput No print, only return string + * @return string + */ + public function showBox($head = null, $contents = null, $nooutput = 0) + { + return parent::showBox($this->info_box_head, $this->info_box_contents, $nooutput); + } +} diff --git a/htdocs/core/boxes/modules_boxes.php b/htdocs/core/boxes/modules_boxes.php index 1a29c8e1389..54ad02c0f3b 100644 --- a/htdocs/core/boxes/modules_boxes.php +++ b/htdocs/core/boxes/modules_boxes.php @@ -464,6 +464,7 @@ class ModeleBoxes // Can't be abtract as it is instantiated to build "empty" box closedir($handle); } } + echo "
";print_r($modules);echo "
"; asort($orders); diff --git a/htdocs/langs/en_US/boxes.lang b/htdocs/langs/en_US/boxes.lang index 0ac1ecce545..9e80e36b119 100644 --- a/htdocs/langs/en_US/boxes.lang +++ b/htdocs/langs/en_US/boxes.lang @@ -24,6 +24,7 @@ BoxFicheInter=Latest interventions BoxCurrentAccounts=Open accounts balance BoxTitleMemberNextBirthdays=Birthdays of this month (members) BoxTitleMembersByType=Members by type and status +BoxTitleMembersByTags=Members by tags and status BoxTitleMembersSubscriptionsByYear=Members Subscriptions by year BoxTitleLastRssInfos=Latest %s news from %s BoxTitleLastProducts=Products/Services: last %s modified From 5b40a4a21097b2550063c228e0d020b7ffd63752 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 26 Dec 2022 21:37:33 +0000 Subject: [PATCH 114/816] Fixing style errors. --- htdocs/adherents/class/adherent.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 15df4f7225d..6aaac503060 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -3203,4 +3203,4 @@ class Adherent extends CommonObject return $nbko; } -} \ No newline at end of file +} From 5d09076a8faad01b77446ceb03d7ddcfd9f6bbe0 Mon Sep 17 00:00:00 2001 From: daraelmin Date: Mon, 26 Dec 2022 22:56:26 +0100 Subject: [PATCH 115/816] Doc --- htdocs/adherents/class/adherentstats.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/adherents/class/adherentstats.class.php b/htdocs/adherents/class/adherentstats.class.php index ed86cae8704..20d66130362 100644 --- a/htdocs/adherents/class/adherentstats.class.php +++ b/htdocs/adherents/class/adherentstats.class.php @@ -187,10 +187,10 @@ class AdherentStats extends Stats /** * Return count of member by status group by adh type, total and average * - * @param int $numberYears Years to scan - * @return array Array with total of draft, pending, uptodate, expired, resiliated for each member type + * @param int $numberYears Years to scan + * @return array Array with total of draft, pending, uptodate, expired, resiliated for each member tag */ - public function countMembersByTagAndStatus($tag_id, $numberYears = 2) + public function countMembersByTagAndStatus($numberYears = 2) { global $user; From 7a15e61849fd66edb0b1a33de6f34b2d1b5f201a Mon Sep 17 00:00:00 2001 From: daraelmin Date: Mon, 26 Dec 2022 22:59:39 +0100 Subject: [PATCH 116/816] Clean code --- htdocs/core/boxes/box_members_by_tags.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/core/boxes/box_members_by_tags.php b/htdocs/core/boxes/box_members_by_tags.php index cd7a499c867..196cec30738 100644 --- a/htdocs/core/boxes/box_members_by_tags.php +++ b/htdocs/core/boxes/box_members_by_tags.php @@ -98,8 +98,7 @@ class box_members_by_tags extends ModeleBoxes $stats = new AdherentStats($this->db, $user->socid, $user->id); // Show array - $sumMembers= $stats->countMembersByTagAndStatus($tag_id, $numberyears); - echo "
";print_r($sumMembers);echo "
"; + $sumMembers= $stats->countMembersByTagAndStatus($numberyears); if ($sumMembers) { $line = 0; $this->info_box_contents[$line][] = array( From d0ea4760d9f8921c3e2761c84689f9c9b0904e4e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 02:38:40 +0100 Subject: [PATCH 117/816] Update perms.php --- htdocs/admin/perms.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/perms.php b/htdocs/admin/perms.php index 60f8c9d064a..8b1f6249d93 100644 --- a/htdocs/admin/perms.php +++ b/htdocs/admin/perms.php @@ -226,7 +226,7 @@ if ($result) { // Tick if ($obj->bydefault == 1) { print '
'; - print ''; + print ''; //print img_edit_remove(); print img_picto('', 'switch_on'); print ''; From f3d73690c6a8139590ff7db7b752909e72379deb Mon Sep 17 00:00:00 2001 From: Randall Mora <50120822+randallmoraes@users.noreply.github.com> Date: Wed, 28 Dec 2022 08:29:55 -0600 Subject: [PATCH 118/816] Update notify.class.php Allows modification of attachments using the hook --- htdocs/core/class/notify.class.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index 2a3a2b805da..c85339f7df8 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -658,6 +658,11 @@ class Notify $reshook = $hookmanager->executeHooks('formatNotificationMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if (empty($reshook)) { + if (!empty($hookmanager->resArray['files'])) { + $filename_list = $hookmanager->resArray['files']['file']; + $mimetype_list = $hookmanager->resArray['files']['mimefile']; + $mimefilename_list = $hookmanager->resArray['files']['filename']; + } if (!empty($hookmanager->resArray['subject'])) { $subject .= $hookmanager->resArray['subject']; } @@ -901,6 +906,11 @@ class Notify $parameters = array('notifcode'=>$notifcode, 'sendto'=>$sendto, 'replyto'=>$replyto, 'file'=>$filename_list, 'mimefile'=>$mimetype_list, 'filename'=>$mimefilename_list); $reshook = $hookmanager->executeHooks('formatNotificationMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if (empty($reshook)) { + if (!empty($hookmanager->resArray['files'])) { + $filename_list = $hookmanager->resArray['files']['file']; + $mimetype_list = $hookmanager->resArray['files']['mimefile']; + $mimefilename_list = $hookmanager->resArray['files']['filename']; + } if (!empty($hookmanager->resArray['subject'])) { $subject .= $hookmanager->resArray['subject']; } From 53912df6f2b8127c61cc215798f7fc27c6fc77af Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 15:49:03 +0100 Subject: [PATCH 119/816] FIX Warning not visible --- htdocs/societe/paymentmodes.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index ae39569a36e..6869e80bd87 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -1480,20 +1480,22 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print $string; print ''.dol_escape_htmltag($rib->iban); + print ''; if (!empty($rib->iban)) { if (!checkIbanForAccount($rib)) { - print ' '.img_picto($langs->trans("IbanNotValid"), 'warning'); + print img_picto($langs->trans("IbanNotValid"), 'warning').' '; } } + print dol_escape_htmltag($rib->iban); print ''.$rib->bic; + print ''; if (!empty($rib->bic)) { if (!checkSwiftForAccount($rib)) { - print ' '.img_picto($langs->trans("SwiftNotValid"), 'warning'); + print img_picto($langs->trans("SwiftNotValid"), 'warning').' '; } } + print dol_escape_htmltag($rib->bic); print '
'; - if ($action != 'editretainedwarranty' && $user->rights->facture->creer) { + if ($action != 'editretainedwarranty' && $user->rights->facture->creer && $object->statut == Facture::STATUS_DRAFT) { print ''; } print '
'; print $langs->trans('RetainedWarranty'); print 'id.'">'.img_edit($langs->trans('setretainedwarranty'), 1).'
'; print '
'; - if ($action == 'editretainedwarranty') { + if ($action == 'editretainedwarranty' && $object->statut == Facture::STATUS_DRAFT) { print ''; print ''; print ''; @@ -4540,7 +4540,7 @@ if ($action == 'create') { print ''; - if ($action != 'editretainedwarrantypaymentterms' && $user->rights->facture->creer) { + if ($action != 'editretainedwarrantypaymentterms' && $user->rights->facture->creer && $object->statut == Facture::STATUS_DRAFT) { print ''; } @@ -4551,7 +4551,7 @@ if ($action == 'create') { $defaultDate = $object->date; } - if ($action == 'editretainedwarrantypaymentterms') { + if ($action == 'editretainedwarrantypaymentterms' && $object->statut == Facture::STATUS_DRAFT) { //date('Y-m-d',$object->date_lim_reglement) print ''; print ''; @@ -4575,7 +4575,7 @@ if ($action == 'create') { print '
'; print $langs->trans('PaymentConditionsShortRetainedWarranty'); print 'id.'">'.img_edit($langs->trans('setPaymentConditionsShortRetainedWarranty'), 1).'
'; - if ($action != 'editretainedwarrantydatelimit' && $user->rights->facture->creer) { + if ($action != 'editretainedwarrantydatelimit' && $user->rights->facture->creer && $object->statut == Facture::STATUS_DRAFT) { print ''; } @@ -4586,7 +4586,7 @@ if ($action == 'create') { $defaultDate = $object->date; } - if ($action == 'editretainedwarrantydatelimit') { + if ($action == 'editretainedwarrantydatelimit' && $object->statut == Facture::STATUS_DRAFT) { //date('Y-m-d',$object->date_lim_reglement) print ''; print ''; From 39cf086ace24ffd79ef4072dc2022caa28df7d54 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 18:20:52 +0100 Subject: [PATCH 121/816] Update modules_boxes.php --- htdocs/core/boxes/modules_boxes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/boxes/modules_boxes.php b/htdocs/core/boxes/modules_boxes.php index 54ad02c0f3b..96928adfdff 100644 --- a/htdocs/core/boxes/modules_boxes.php +++ b/htdocs/core/boxes/modules_boxes.php @@ -464,7 +464,7 @@ class ModeleBoxes // Can't be abtract as it is instantiated to build "empty" box closedir($handle); } } - echo "
";print_r($modules);echo "
"; + //echo "
";print_r($modules);echo "
"; asort($orders); From be03dcb8ceeb94f03958509e7070caa1ac1a8da5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 19:06:16 +0100 Subject: [PATCH 122/816] Fix strange condition --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index ca2418a0ab1..5e5198d6b4c 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2985,7 +2985,7 @@ class Product extends CommonObject $adeduire = 0; $sql = "SELECT sum(fd.qty) as count FROM ".MAIN_DB_PREFIX."facturedet fd "; $sql .= " JOIN ".MAIN_DB_PREFIX."facture f ON fd.fk_facture = f.rowid "; - $sql .= " JOIN ".MAIN_DB_PREFIX."element_element el ON el.fk_target = f.rowid and el.targettype = 'facture' and sourcetype = 'commande'"; + $sql .= " JOIN ".MAIN_DB_PREFIX."element_element el ON ((el.fk_target = f.rowid AND el.targettype = 'facture' AND sourcetype = 'commande') OR (el.fk_source = f.rowid AND el.targettype = 'commande' AND sourcetype = 'facture'))"; $sql .= " JOIN ".MAIN_DB_PREFIX."commande c ON el.fk_source = c.rowid "; $sql .= " WHERE c.fk_statut IN (".$this->db->sanitize($filtrestatut).") AND c.facture = 0 AND fd.fk_product = ".((int) $this->id); dol_syslog(__METHOD__.":: sql $sql", LOG_NOTICE); From 934d7b46d01c3ae93d7fe50179dfb1c0376fab7f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 19:15:07 +0100 Subject: [PATCH 123/816] Update product.class.php --- htdocs/product/class/product.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 9cb7187a0ad..d9e09ce788d 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3091,9 +3091,9 @@ class Product extends CommonObject // For every order having invoice already validated we need to decrease stock cause it's in physical stock $adeduire = 0; $sql = 'SELECT sum(fd.qty) as count FROM '.MAIN_DB_PREFIX.'facturedet fd '; - $sql .= ' JOIN '.MAIN_DB_PREFIX.'facture f ON fd.fk_facture = f.rowid '; - $sql .= ' JOIN '.MAIN_DB_PREFIX."element_element el ON ((el.fk_target = f.rowid AND el.targettype = 'facture' AND sourcetype = 'commande') OR (el.fk_source = f.rowid AND el.targettype = 'commande' AND sourcetype = 'facture'))"; - $sql .= ' JOIN '.MAIN_DB_PREFIX.'commande c ON el.fk_source = c.rowid '; + $sql .= ' JOIN '.MAIN_DB_PREFIX.'facture as f ON fd.fk_facture = f.rowid '; + $sql .= ' JOIN '.MAIN_DB_PREFIX."element_element as el ON ((el.fk_target = f.rowid AND el.targettype = 'facture' AND sourcetype = 'commande') OR (el.fk_source = f.rowid AND el.targettype = 'commande' AND sourcetype = 'facture'))"; + $sql .= ' JOIN '.MAIN_DB_PREFIX.'commande as c ON el.fk_source = c.rowid '; $sql .= ' WHERE c.fk_statut IN ('.$this->db->sanitize($filtrestatut).') AND f.fk_statut > '.Facture::STATUS_DRAFT.' AND fd.fk_product = '.((int) $this->id); dol_syslog(__METHOD__.":: sql $sql", LOG_NOTICE); $resql = $this->db->query($sql); From 572ba6d3e06b591c51dd7c0dd3d0ec7f6592248e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 19:15:46 +0100 Subject: [PATCH 124/816] Update product.class.php --- htdocs/product/class/product.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index d9e09ce788d..0271e0c0d2c 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3070,7 +3070,7 @@ class Product extends CommonObject if (!empty($conf->global->STOCK_CALCULATE_ON_BILL)) { if (!empty($conf->global->DECREASE_ONLY_UNINVOICEDPRODUCTS)) { $adeduire = 0; - $sql = "SELECT sum(fd.qty) as count FROM ".$this->db->prefix()."facturedet fd "; + $sql = "SELECT sum(fd.qty) as count FROM ".$this->db->prefix()."facturedet as fd "; $sql .= " JOIN ".$this->db->prefix()."facture as f ON fd.fk_facture = f.rowid "; $sql .= " JOIN ".$this->db->prefix()."element_element as el ON ((el.fk_target = f.rowid AND el.targettype = 'facture' AND sourcetype = 'commande') OR (el.fk_source = f.rowid AND el.targettype = 'commande' AND sourcetype = 'facture'))"; $sql .= " JOIN ".$this->db->prefix()."commande as c ON el.fk_source = c.rowid "; @@ -3090,7 +3090,7 @@ class Product extends CommonObject // For every order having invoice already validated we need to decrease stock cause it's in physical stock $adeduire = 0; - $sql = 'SELECT sum(fd.qty) as count FROM '.MAIN_DB_PREFIX.'facturedet fd '; + $sql = 'SELECT sum(fd.qty) as count FROM '.MAIN_DB_PREFIX.'facturedet as fd '; $sql .= ' JOIN '.MAIN_DB_PREFIX.'facture as f ON fd.fk_facture = f.rowid '; $sql .= ' JOIN '.MAIN_DB_PREFIX."element_element as el ON ((el.fk_target = f.rowid AND el.targettype = 'facture' AND sourcetype = 'commande') OR (el.fk_source = f.rowid AND el.targettype = 'commande' AND sourcetype = 'facture'))"; $sql .= ' JOIN '.MAIN_DB_PREFIX.'commande as c ON el.fk_source = c.rowid '; From 582d9ac514bd94632a8eea47fe39e25844cb0365 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 19:22:34 +0100 Subject: [PATCH 125/816] Update product.class.php --- htdocs/product/class/product.class.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 0271e0c0d2c..f17a128544a 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3005,7 +3005,7 @@ class Product extends CommonObject * * @param int $socid Id societe pour filtrer sur une societe * @param string $filtrestatut Id statut pour filtrer sur un statut - * @param int $forVirtualStock Ignore rights filter for virtual stock calculation. + * @param int $forVirtualStock Ignore rights filter for virtual stock calculation. Set when load_stats_commande is used for virtual stock calculation. * @return integer Array of stats in $this->stats_commande (nb=nb of order, qty=qty ordered), <0 if ko or >0 if ok */ public function load_stats_commande($socid = 0, $filtrestatut = '', $forVirtualStock = 0) @@ -3065,10 +3065,10 @@ class Product extends CommonObject } // If stock decrease is on invoice validation, the theorical stock continue to - // count the orders to ship in theorical stock when some are already removed b invoice validation. - // If option DECREASE_ONLY_UNINVOICEDPRODUCTS is on, we make a compensation. - if (!empty($conf->global->STOCK_CALCULATE_ON_BILL)) { + // count the orders to ship in theorical stock when some are already removed by invoice validation. + if ($forVirtualStock && !empty($conf->global->STOCK_CALCULATE_ON_BILL)) { if (!empty($conf->global->DECREASE_ONLY_UNINVOICEDPRODUCTS)) { + // If option DECREASE_ONLY_UNINVOICEDPRODUCTS is on, we make a compensation but only if order not yet invoice. $adeduire = 0; $sql = "SELECT sum(fd.qty) as count FROM ".$this->db->prefix()."facturedet as fd "; $sql .= " JOIN ".$this->db->prefix()."facture as f ON fd.fk_facture = f.rowid "; @@ -3086,6 +3086,7 @@ class Product extends CommonObject $this->stats_commande['qty'] -= $adeduire; } else { + // If option DECREASE_ONLY_UNINVOICEDPRODUCTS is off, we make a compensation with lines of invoices linked to the order include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; // For every order having invoice already validated we need to decrease stock cause it's in physical stock From ec95c6402452d45557e1be939fdd9ea730330de1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 23:20:42 +0100 Subject: [PATCH 126/816] Clean code --- htdocs/accountancy/admin/categories.php | 3 ++- htdocs/categories/viewcat.php | 2 +- htdocs/core/menus/standard/eldy.lib.php | 2 +- htdocs/core/modules/modMrp.class.php | 2 +- .../mailings/mailinglist_mymodule_myobject.modules.php | 8 ++++---- htdocs/mrp/lib/mrp.lib.php | 2 +- htdocs/recruitment/admin/setup.php | 3 +-- htdocs/recruitment/admin/setup_candidatures.php | 3 +-- htdocs/recruitment/lib/recruitment.lib.php | 4 ++-- 9 files changed, 14 insertions(+), 15 deletions(-) diff --git a/htdocs/accountancy/admin/categories.php b/htdocs/accountancy/admin/categories.php index 87e6a3b490c..442c0d6763b 100644 --- a/htdocs/accountancy/admin/categories.php +++ b/htdocs/accountancy/admin/categories.php @@ -1,6 +1,7 @@ * Copyright (C) 2017-2022 Alexandre Spangaro + * Copyright (C) 2022 Laurent Destailleur * * 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 @@ -31,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; $error = 0; // Load translation files required by the page -$langs->loadLangs(array("bills", "accountancy")); +$langs->loadLangs(array("bills", "accountancy", "compta")); $id = GETPOST('id', 'int'); $cancel = GETPOST('cancel', 'alpha'); diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 329c9473cc7..6f09e734406 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -35,7 +35,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; // Load translation files required by the page -$langs->load("categories"); +$langs->loadLangs(array("categories", "compta")); $id = GETPOST('id', 'int'); $label = GETPOST('label', 'alpha'); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 398aa6421a7..fece6df98ec 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1622,7 +1622,6 @@ function get_left_menu_accountancy($mainmenu, &$newmenu, $usemenuhider = 1, $lef $newmenu->add("/accountancy/admin/accountmodel.php?id=31&mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("Pcg_version"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_chartmodel', 40); $newmenu->add("/accountancy/admin/account.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("Chartofaccounts"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_chart', 41); $newmenu->add("/accountancy/admin/subaccount.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("ChartOfSubaccounts"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_chart', 41); - $newmenu->add("/accountancy/admin/categories_list.php?id=32&search_country_id=".$mysoc->country_id."&mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("AccountingCategory"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_chart', 50); $newmenu->add("/accountancy/admin/defaultaccounts.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuDefaultAccounts"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_default', 60); if (isModEnabled('banque')) { $newmenu->add("/compta/bank/list.php?mainmenu=accountancy&leftmenu=accountancy_admin&search_status=-1", $langs->trans("MenuBankAccounts"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_bank', 70); @@ -1640,6 +1639,7 @@ function get_left_menu_accountancy($mainmenu, &$newmenu, $usemenuhider = 1, $lef if ($conf->global->MAIN_FEATURES_LEVEL > 1) { $newmenu->add("/accountancy/admin/closure.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuClosureAccounts"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_closure', 120); } + $newmenu->add("/accountancy/admin/categories_list.php?id=32&search_country_id=".$mysoc->country_id."&mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("AccountingCategory"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_chart', 125); $newmenu->add("/accountancy/admin/export.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("ExportOptions"), 1, $user->hasRight('accounting', 'chartofaccount'), '', $mainmenu, 'accountancy_admin_export', 130); } diff --git a/htdocs/core/modules/modMrp.class.php b/htdocs/core/modules/modMrp.class.php index fb836c8393b..58e7791845a 100644 --- a/htdocs/core/modules/modMrp.class.php +++ b/htdocs/core/modules/modMrp.class.php @@ -2,7 +2,7 @@ /* Copyright (C) 2004-2018 Laurent Destailleur * Copyright (C) 2018-2019 Nicolas ZABOURI * Copyright (C) 2019 Frédéric France - * Copyright (C) 2019 Alicealalalamdskfldmjgdfgdfhfghgfh Adminson + * Copyright (C) 2019 Destailleur Laurent * * 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 diff --git a/htdocs/modulebuilder/template/core/modules/mailings/mailinglist_mymodule_myobject.modules.php b/htdocs/modulebuilder/template/core/modules/mailings/mailinglist_mymodule_myobject.modules.php index 7b2c4e2ab5a..ad0814f7b4d 100644 --- a/htdocs/modulebuilder/template/core/modules/mailings/mailinglist_mymodule_myobject.modules.php +++ b/htdocs/modulebuilder/template/core/modules/mailings/mailinglist_mymodule_myobject.modules.php @@ -104,9 +104,9 @@ class mailing_mailinglist_mymodule_myobject extends MailingTargets $target = array(); $j = 0; - $sql = " select rowid as id, email, firstname, lastname, plan, partner"; + $sql = " select rowid as id, label, firstname, lastname"; $sql .= " from ".MAIN_DB_PREFIX."myobject"; - $sql .= " where email IS NOT NULL AND email != ''"; + $sql .= " where email IS NOT NULL AND email <> ''"; if (GETPOSTISSET('filter') && GETPOST('filter', 'alphanohtml') != 'none') { $sql .= " AND status = '".$this->db->escape(GETPOST('filter', 'alphanohtml'))."'"; } @@ -129,10 +129,10 @@ class mailing_mailinglist_mymodule_myobject extends MailingTargets 'name' => $obj->lastname, 'id' => $obj->id, 'firstname' => $obj->firstname, - 'other' => $obj->plan.';'.$obj->partner, + 'other' => $obj->label, 'source_url' => $this->url($obj->id), 'source_id' => $obj->id, - 'source_type' => 'dolicloud' + 'source_type' => 'myobject@mymodule' ); $old = $obj->email; $j++; diff --git a/htdocs/mrp/lib/mrp.lib.php b/htdocs/mrp/lib/mrp.lib.php index 854244e53c7..55ec94ef097 100644 --- a/htdocs/mrp/lib/mrp.lib.php +++ b/htdocs/mrp/lib/mrp.lib.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2019 Laurent Destailleur * * 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 diff --git a/htdocs/recruitment/admin/setup.php b/htdocs/recruitment/admin/setup.php index 517bbca5c19..120c476de90 100644 --- a/htdocs/recruitment/admin/setup.php +++ b/htdocs/recruitment/admin/setup.php @@ -1,6 +1,5 @@ - * Copyright (C) 2020 Adminson Alicealalalamdskfldmjgdfgdfhfghgfh +/* Copyright (C) 2004-2020 Laurent Destailleur * * 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 diff --git a/htdocs/recruitment/admin/setup_candidatures.php b/htdocs/recruitment/admin/setup_candidatures.php index adc12a656f4..b53fff4213a 100644 --- a/htdocs/recruitment/admin/setup_candidatures.php +++ b/htdocs/recruitment/admin/setup_candidatures.php @@ -1,6 +1,5 @@ - * Copyright (C) 2020 Adminson Alicealalalamdskfldmjgdfgdfhfghgfh +/* Copyright (C) 2004-2020 Laurent Destailleur * * 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 diff --git a/htdocs/recruitment/lib/recruitment.lib.php b/htdocs/recruitment/lib/recruitment.lib.php index 6fa58cc64f5..911c6abdb03 100644 --- a/htdocs/recruitment/lib/recruitment.lib.php +++ b/htdocs/recruitment/lib/recruitment.lib.php @@ -1,6 +1,6 @@ - * Copyright (C) 2022 Frédéric France +/* Copyright (C) 2019 Laurent Destailleur + * Copyright (C) 2022 Frédéric France * * 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 f7f140f003eb0b7e10bb929b054d9f1d640efc3c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 28 Dec 2022 23:39:46 +0100 Subject: [PATCH 127/816] css --- htdocs/accountancy/admin/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 385c105451e..244b6f72330 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -430,7 +430,7 @@ foreach ($list_binding as $key) { print $form->selectDate((!empty($conf->global->$key) ? $db->idate($conf->global->$key) : -1), $key, 0, 0, 1); } elseif ($key == 'ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER') { $array = array(0=>$langs->trans("PreviousMonth"), 1=>$langs->trans("CurrentMonth"), 2=>$langs->trans("Fiscalyear")); - print $form->selectarray($key, $array, (isset($conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER) ? $conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER : 0)); + print $form->selectarray($key, $array, (isset($conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER) ? $conf->global->ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER : 0), 0, 0, 0, '', 0, 0, 0, '', 'onrightofpage'); } else { print ''; } From aa5419cfb53626010970a5a6339bd33e298cb6a2 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Thu, 29 Dec 2022 16:10:53 +0100 Subject: [PATCH 128/816] update in modulbuilder for menu object --- htdocs/modulebuilder/index.php | 58 +++++++++++++++++-- .../core/modules/modMyModule.class.php | 2 +- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 8b87d84c10e..eeb016db6b6 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1344,12 +1344,12 @@ if ($dirins && $action == 'initobject' && $module && $objectname) { // 0=Menu for internal users, 1=external users, 2=both 'user'=>2 );\n"; - $stringtoadd = preg_replace('/MyObject/', $objectnameloop, $stringtoadd); + $stringtoadd = preg_replace('/MyObject/', $objectname, $stringtoadd); $stringtoadd = preg_replace('/mymodule/', strtolower($module), $stringtoadd); - $stringtoadd = preg_replace('/myobject/', strtolower($objectnameloop), $stringtoadd); + $stringtoadd = preg_replace('/myobject/', strtolower($objectname), $stringtoadd); $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php'; - + } // TODO Allow a replace with regex using dolReplaceInFile with param arryreplacementisregex to 1 // TODO Avoid duplicate addition @@ -1357,7 +1357,6 @@ if ($dirins && $action == 'initobject' && $module && $objectname) { // Add module descriptor to list of files to replace "MyObject' string with real name of object. $filetogenerate[] = 'core/modules/mod'.$module.'.class.php'; - } } if (!$error) { @@ -1377,7 +1376,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) { 'htdocs/modulebuilder/template/'=>strtolower($modulename), 'myobject'=>strtolower($objectname), 'MyObject'=>$objectname, - 'MYOBJECT'=>strtoupper($objectname), + //'MYOBJECT'=>strtoupper($objectname), '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : '') ); @@ -1730,6 +1729,55 @@ if ($dirins && $action == 'confirm_deleteobject' && $objectname) { 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php'=>'core/modules/'.strtolower($module).'/doc/pdf_standard_'.strtolower($objectname).'.modules.php' ); + //menu for the object selected + $stringtoedit = "\$this->menu[\$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=".strtolower($module)."', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'List ".ucfirst($objectname)."', + 'mainmenu'=>'".strtolower($module)."', + 'leftmenu'=>'".strtolower($module)."_".strtolower($objectname)."', + 'url'=>'/".strtolower($module)."/".strtolower($objectname)."_list.php', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'".strtolower($module)."@".strtolower($module)."', + 'position'=>1100+\$r, + // Define condition to show or hide menu entry. Use '\$conf->".strtolower($module)."->enabled' if entry must be visible if module is enabled. Use '\$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'\$conf->".strtolower($module)."->enabled', + // Use 'perms'=>'\$user->rights->".strtolower($module)."->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2, + ); + \$this->menu[\$r++]=array( + // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'fk_menu'=>'fk_mainmenu=".strtolower($module).",fk_leftmenu=".strtolower($module)."_".strtolower($objectname)."', + // This is a Left menu entry + 'type'=>'left', + 'titre'=>'New ".ucfirst($objectname)."', + 'mainmenu'=>'".strtolower($module)."', + 'leftmenu'=>'".strtolower($module)."_".strtolower($objectname)."', + 'url'=>'/".strtolower($module)."/".strtolower($objectname)."_card.php?action=create', + // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'langs'=>'".strtolower($module)."@".strtolower($module)."', + 'position'=>1100+\$r, + // Define condition to show or hide menu entry. Use '\$conf->".strtolower($module)."->enabled' if entry must be visible if module is enabled. Use '\$leftmenu==\'system\'' to show if leftmenu system is selected. + 'enabled'=>'\$conf->".strtolower($module)."->enabled', + // Use 'perms'=>'\$user->rights->".strtolower($module)."->level1->level2' if you want your menu with a permission rules + 'perms'=>'1', + 'target'=>'', + // 0=Menu for internal users, 1=external users, 2=both + 'user'=>2 + );"; + + $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; + + $check = dolReplaceInFile($moduledescriptorfile, array($stringtoedit => '')); + if ($check > 0) { + dolReplaceInFile($moduledescriptorfile, array('/*'.strtoupper($objectname).'*/' => '')); + } + $resultko = 0; foreach ($filetodelete as $filetodelete) { $resulttmp = dol_delete_file($dir.'/'.$filetodelete, 0, 0, 1); diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 99cd900b512..2788c78fc37 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -348,7 +348,7 @@ class modMyModule extends DolibarrModules 'target'=>'', 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both ); - END MODULEBUILDER LEFTMENU MYOBJECT */ + /* END MODULEBUILDER LEFTMENU MYOBJECT */ // Exports profiles provided by this module $r = 1; /* BEGIN MODULEBUILDER EXPORT MYOBJECT */ From a7c2d723158916e1e73b4e28063a202df2b5ab11 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 13:28:36 +0100 Subject: [PATCH 129/816] NEW Can filter on a custom group of accounts. Perf or ledger list. --- htdocs/accountancy/admin/card.php | 4 +- htdocs/accountancy/admin/categories.php | 2 +- htdocs/accountancy/bookkeeping/list.php | 83 ++++++-- .../accountancy/bookkeeping/listbyaccount.php | 53 +++-- .../class/accountancycategory.class.php | 127 ++++++------ .../accountancy/class/bookkeeping.class.php | 181 ++++++++++-------- .../core/class/html.formaccounting.class.php | 4 +- htdocs/langs/en_US/accountancy.lang | 2 +- 8 files changed, 277 insertions(+), 179 deletions(-) diff --git a/htdocs/accountancy/admin/card.php b/htdocs/accountancy/admin/card.php index 97d2509b898..43d1852c720 100644 --- a/htdocs/accountancy/admin/card.php +++ b/htdocs/accountancy/admin/card.php @@ -282,7 +282,7 @@ if ($action == 'create') { print $form->textwithpicto($langs->trans("AccountingCategory"), $langs->transnoentitiesnoconv("AccountingAccountGroupsDesc")); print ''; print '
'; print '
'; print $langs->trans('RetainedWarrantyDateLimit'); print 'id.'">'.img_edit($langs->trans('setretainedwarrantyDateLimit'), 1).''; - $formaccounting->select_accounting_category($object->account_category, 'account_category', 1, 0, 1); + print $formaccounting->select_accounting_category($object->account_category, 'account_category', 1, 0, 1); print '
'; @@ -359,7 +359,7 @@ if ($action == 'create') { print $form->textwithpicto($langs->trans("AccountingCategory"), $langs->transnoentitiesnoconv("AccountingAccountGroupsDesc")); print '
'; - $formaccounting->select_accounting_category($object->account_category, 'account_category', 1); + print $formaccounting->select_accounting_category($object->account_category, 'account_category', 1); print '
'; diff --git a/htdocs/accountancy/admin/categories.php b/htdocs/accountancy/admin/categories.php index 442c0d6763b..3414c36cd52 100644 --- a/htdocs/accountancy/admin/categories.php +++ b/htdocs/accountancy/admin/categories.php @@ -111,7 +111,7 @@ print ''; // Select the category print ''; print ''; diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 9590c3551cf..ac1cc93cba7 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -102,7 +102,9 @@ if (GETPOST("button_export_file_x") || GETPOST("button_export_file.x") || GETPOS $action = 'export_file'; } -$search_accountancy_code = GETPOST("search_accountancy_code"); +$search_account_category = GETPOST('search_account_category', 'int'); + +$search_accountancy_code = GETPOST("search_accountancy_code", 'alpha'); $search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha'); if ($search_accountancy_code_start == - 1) { $search_accountancy_code_start = ''; @@ -253,6 +255,7 @@ if (empty($reshook)) { $search_doc_type = ''; $search_doc_ref = ''; $search_doc_date = ''; + $search_account_category = ''; $search_accountancy_code = ''; $search_accountancy_code_start = ''; $search_accountancy_code_end = ''; @@ -335,6 +338,20 @@ if (empty($reshook)) { $filter['t.doc_ref'] = $search_doc_ref; $param .= '&search_doc_ref='.urlencode($search_doc_ref); } + if ($search_account_category != '-1' && !empty($search_account_category)) { + require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.php'; + $accountingcategory = new AccountancyCategory($db); + + $listofaccountsforgroup = $accountingcategory->getCptsCat(0, 'fk_accounting_category = '.((int) $search_account_category)); + $listofaccountsforgroup2 = array(); + if (is_array($listofaccountsforgroup)) { + foreach ($listofaccountsforgroup as $tmpval) { + $listofaccountsforgroup2[] = $tmpval['id']; + } + } + $filter['t.search_accounting_code_in'] = join(',', $listofaccountsforgroup2); + $param .= '&search_account_category='.urlencode($search_account_category); + } if (!empty($search_accountancy_code)) { $filter['t.numero_compte'] = $search_accountancy_code; $param .= '&search_accountancy_code='.urlencode($search_accountancy_code); @@ -642,6 +659,9 @@ $sql .= " t.tms as date_modification,"; $sql .= " t.date_export,"; $sql .= " t.date_validated as date_validation,"; $sql .= " t.import_key"; + +$sqlfields = $sql; // $sql fields to remove for count total + $sql .= ' FROM '.MAIN_DB_PREFIX.$object->table_element.' as t'; // Manage filter $sqlwhere = array(); @@ -672,7 +692,13 @@ if (count($filter) > 0) { } elseif ($key == 't.reconciled_option') { $sqlwhere[] = 't.lettering_code IS NULL'; } elseif ($key == 't.code_journal' && !empty($value)) { - $sqlwhere[] = natural_search("t.code_journal", join(',', $value), 3, 1); + if (is_array($value)) { + $sqlwhere[] = natural_search("t.code_journal", join(',', $value), 3, 1); + } else { + $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); + } + } elseif ($key == 't.search_accounting_code_in' && !empty($value)) { + $sqlwhere[] = 't.numero_compte IN ('.$value.')'; } else { $sqlwhere[] = natural_search($key, $value, 0, 1); } @@ -685,9 +711,6 @@ if (empty($conf->global->ACCOUNTING_REEXPORT)) { if (count($sqlwhere) > 0) { $sql .= ' AND '.implode(' AND ', $sqlwhere); } -if (!empty($sortfield)) { - $sql .= $db->order($sortfield, $sortorder); -} //print $sql; @@ -783,28 +806,38 @@ $title_page = $langs->trans("Operations").' - '.$langs->trans("Journals"); // Count total nb of records $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $resql = $db->query($sql); - $nbtotalofrecords = $db->num_rows($resql); - if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); + $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); + if ($resql) { + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + } else { + dol_print_error($db); + } + + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } + $db->free($resql); } -// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set. -if (is_numeric($nbtotalofrecords) && $limit > $nbtotalofrecords) { - $num = $nbtotalofrecords; -} else { + +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { $sql .= $db->plimit($limit + 1, $offset); - - $resql = $db->query($sql); - if (!$resql) { - dol_print_error($db); - exit; - } - - $num = $db->num_rows($resql); } +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + $arrayofselected = is_array($toselect) ? $toselect : array(); // Output page @@ -997,6 +1030,12 @@ if ($massactionbutton && $contextpage != 'poslist') { } $moreforfilter = ''; +$moreforfilter .= '
'; +$moreforfilter .= $langs->trans('AccountingCategory').': '; +$moreforfilter .= '
'; +$moreforfilter .= $formaccounting->select_accounting_category($search_account_category, 'search_account_category', 1, 0, 0, 0); +$moreforfilter .= '
'; +$moreforfilter .= '
'; $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -1006,6 +1045,10 @@ if (empty($reshook)) { $moreforfilter = $hookmanager->resPrint; } +print '
'; +print $moreforfilter; +print '
'; + print '
'; print '
'.$langs->trans("AccountingCategory").''; -$formaccounting->select_accounting_category($cat_id, 'account_category', 1, 0, 0, 0); +print $formaccounting->select_accounting_category($cat_id, 'account_category', 1, 0, 0, 0); print ''; print '
'; diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 4a6e37ceb29..c24e509ff60 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -79,7 +79,8 @@ $search_date_validation_start = dol_mktime(0, 0, 0, $search_date_validation_star $search_date_validation_end = dol_mktime(23, 59, 59, $search_date_validation_endmonth, $search_date_validation_endday, $search_date_validation_endyear); $search_import_key = GETPOST("search_import_key", 'alpha'); -$search_accountancy_code = GETPOST("search_accountancy_code"); +$search_account_category = GETPOST('search_account_category', 'int'); + $search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha'); if ($search_accountancy_code_start == - 1) { $search_accountancy_code_start = ''; @@ -198,6 +199,8 @@ if (!$user->hasRight('accounting', 'mouvements', 'lire')) { accessforbidden(); } +$error = 0; + /* * Action @@ -224,7 +227,7 @@ if (empty($reshook)) { if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers $search_doc_date = ''; - $search_accountancy_code = ''; + $search_account_category = ''; $search_accountancy_code_start = ''; $search_accountancy_code_end = ''; $search_label_account = ''; @@ -280,6 +283,20 @@ if (empty($reshook)) { $filter['t.doc_date'] = $search_doc_date; $param .= '&doc_datemonth='.GETPOST('doc_datemonth', 'int').'&doc_dateday='.GETPOST('doc_dateday', 'int').'&doc_dateyear='.GETPOST('doc_dateyear', 'int'); } + if ($search_account_category != '-1' && !empty($search_account_category)) { + require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.php'; + $accountingcategory = new AccountancyCategory($db); + + $listofaccountsforgroup = $accountingcategory->getCptsCat(0, 'fk_accounting_category = '.((int) $search_account_category)); + $listofaccountsforgroup2 = array(); + if (is_array($listofaccountsforgroup)) { + foreach ($listofaccountsforgroup as $tmpval) { + $listofaccountsforgroup2[] = $tmpval['id']; + } + } + $filter['t.search_accounting_code_in'] = join(',', $listofaccountsforgroup2); + $param .= '&search_account_category='.urlencode($search_account_category); + } if (!empty($search_accountancy_code_start)) { if ($type == 'sub') { $filter['t.subledger_account>='] = $search_accountancy_code_start; @@ -358,7 +375,6 @@ if (empty($reshook)) { $filter['t.import_key'] = $search_import_key; $param .= '&search_import_key='.urlencode($search_import_key); } - // param with type of list $url_param = substr($param, 1); // remove first "&" if (!empty($type)) { @@ -544,25 +560,29 @@ llxHeader('', $title_page); // List $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + // TODO Perf Replace this by a count if ($type == 'sub') { - $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter, 'AND', 1); + $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter, 'AND', 1, 1); } else { - $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter); + $nbtotalofrecords = $object->fetchAllByAccount($sortorder, $sortfield, 0, 0, $filter, 'AND', 0, 1); } if ($nbtotalofrecords < 0) { setEventMessages($object->error, $object->errors, 'errors'); + $error++; } } -if ($type == 'sub') { - $result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1); -} else { - $result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter); -} +if (!$error) { + if ($type == 'sub') { + $result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1); + } else { + $result = $object->fetchAllByAccount($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 0); + } -if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } } $arrayofselected = is_array($toselect) ? $toselect : array(); @@ -711,7 +731,7 @@ if ($type == 'sub') { $moreforfilter = ''; -// Accountancy account +// Search on accountancy custom groups or account $moreforfilter .= '
'; $moreforfilter .= $langs->trans('AccountAccounting').': '; $moreforfilter .= '
'; @@ -729,6 +749,13 @@ if ($type == 'sub') { $moreforfilter .= '
'; $moreforfilter .= '
'; +$moreforfilter .= '
'; +$moreforfilter .= $langs->trans('AccountingCategory').': '; +$moreforfilter .= '
'; +$moreforfilter .= $formaccounting->select_accounting_category($search_account_category, 'search_account_category', 1, 0, 0, 0); +$moreforfilter .= '
'; +$moreforfilter .= '
'; + $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook if (empty($reshook)) { diff --git a/htdocs/accountancy/class/accountancycategory.class.php b/htdocs/accountancy/class/accountancycategory.class.php index 2f6c71dde7f..74626aa61e0 100644 --- a/htdocs/accountancy/class/accountancycategory.class.php +++ b/htdocs/accountancy/class/accountancycategory.class.php @@ -605,60 +605,6 @@ class AccountancyCategory // extends CommonObject } } - /** - * Function to know all custom groupd from an accounting account - * - * @return array|integer Result in table (array), -1 if KO - */ - public function getCatsCpts() - { - global $mysoc, $conf; - - if (empty($mysoc->country_id)) { - dol_print_error('', 'Call to select_accounting_account with mysoc country not yet defined'); - exit(); - } - - $sql = "SELECT t.rowid, t.account_number, t.label as account_label, cat.code, cat.position, cat.label as name_cat, cat.sens "; - $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as t, ".MAIN_DB_PREFIX."c_accounting_category as cat"; - $sql .= " WHERE t.fk_accounting_category IN ( SELECT c.rowid "; - $sql .= " FROM ".MAIN_DB_PREFIX."c_accounting_category as c"; - $sql .= " WHERE c.active = 1"; - $sql .= " AND c.entity = ".$conf->entity; - $sql .= " AND (c.fk_country = ".((int) $mysoc->country_id)." OR c.fk_country = 0)"; - $sql .= " AND cat.rowid = t.fk_accounting_category"; - $sql .= " AND t.entity = ".$conf->entity; - $sql .= " ORDER BY cat.position ASC"; - - $resql = $this->db->query($sql); - if ($resql) { - $i = 0; - $obj = ''; - $num = $this->db->num_rows($resql); - $data = array(); - if ($num) { - while ($obj = $this->db->fetch_object($resql)) { - $name_cat = $obj->name_cat; - $data[$name_cat][$i] = array( - 'id' => $obj->rowid, - 'code' => $obj->code, - 'position' => $obj->position, - 'account_number' => $obj->account_number, - 'account_label' => $obj->account_label, - 'sens' => $obj->sens - ); - $i++; - } - } - return $data; - } else { - $this->error = "Error ".$this->db->lasterror(); - dol_syslog(__METHOD__." ".$this->error, LOG_ERR); - - return -1; - } - } - /** * Function to show result of an accounting account from the ledger with a direction and a period * @@ -734,12 +680,75 @@ class AccountancyCategory // extends CommonObject } } + /** + * Function to get an array of all active custom groups (llx_c_accunting_categories) with their accounts from the chart of account (ll_accounting_acount) + * + * @param int $catid Custom group ID + * @return array|integer Result in table (array), -1 if KO + * @see getCats(), getCptsCat() + */ + public function getCatsCpts($catid = 0) + { + global $mysoc, $conf; + + if (empty($mysoc->country_id)) { + $this->error = "Error ".$this->db->lasterror(); + dol_syslog(__METHOD__." ".$this->error, LOG_ERR); + return -1; + } + + $sql = "SELECT t.rowid, t.account_number, t.label as account_label,"; + $sql .= " cat.code, cat.position, cat.label as name_cat, cat.sens, cat.category_type, cat.formula"; + $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as t, ".MAIN_DB_PREFIX."c_accounting_category as cat"; + $sql .= " WHERE t.fk_accounting_category IN (SELECT c.rowid"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_accounting_category as c"; + $sql .= " WHERE c.active = 1"; + $sql .= " AND c.entity = ".$conf->entity; + $sql .= " AND (c.fk_country = ".((int) $mysoc->country_id)." OR c.fk_country = 0)"; + $sql .= " AND cat.rowid = t.fk_accounting_category"; + $sql .= " AND t.entity = ".$conf->entity; + if ($catid > 0) { + $sql .= " AND cat.rowid = ".((int) $catid); + } + $sql .= " ORDER BY cat.position ASC"; + + $resql = $this->db->query($sql); + if ($resql) { + $obj = ''; + $num = $this->db->num_rows($resql); + $data = array(); + if ($num) { + while ($obj = $this->db->fetch_object($resql)) { + $name_cat = $obj->name_cat; + $data[$name_cat][$obj->rowid] = array( + 'id' => $obj->rowid, + 'code' => $obj->code, + 'label' => $obj->label, + 'position' => $obj->position, + 'category_type' => $obj->category_type, + 'formula' => $obj->formula, + 'sens' => $obj->sens, + 'account_number' => $obj->account_number, + 'account_label' => $obj->account_label + ); + } + } + return $data; + } else { + $this->error = "Error ".$this->db->lasterror(); + dol_syslog(__METHOD__." ".$this->error, LOG_ERR); + return -1; + } + } + /** * Return list of custom groups. + * For list + detail of accounting account, see getCatsCpt() * * @param int $categorytype -1=All, 0=Only non computed groups, 1=Only computed groups * @param int $active 1= active, 0=not active * @return array|int Array of groups or -1 if error + * @see getCatsCpts(), getCptsCat() */ public function getCats($categorytype = -1, $active = 1) { @@ -774,9 +783,10 @@ class AccountancyCategory // extends CommonObject 'rowid' => $obj->rowid, 'code' => $obj->code, 'label' => $obj->label, - 'formula' => $obj->formula, 'position' => $obj->position, 'category_type' => $obj->category_type, + 'formula' => $obj->formula, + 'sens' => $obj->sens, 'bc' => $obj->sens ); $i++; @@ -794,12 +804,15 @@ class AccountancyCategory // extends CommonObject /** - * Get all accounting account of a custom group (or a list of custom groups). + * Get all accounting account of a given custom group (or a list of custom groups). * You must choose between first parameter (personalized group) or the second (free criteria filter) * * @param int $cat_id Id if personalized accounting group/category - * @param string $predefinedgroupwhere Sql criteria filter to select accounting accounts. This value must not come from an input of a user. + * @param string $predefinedgroupwhere Sql criteria filter to select accounting accounts. This value must be sanitized and not come from an input of a user. + * Example: "pcg_type = 'EXPENSE' AND fk_pcg_version = 'xx'" + * Example: "fk_accounting_category = 99" * @return array|int Array of accounting accounts or -1 if error + * @see getCats(), getCatsCpts() */ public function getCptsCat($cat_id, $predefinedgroupwhere = '') { diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 95ba38d20bb..0458250489f 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -817,56 +817,61 @@ class BookKeeping extends CommonObject /** - * Load object in memory from the database + * Load object in memory from the database in ->lines. Or just make a simple count if $countonly=1. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit offset limit - * @param int $offset offset limit - * @param array $filter filter array - * @param string $filtermode filter mode (AND or OR) - * @param int $option option (0: general account or 1: subaccount) - * - * @return int <0 if KO, >=0 if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit offset limit + * @param int $offset offset limit + * @param array $filter filter array + * @param string $filtermode filter mode (AND or OR) + * @param int $option option (0: general account or 1: subaccount) + * @param int $countonly Do not fill the $object->lines, return only the count. + * @return int <0 if KO, Number of lines if OK */ - public function fetchAllByAccount($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND', $option = 0) + public function fetchAllByAccount($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND', $option = 0, $countonly = 0) { global $conf; dol_syslog(__METHOD__, LOG_DEBUG); $this->lines = array(); + $num = 0; $sql = 'SELECT'; - $sql .= ' t.rowid,'; - $sql .= " t.doc_date,"; - $sql .= " t.doc_type,"; - $sql .= " t.doc_ref,"; - $sql .= " t.fk_doc,"; - $sql .= " t.fk_docdet,"; - $sql .= " t.thirdparty_code,"; - $sql .= " t.subledger_account,"; - $sql .= " t.subledger_label,"; - $sql .= " t.numero_compte,"; - $sql .= " t.label_compte,"; - $sql .= " t.label_operation,"; - $sql .= " t.debit,"; - $sql .= " t.credit,"; - $sql .= " t.montant as amount,"; - $sql .= " t.sens,"; - $sql .= " t.multicurrency_amount,"; - $sql .= " t.multicurrency_code,"; - $sql .= " t.lettering_code,"; - $sql .= " t.date_lettering,"; - $sql .= " t.fk_user_author,"; - $sql .= " t.import_key,"; - $sql .= " t.code_journal,"; - $sql .= " t.journal_label,"; - $sql .= " t.piece_num,"; - $sql .= " t.date_creation,"; - $sql .= " t.date_export,"; - $sql .= " t.date_validated as date_validation,"; - $sql .= " t.import_key"; + if ($countonly) { + $sql .= ' COUNT(t.rowid) as nb'; + } else { + $sql .= ' t.rowid,'; + $sql .= " t.doc_date,"; + $sql .= " t.doc_type,"; + $sql .= " t.doc_ref,"; + $sql .= " t.fk_doc,"; + $sql .= " t.fk_docdet,"; + $sql .= " t.thirdparty_code,"; + $sql .= " t.subledger_account,"; + $sql .= " t.subledger_label,"; + $sql .= " t.numero_compte,"; + $sql .= " t.label_compte,"; + $sql .= " t.label_operation,"; + $sql .= " t.debit,"; + $sql .= " t.credit,"; + $sql .= " t.montant as amount,"; + $sql .= " t.sens,"; + $sql .= " t.multicurrency_amount,"; + $sql .= " t.multicurrency_code,"; + $sql .= " t.lettering_code,"; + $sql .= " t.date_lettering,"; + $sql .= " t.fk_user_author,"; + $sql .= " t.import_key,"; + $sql .= " t.code_journal,"; + $sql .= " t.journal_label,"; + $sql .= " t.piece_num,"; + $sql .= " t.date_creation,"; + $sql .= " t.date_export,"; + $sql .= " t.date_validated as date_validation,"; + $sql .= " t.import_key"; + } // Manage filter $sqlwhere = array(); if (count($filter) > 0) { @@ -880,7 +885,7 @@ class BookKeeping extends CommonObject } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') { $sqlwhere[] = $key.'='.$value; } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') { - $sqlwhere[] = $key.' LIKE \''.$this->db->escape($value).'%\''; + $sqlwhere[] = $key.' LIKE \''.$this->db->escapeforlike($this->db->escape($value)).'%\''; } elseif ($key == 't.date_creation>=' || $key == 't.date_creation<=') { $sqlwhere[] = $key.'\''.$this->db->idate($value).'\''; } elseif ($key == 't.date_export>=' || $key == 't.date_export<=') { @@ -897,18 +902,19 @@ class BookKeeping extends CommonObject } else { $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); } + } elseif ($key == 't.search_accounting_code_in' && !empty($value)) { + $sqlwhere[] = 't.numero_compte IN ('.$value.')'; } else { $sqlwhere[] = natural_search($key, $value, 0, 1); } } } $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; - $sql .= ' WHERE 1 = 1'; - $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features + $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features if (count($sqlwhere) > 0) { $sql .= " AND ".implode(" ".$filtermode." ", $sqlwhere); } - // Affichage par compte comptable + // Filter by ledger account or subledger account if (!empty($option)) { $sql .= " AND t.subledger_account IS NOT NULL"; $sql .= " AND t.subledger_account <> ''"; @@ -919,54 +925,63 @@ class BookKeeping extends CommonObject $sortorder = 'ASC'.($sortorder ? ','.$sortorder : ''); } - $sql .= $this->db->order($sortfield, $sortorder); - if (!empty($limit)) { - $sql .= $this->db->plimit($limit + 1, $offset); + if (!$countonly) { + $sql .= $this->db->order($sortfield, $sortorder); + if (!empty($limit)) { + $sql .= $this->db->plimit($limit + 1, $offset); + } } $resql = $this->db->query($sql); if ($resql) { - $num = $this->db->num_rows($resql); + if ($countonly) { + $obj = $this->db->fetch_object($resql); + if ($obj) { + $num = $obj->nb; + } + } else { + $num = $this->db->num_rows($resql); - $i = 0; - while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) { - $line = new BookKeepingLine(); + $i = 0; + while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) { + $line = new BookKeepingLine(); - $line->id = $obj->rowid; + $line->id = $obj->rowid; - $line->doc_date = $this->db->jdate($obj->doc_date); - $line->doc_type = $obj->doc_type; - $line->doc_ref = $obj->doc_ref; - $line->fk_doc = $obj->fk_doc; - $line->fk_docdet = $obj->fk_docdet; - $line->thirdparty_code = $obj->thirdparty_code; - $line->subledger_account = $obj->subledger_account; - $line->subledger_label = $obj->subledger_label; - $line->numero_compte = $obj->numero_compte; - $line->label_compte = $obj->label_compte; - $line->label_operation = $obj->label_operation; - $line->debit = $obj->debit; - $line->credit = $obj->credit; - $line->montant = $obj->amount; // deprecated - $line->amount = $obj->amount; - $line->sens = $obj->sens; - $line->multicurrency_amount = $obj->multicurrency_amount; - $line->multicurrency_code = $obj->multicurrency_code; - $line->lettering_code = $obj->lettering_code; - $line->date_lettering = $obj->date_lettering; - $line->fk_user_author = $obj->fk_user_author; - $line->import_key = $obj->import_key; - $line->code_journal = $obj->code_journal; - $line->journal_label = $obj->journal_label; - $line->piece_num = $obj->piece_num; - $line->date_creation = $this->db->jdate($obj->date_creation); - $line->date_export = $this->db->jdate($obj->date_export); - $line->date_validation = $this->db->jdate($obj->date_validation); - $line->import_key = $obj->import_key; + $line->doc_date = $this->db->jdate($obj->doc_date); + $line->doc_type = $obj->doc_type; + $line->doc_ref = $obj->doc_ref; + $line->fk_doc = $obj->fk_doc; + $line->fk_docdet = $obj->fk_docdet; + $line->thirdparty_code = $obj->thirdparty_code; + $line->subledger_account = $obj->subledger_account; + $line->subledger_label = $obj->subledger_label; + $line->numero_compte = $obj->numero_compte; + $line->label_compte = $obj->label_compte; + $line->label_operation = $obj->label_operation; + $line->debit = $obj->debit; + $line->credit = $obj->credit; + $line->montant = $obj->amount; // deprecated + $line->amount = $obj->amount; + $line->sens = $obj->sens; + $line->multicurrency_amount = $obj->multicurrency_amount; + $line->multicurrency_code = $obj->multicurrency_code; + $line->lettering_code = $obj->lettering_code; + $line->date_lettering = $obj->date_lettering; + $line->fk_user_author = $obj->fk_user_author; + $line->import_key = $obj->import_key; + $line->code_journal = $obj->code_journal; + $line->journal_label = $obj->journal_label; + $line->piece_num = $obj->piece_num; + $line->date_creation = $this->db->jdate($obj->date_creation); + $line->date_export = $this->db->jdate($obj->date_export); + $line->date_validation = $this->db->jdate($obj->date_validation); + $line->import_key = $obj->import_key; - $this->lines[] = $line; + $this->lines[] = $line; - $i++; + $i++; + } } $this->db->free($resql); diff --git a/htdocs/core/class/html.formaccounting.class.php b/htdocs/core/class/html.formaccounting.class.php index 8ebac3611cb..545d0da67a1 100644 --- a/htdocs/core/class/html.formaccounting.class.php +++ b/htdocs/core/class/html.formaccounting.class.php @@ -224,7 +224,7 @@ class FormAccounting extends Form * @param int $maxlen Max length of text in combo box * @param int $help Add or not the admin help picto * @param int $allcountries All countries - * @return void + * @return string HTML component with the select */ public function select_accounting_category($selected = '', $htmlname = 'account_category', $useempty = 0, $maxlen = 0, $help = 1, $allcountries = 0) { @@ -295,7 +295,7 @@ class FormAccounting extends Form $out .= ajax_combobox($htmlname, array()); - print $out; + return $out; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index b6bf1b90aef..03af44134e2 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -217,7 +217,7 @@ Codejournal=Journal JournalLabel=Journal label NumPiece=Piece number TransactionNumShort=Num. transaction -AccountingCategory=Custom group +AccountingCategory=Custom group of accounts GroupByAccountAccounting=Group by general ledger account GroupBySubAccountAccounting=Group by subledger account AccountingAccountGroupsDesc=You can define here some groups of accounting account. They will be used for personalized accounting reports. From 474dd5197ff24dd61d60539bfa48cb0c998717d1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 17:06:39 +0100 Subject: [PATCH 130/816] Fix tooltip in report --- htdocs/compta/resultat/result.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index 3f3e14e2d61..cb2158bb48b 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -320,9 +320,9 @@ if ($modecompta == 'CREANCES-DETTES') { print ''; // Year NP - print ''; @@ -399,8 +399,7 @@ if ($modecompta == 'CREANCES-DETTES') { print "\n"; //var_dump($sommes); - } else // normal category - { + } else { // normal category $code = $cat['code']; // Category code we process $totCat = array(); @@ -478,37 +477,38 @@ if ($modecompta == 'CREANCES-DETTES') { // Now output columns for row $code ('VTE', 'MAR', ...) - print ""; + print ''; // Column group - print ''; // Label of group - print ''; print ''; From 13a19037dd8f3df460bfe735a4b533df2b275c9c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 17:23:56 +0100 Subject: [PATCH 131/816] NEW sort of column of custom group of account --- htdocs/accountancy/admin/categories.php | 41 +++++++++++++++++-------- htdocs/compta/resultat/result.php | 6 ++-- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/htdocs/accountancy/admin/categories.php b/htdocs/accountancy/admin/categories.php index 3414c36cd52..2a15921243f 100644 --- a/htdocs/accountancy/admin/categories.php +++ b/htdocs/accountancy/admin/categories.php @@ -45,6 +45,26 @@ if ($cat_id == 0) { $cat_id = null; } +// 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 < 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; +} +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +if (empty($sortfield)) { + $sortfield = 'account_number'; +} +if (empty($sortorder)) { + $sortorder = 'ASC'; +} + // Security check if (!$user->hasRight('accounting', 'chartofaccount')) { accessforbidden(); @@ -137,14 +157,6 @@ if (!empty($cat_id)) { if (is_array($accountingcategory->lines_cptbk) && count($accountingcategory->lines_cptbk) > 0) { print img_picto($langs->trans("AccountingAccount"), 'accounting_account', 'class="pictofixedwith"'); print $form->multiselectarray('cpt_bk', $arraykeyvalue, GETPOST('cpt_bk', 'array'), null, null, '', 0, "80%", '', '', $langs->transnoentitiesnoconv("AddAccountFromBookKeepingWithNoCategories")); - //print '
'; - /*print '
'; - print ajax_combobox('cpt_bk'); - */ print ' '; } } @@ -152,13 +164,16 @@ if (!empty($cat_id)) { print ''; -if ($action == 'display' || $action == 'delete') { +if ((empty($action) || $action == 'display' || $action == 'delete') && $cat_id > 0) { + $param = 'account_category='.((int) $cat_id); + print '
'; print '
'; + print ''; print dol_escape_htmltag($cat['code']); - print ''; + print ''; print dol_escape_htmltag($cat['label']); print '
'; + print ''; print dol_escape_htmltag($cat['code']); print ''; - print dol_escape_htmltag($cat['label']); + $labeltoshow = dol_escape_htmltag($cat['label']); if (count($cpts) > 0 && !empty($cpts[0])) { // Show example of 5 first accounting accounts $i = 0; foreach ($cpts as $cpt) { if ($i > 5) { - print '...)'; + $labeltoshow .= '...)'; break; } if ($i > 0) { - print ', '; + $labeltoshow .= ', '; } else { - print ' ('; + $labeltoshow .= ' ('; } - print dol_escape_htmltag($cpt['account_number']); + $labeltoshow .= dol_escape_htmltag($cpt['account_number']); $i++; } if ($i <= 5) { - print ')'; + $labeltoshow .= ')'; } } else { - print ' - '.$langs->trans("GroupIsEmptyCheckSetup").''; + $labeltoshow .= ' - '.$langs->trans("GroupIsEmptyCheckSetup").''; } + print ''; + print $labeltoshow; print ''.price($totCat['NP']).'
'."\n"; print ''; - print '"; - print '"; - print "\n"; + print getTitleFieldOfList('AccountAccounting', 0, $_SERVER['PHP_SELF'], 'account_number', '', $param, '', $sortfield, $sortorder, '')."\n"; + print getTitleFieldOfList('Label', 0, $_SERVER['PHP_SELF'], 'label', '', $param, '', $sortfield, $sortorder, '')."\n"; + print getTitleFieldOfList('', 0, $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, '')."\n"; + print ''."\n"; if (!empty($cat_id)) { $return = $accountingcategory->display($cat_id); // This load ->lines_display @@ -167,6 +182,8 @@ if ($action == 'display' || $action == 'delete') { } if (is_array($accountingcategory->lines_display) && count($accountingcategory->lines_display) > 0) { + $accountingcategory->lines_display = dol_sort_array($accountingcategory->lines_display, $sortfield, $sortorder, 1, 0, 1); + foreach ($accountingcategory->lines_display as $cpt) { print ''; print ''; diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index cb2158bb48b..4bbb20b18a1 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -322,7 +322,7 @@ if ($modecompta == 'CREANCES-DETTES') { // Year NP print ''; @@ -507,7 +507,7 @@ if ($modecompta == 'CREANCES-DETTES') { } else { $labeltoshow .= ' - '.$langs->trans("GroupIsEmptyCheckSetup").''; } - print ''; @@ -537,7 +537,7 @@ if ($modecompta == 'CREANCES-DETTES') { if ($showaccountdetail == 'all' || $resultN != 0) { print ''; print ''; - print ''; - print '
'; - print '
'.$langs->trans("AccountAccounting")."'.$langs->trans("Label")."
'.length_accountg($cpt->account_number).''; print dol_escape_htmltag($cat['code']); - print ''; + print ''; print dol_escape_htmltag($cat['label']); print ''; + print ''; print $labeltoshow; print '
'; + print ''; print '     '.length_accountg($cpt['account_number']); print ' - '; print $cpt['account_label']; From 429b38a2e64ef4cf753580ece0c63c9847df4518 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 17:45:40 +0100 Subject: [PATCH 132/816] Fix sort --- htdocs/accountancy/admin/categories_list.php | 38 ++++++++++++-------- htdocs/compta/resultat/result.php | 2 +- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/htdocs/accountancy/admin/categories_list.php b/htdocs/accountancy/admin/categories_list.php index 0e7bd908c9a..755a5a88aed 100644 --- a/htdocs/accountancy/admin/categories_list.php +++ b/htdocs/accountancy/admin/categories_list.php @@ -444,15 +444,37 @@ if ($search_country_id > 0) { if ($sortfield == 'country') { $sortfield = 'country_code'; } +if (empty($sortfield)) { + $sortfield = 'position'; +} + $sql .= $db->order($sortfield, $sortorder); $sql .= $db->plimit($listlimit + 1, $offset); //print $sql; $fieldlist = explode(',', $tabfield[$id]); +$param = '&id='.$id; +if ($search_country_id > 0) { + $param .= '&search_country_id='.urlencode($search_country_id); +} +$paramwithsearch = $param; +if ($sortorder) { + $paramwithsearch .= '&sortorder='.urlencode($sortorder); +} +if ($sortfield) { + $paramwithsearch .= '&sortfield='.urlencode($sortfield); +} +if (GETPOST('from', 'alpha')) { + $paramwithsearch .= '&from='.urlencode(GETPOST('from', 'alpha')); +} + print '
'; print ''; print ''; +print ''; +print ''; + print '
'; print ''; @@ -571,20 +593,6 @@ if ($resql) { $num = $db->num_rows($resql); $i = 0; - $param = '&id='.$id; - if ($search_country_id > 0) { - $param .= '&search_country_id='.urlencode($search_country_id); - } - $paramwithsearch = $param; - if ($sortorder) { - $paramwithsearch .= '&sortorder='.$sortorder; - } - if ($sortfield) { - $paramwithsearch .= '&sortfield='.$sortfield; - } - if (GETPOST('from', 'alpha')) { - $paramwithsearch .= '&from='.GETPOST('from', 'alpha'); - } // There is several pages if ($num > $listlimit) { print ''; + print ''; // Column group print ''; - - // Year N - $code = $cat['code']; // code of categorie ('VTE', 'MAR', ...) - $sommes[$code]['NP'] += $r; - - // Current fiscal year (N) - if (is_array($sommes) && !empty($sommes)) { - foreach ($sommes as $code => $det) { - $vars[$code] = $det['N']; - } - } - - $result = strtr($formula, $vars); - - //$r = $AccCat->calculate($result); - $r = dol_eval($result, 1, 1, 1); - - print ''; - $sommes[$code]['N'] += $r; - - // Detail by month - foreach ($months as $k => $v) { - if (($k + 1) >= $date_startmonth) { - foreach ($sommes as $code => $det) { - $vars[$code] = $det['M'][$k]; + if (preg_match('/[a-z]/i', $result)) { + $r = 'Error bad formula: '.$result; + $rshort = 'Err'; + print ''; + print ''; + // Detail by month + foreach ($months as $k => $v) { + if (($k + 1) >= $date_startmonth) { + print ''; } - $result = strtr($formula, $vars); - - //$r = $AccCat->calculate($result); - $r = dol_eval($result, 1, 1, 1); - - print ''; - $sommes[$code]['M'][$k] += $r; } - } - foreach ($months as $k => $v) { - if (($k + 1) < $date_startmonth) { - foreach ($sommes as $code => $det) { - $vars[$code] = $det['M'][$k]; + foreach ($months as $k => $v) { + if (($k + 1) < $date_startmonth) { + print ''; } - $result = strtr($formula, $vars); + } + } else { + //var_dump($result); + //$r = $AccCat->calculate($result); + $r = dol_eval($result, 1, 1, '1'); + //var_dump($r); - //$r = $AccCat->calculate($result); - $r = dol_eval($result, 1, 1, 1); + print ''; - print ''; - $sommes[$code]['M'][$k] += $r; + // Year N + $code = $cat['code']; // code of categorie ('VTE', 'MAR', ...) + $sommes[$code]['NP'] += $r; + + // Current fiscal year (N) + if (is_array($sommes) && !empty($sommes)) { + foreach ($sommes as $code => $det) { + $vars[$code] = $det['N']; + } + } + + $result = strtr($formula, $vars); + + //$r = $AccCat->calculate($result); + $r = dol_eval($result, 1, 1, 1); + + print ''; + $sommes[$code]['N'] += $r; + + // Detail by month + foreach ($months as $k => $v) { + if (($k + 1) >= $date_startmonth) { + foreach ($sommes as $code => $det) { + $vars[$code] = $det['M'][$k]; + } + $result = strtr($formula, $vars); + + //$r = $AccCat->calculate($result); + $r = dol_eval($result, 1, 1, 1); + + print ''; + $sommes[$code]['M'][$k] += $r; + } + } + + + foreach ($months as $k => $v) { + if (($k + 1) < $date_startmonth) { + foreach ($sommes as $code => $det) { + $vars[$code] = $det['M'][$k]; + } + $result = strtr($formula, $vars); + + //$r = $AccCat->calculate($result); + $r = dol_eval($result, 1, 1, 1); + + print ''; + $sommes[$code]['M'][$k] += $r; + } } } From bcd5c207cf7e57917116cac98091bc848891652d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 20:25:53 +0100 Subject: [PATCH 135/816] Debug v17 - Fix the report on custom groups, column previous period --- .../class/accountancycategory.class.php | 47 ++++-- htdocs/compta/resultat/result.php | 147 ++++++++---------- 2 files changed, 100 insertions(+), 94 deletions(-) diff --git a/htdocs/accountancy/class/accountancycategory.class.php b/htdocs/accountancy/class/accountancycategory.class.php index 68662ccb610..300ccff9c09 100644 --- a/htdocs/accountancy/class/accountancycategory.class.php +++ b/htdocs/accountancy/class/accountancycategory.class.php @@ -678,6 +678,22 @@ class AccountancyCategory // extends CommonObject $this->sdc = 0; $this->sdcpermonth = array(); + if (is_array($cpt)) { + $listofaccount = ''; + foreach ($cpt as $cptcursor) { + if (! is_null($cptcursor)) { + if ($listofaccount) { + $listofaccount .= ","; + } + $listofaccount .= "'".$cptcursor."'"; + } + } + if (empty($listofaccount)) { + // List of account is empty, so we do no try sql request, we can say result is empty. + return 0; + } + } + $sql = "SELECT SUM(t.debit) as debit, SUM(t.credit) as credit"; if (is_array($cpt)) { $sql .= ", t.numero_compte as accountancy_account"; @@ -686,13 +702,6 @@ class AccountancyCategory // extends CommonObject //if (in_array($this->db->type, array('mysql', 'mysqli'))) $sql.=' USE INDEX idx_accounting_bookkeeping_doc_date'; $sql .= " WHERE t.entity = ".$conf->entity; if (is_array($cpt)) { - $listofaccount = ''; - foreach ($cpt as $cptcursor) { - if ($listofaccount) { - $listofaccount .= ","; - } - $listofaccount .= "'".$cptcursor."'"; - } $sql .= " AND t.numero_compte IN (".$this->db->sanitize($listofaccount, 1).")"; } else { $sql .= " AND t.numero_compte = '".$this->db->escape($cpt)."'"; @@ -709,22 +718,28 @@ class AccountancyCategory // extends CommonObject if (is_array($cpt)) { $sql .= " GROUP BY t.numero_compte"; } - //print $sql; $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); if ($num) { - $obj = $this->db->fetch_object($resql); - if ($sens == 1) { - $this->sdc = $obj->debit - $obj->credit; - } else { - $this->sdc = $obj->credit - $obj->debit; - } - if (is_array($cpt)) { - $this->sdcperaccount[$obj->accountancy_account] = $this->sdc; + $i = 0; + while ($i < $num) { + $obj = $this->db->fetch_object($resql); + if ($obj) { + if ($sens == 1) { + $this->sdc = $obj->debit - $obj->credit; + } else { + $this->sdc = $obj->credit - $obj->debit; + } + if (is_array($cpt)) { + $this->sdcperaccount[$obj->accountancy_account] = $this->sdc; + } + } + $i++; } } + return $num; } else { $this->error = "Error ".$this->db->lasterror(); diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index 856eb8a5fe8..8615e595200 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -184,8 +184,8 @@ llxheader('', $langs->trans('ReportInOut')); $formaccounting = new FormAccounting($db); $form = new Form($db); -$textprevyear = ''.img_previous().''; -$textnextyear = ' '.img_next().''; +$textprevyear = ''.img_previous().''; +$textnextyear = '   '.img_next().''; @@ -309,8 +309,8 @@ if ($modecompta == 'CREANCES-DETTES') { if (!is_array($cats) && $cats < 0) { setEventMessages(null, $AccCat->errors, 'errors'); } elseif (is_array($cats) && count($cats) > 0) { + // Loop on each custom group of accounts foreach ($cats as $cat) { - // Loop on each group if (!empty($cat['category_type'])) { // category calculed // When we enter here, $sommes was filled by group of accounts @@ -319,10 +319,10 @@ if ($modecompta == 'CREANCES-DETTES') { print ''; - // Year NP - print ''; @@ -345,83 +345,71 @@ if ($modecompta == 'CREANCES-DETTES') { $r = 'Error bad formula: '.$result; $rshort = 'Err'; print ''; - print ''; - // Detail by month - foreach ($months as $k => $v) { - if (($k + 1) >= $date_startmonth) { - print ''; - } - } - foreach ($months as $k => $v) { - if (($k + 1) < $date_startmonth) { - print ''; - } - } } else { //var_dump($result); //$r = $AccCat->calculate($result); $r = dol_eval($result, 1, 1, '1'); - //var_dump($r); print ''; + } - // Year N - $code = $cat['code']; // code of categorie ('VTE', 'MAR', ...) - $sommes[$code]['NP'] += $r; + // Year N + $code = $cat['code']; // code of categorie ('VTE', 'MAR', ...) + $sommes[$code]['NP'] += $r; - // Current fiscal year (N) - if (is_array($sommes) && !empty($sommes)) { + // Current fiscal year (N) + if (is_array($sommes) && !empty($sommes)) { + foreach ($sommes as $code => $det) { + $vars[$code] = $det['N']; + } + } + + $result = strtr($formula, $vars); + $result = str_replace('--', '+', $result); + + //$r = $AccCat->calculate($result); + $r = dol_eval($result, 1, 1, '1'); + + print ''; + $sommes[$code]['N'] += $r; + + // Detail by month + foreach ($months as $k => $v) { + if (($k + 1) >= $date_startmonth) { foreach ($sommes as $code => $det) { - $vars[$code] = $det['N']; + $vars[$code] = $det['M'][$k]; } + $result = strtr($formula, $vars); + $result = str_replace('--', '+', $result); + + //$r = $AccCat->calculate($result); + $r = dol_eval($result, 1, 1, '1'); + + print ''; + $sommes[$code]['M'][$k] += $r; } + } - $result = strtr($formula, $vars); - - //$r = $AccCat->calculate($result); - $r = dol_eval($result, 1, 1, 1); - - print ''; - $sommes[$code]['N'] += $r; - - // Detail by month - foreach ($months as $k => $v) { - if (($k + 1) >= $date_startmonth) { - foreach ($sommes as $code => $det) { - $vars[$code] = $det['M'][$k]; - } - $result = strtr($formula, $vars); - - //$r = $AccCat->calculate($result); - $r = dol_eval($result, 1, 1, 1); - - print ''; - $sommes[$code]['M'][$k] += $r; + foreach ($months as $k => $v) { + if (($k + 1) < $date_startmonth) { + foreach ($sommes as $code => $det) { + $vars[$code] = $det['M'][$k]; } - } + $result = strtr($formula, $vars); + $result = str_replace('--', '+', $result); + //$r = $AccCat->calculate($result); + $r = dol_eval($result, 1, 1, '1'); - foreach ($months as $k => $v) { - if (($k + 1) < $date_startmonth) { - foreach ($sommes as $code => $det) { - $vars[$code] = $det['M'][$k]; - } - $result = strtr($formula, $vars); - - //$r = $AccCat->calculate($result); - $r = dol_eval($result, 1, 1, 1); - - print ''; - $sommes[$code]['M'][$k] += $r; - } + print ''; + $sommes[$code]['M'][$k] += $r; } } print "\n"; //var_dump($sommes); - } else // normal category - { + } else { // normal category $code = $cat['code']; // Category code we process $totCat = array(); @@ -435,23 +423,25 @@ if ($modecompta == 'CREANCES-DETTES') { // Set $cpts with array of accounts in the category/group $cpts = $AccCat->getCptsCat($cat['rowid']); // We should loop over empty $cpts array, else the category _code_ is used in the formula, which leads to wrong result if the code is a number. - if (empty($cpts)) $cpts[] = array(); - + if (empty($cpts)) { + $cpts[] = array(); + } $arrayofaccountforfilter = array(); foreach ($cpts as $i => $cpt) { // Loop on each account. - $arrayofaccountforfilter[] = $cpt['account_number']; + if (!is_null($cpt['account_number'])) { + $arrayofaccountforfilter[] = $cpt['account_number']; + } } // N-1 if (!empty($arrayofaccountforfilter)) { $return = $AccCat->getSumDebitCredit($arrayofaccountforfilter, $date_start_previous, $date_end_previous, $cat['dc'] ? $cat['dc'] : 0); - if ($return < 0) { setEventMessages(null, $AccCat->errors, 'errors'); $resultNP = 0; } else { - foreach ($cpts as $i => $cpt) { // Loop on each account. + foreach ($cpts as $i => $cpt) { // Loop on each account found $resultNP = empty($AccCat->sdcperaccount[$cpt['account_number']]) ? 0 : $AccCat->sdcperaccount[$cpt['account_number']]; $totCat['NP'] += $resultNP; @@ -499,37 +489,38 @@ if ($modecompta == 'CREANCES-DETTES') { // Now output columns for row $code ('VTE', 'MAR', ...) - print ""; + print ''; // Column group - print ''; // Label of group - print ''; print ''; @@ -558,7 +549,7 @@ if ($modecompta == 'CREANCES-DETTES') { if ($showaccountdetail == 'all' || $resultN != 0) { print ''; print ''; - print ''; @@ -370,7 +370,7 @@ if ($modecompta == 'CREANCES-DETTES') { //$r = $AccCat->calculate($result); $r = dol_eval($result, 1, 1, '1'); - print ''; + print ''; $sommes[$code]['N'] += $r; // Detail by month @@ -519,12 +519,12 @@ if ($modecompta == 'CREANCES-DETTES') { } else { $labeltoshow .= ' - '.$langs->trans("GroupIsEmptyCheckSetup").''; } - print ''; print ''; - print ''; + print ''; // Each month foreach ($totCat['M'] as $k => $v) { @@ -549,13 +549,13 @@ if ($modecompta == 'CREANCES-DETTES') { if ($showaccountdetail == 'all' || $resultN != 0) { print ''; print ''; - print ''; print ''; - print ''; + print ''; // Make one call for each month foreach ($months as $k => $v) { From 9d777497db1f0cc7729303dd8d6e059d89d4ed1d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 22:07:26 +0100 Subject: [PATCH 137/816] NEW dol_sort_array can sort on alphabetical order even if val is num --- htdocs/accountancy/admin/categories.php | 2 +- htdocs/core/lib/functions.lib.php | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/admin/categories.php b/htdocs/accountancy/admin/categories.php index 2a15921243f..7b660419daf 100644 --- a/htdocs/accountancy/admin/categories.php +++ b/htdocs/accountancy/admin/categories.php @@ -182,7 +182,7 @@ if ((empty($action) || $action == 'display' || $action == 'delete') && $cat_id > } if (is_array($accountingcategory->lines_display) && count($accountingcategory->lines_display) > 0) { - $accountingcategory->lines_display = dol_sort_array($accountingcategory->lines_display, $sortfield, $sortorder, 1, 0, 1); + $accountingcategory->lines_display = dol_sort_array($accountingcategory->lines_display, $sortfield, $sortorder, -1, 0, 1); foreach ($accountingcategory->lines_display as $cpt) { print ''; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index cc32224ff2b..85cb8a9cdfe 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8671,7 +8671,8 @@ function dol_htmloutput_errors($mesgstring = '', $mesgarray = array(), $keepembe * @param array $array Array to sort (array of array('key1'=>val1,'key2'=>val2,'key3'...) or array of objects) * @param string $index Key in array to use for sorting criteria * @param int $order Sort order ('asc' or 'desc') - * @param int $natsort 1=use "natural" sort (natsort) for a search criteria thats is strings or unknown, 0=use "standard" sort (asort) for numbers + * @param int $natsort If values are strings (I said value not type): 0=Use alphabetical order, 1=use "natural" sort (natsort) + * If values are numeric (I said value not type): 0=Use numeric order (even if type is string) so use a "natural" sort, 1=use "natural" sort too (same than 0), -1=Force alphabetical order * @param int $case_sensitive 1=sort is case sensitive, 0=not case sensitive * @param int $keepindex If 0 and index key of array to sort is a numeric, than index will be rewrote. If 1 or index key is not numeric, key for index is kept after sorting. * @return array Sorted array @@ -8691,9 +8692,12 @@ function dol_sort_array(&$array, $index, $order = 'asc', $natsort = 0, $case_sen } else { $temp[$key] = empty($array[$key][$index]) ? 0 : $array[$key][$index]; } + if ($natsort == -1) { + $temp[$key] = '___'.$temp[$key]; // We add a string at begin of value to force an alpha order when using asort. + } } - if (!$natsort) { + if (empty($natsort) || $natsort == -1) { if ($order == 'asc') { asort($temp); } else { From 400a1686873fbc06ea924e8c321f522f5c7e8c73 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 23:20:46 +0100 Subject: [PATCH 138/816] NEW Can modify the date of payment of a salary (if not reconciled) --- htdocs/compta/paiement/card.php | 11 +-- htdocs/compta/payment_sc/card.php | 12 +++- htdocs/salaries/class/paymentsalary.class.php | 68 +++++++++++++++++-- htdocs/salaries/paiement_salary.php | 2 +- htdocs/salaries/payment_salary/card.php | 37 +++++++--- 5 files changed, 105 insertions(+), 25 deletions(-) diff --git a/htdocs/compta/paiement/card.php b/htdocs/compta/paiement/card.php index cc39a790527..073365fa876 100644 --- a/htdocs/compta/paiement/card.php +++ b/htdocs/compta/paiement/card.php @@ -84,7 +84,7 @@ if ($action == 'setnote' && $user->hasRight('facture', 'paiement')) { } } -if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->facture->paiement) { +if ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('facture', 'paiement')) { $db->begin(); $result = $object->delete(); @@ -105,7 +105,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->facture-> } } -if ($action == 'confirm_validate' && $confirm == 'yes' && $user->rights->facture->paiement) { +if ($action == 'confirm_validate' && $confirm == 'yes' && $user->hasRight('facture', 'paiement')) { $db->begin(); if ($object->validate($user) > 0) { @@ -175,7 +175,7 @@ if ($action == 'confirm_validate' && $confirm == 'yes' && $user->rights->facture } } -if ($action == 'setnum_paiement' && GETPOST('num_paiement')) { +if ($action == 'setnum_paiement' && GETPOST('num_paiement') && $user->hasRight('facture', 'paiement')) { $res = $object->update_num(GETPOST('num_paiement')); if ($res === 0) { setEventMessages($langs->trans('PaymentNumberUpdateSucceeded'), null, 'mesgs'); @@ -184,7 +184,7 @@ if ($action == 'setnum_paiement' && GETPOST('num_paiement')) { } } -if ($action == 'setdatep' && GETPOST('datepday')) { +if ($action == 'setdatep' && GETPOST('datepday') && $user->hasRight('facture', 'paiement')) { $datepaye = dol_mktime(GETPOST('datephour', 'int'), GETPOST('datepmin', 'int'), GETPOST('datepsec', 'int'), GETPOST('datepmonth', 'int'), GETPOST('datepday', 'int'), GETPOST('datepyear', 'int')); $res = $object->update_date($datepaye); if ($res === 0) { @@ -193,7 +193,8 @@ if ($action == 'setdatep' && GETPOST('datepday')) { setEventMessages($langs->trans('PaymentDateUpdateFailed'), null, 'errors'); } } -if ($action == 'createbankpayment' && !empty($user->rights->facture->paiement)) { + +if ($action == 'createbankpayment' && $user->hasRight('facture', 'paiement')) { $db->begin(); // Create the record into bank for the amount of payment $object diff --git a/htdocs/compta/payment_sc/card.php b/htdocs/compta/payment_sc/card.php index 39bac75ba0c..7d7742c3f01 100644 --- a/htdocs/compta/payment_sc/card.php +++ b/htdocs/compta/payment_sc/card.php @@ -63,7 +63,7 @@ if ($id > 0) { */ // Delete payment -if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->tax->charges->supprimer) { +if ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('tax', 'charges', 'supprimer')) { $db->begin(); $result = $object->delete($user); @@ -77,6 +77,16 @@ if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->tax->char } } +if ($action == 'setdatep' && GETPOST('datepday') && $user->hasRight('tax', 'charges', 'creer')) { + $datepaye = dol_mktime(GETPOST('datephour', 'int'), GETPOST('datepmin', 'int'), GETPOST('datepsec', 'int'), GETPOST('datepmonth', 'int'), GETPOST('datepday', 'int'), GETPOST('datepyear', 'int')); + $res = $object->update_date($datepaye); + if ($res === 0) { + setEventMessages($langs->trans('PaymentDateUpdateSucceeded'), null, 'mesgs'); + } else { + setEventMessages($langs->trans('PaymentDateUpdateFailed'), null, 'errors'); + } +} + /* * View diff --git a/htdocs/salaries/class/paymentsalary.class.php b/htdocs/salaries/class/paymentsalary.class.php index 029e5732f9b..a2de50aeed4 100644 --- a/htdocs/salaries/class/paymentsalary.class.php +++ b/htdocs/salaries/class/paymentsalary.class.php @@ -602,12 +602,66 @@ class PaymentSalary extends CommonObject } } + /** + * Updates the payment date. + * Old name of function is update_date() + * + * @param int $date New date + * @return int <0 if KO, 0 if OK + */ + public function updatePaymentDate($date) + { + $error = 0; + + if (!empty($date)) { + $this->db->begin(); + + dol_syslog(get_class($this)."::updatePaymentDate with date = ".$date, LOG_DEBUG); + + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET datep = '".$this->db->idate($date)."'"; + $sql .= " WHERE rowid = ".((int) $this->id); + + $result = $this->db->query($sql); + if (!$result) { + $error++; + $this->error = 'Error -1 '.$this->db->error(); + } + + $type = $this->element; + + $sql = "UPDATE ".MAIN_DB_PREFIX.'bank'; + $sql .= " SET dateo = '".$this->db->idate($date)."', datev = '".$this->db->idate($date)."'"; + $sql .= " WHERE rowid IN (SELECT fk_bank FROM ".MAIN_DB_PREFIX."bank_url WHERE type = '".$this->db->escape($type)."' AND url_id = ".((int) $this->id).")"; + $sql .= " AND rappro = 0"; + + $result = $this->db->query($sql); + if (!$result) { + $error++; + $this->error = 'Error -1 '.$this->db->error(); + } + + if (!$error) { + } + + if (!$error) { + $this->datep = $date; + + $this->db->commit(); + return 0; + } else { + $this->db->rollback(); + return -2; + } + } + return -1; //no date given or already validated + } /** - * Retourne le libelle du statut d'une facture (brouillon, validee, abandonnee, payee) + * Return the label of the status * - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto - * @return string Libelle + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status */ public function getLibStatut($mode = 0) { @@ -616,11 +670,11 @@ class PaymentSalary extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Renvoi le libelle d'un statut donne + * Return the status * - * @param int $status Statut - * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto - * @return string Libelle du statut + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status */ public function LibStatut($status, $mode = 0) { diff --git a/htdocs/salaries/paiement_salary.php b/htdocs/salaries/paiement_salary.php index 30279ee3538..9f90e4c9ac9 100644 --- a/htdocs/salaries/paiement_salary.php +++ b/htdocs/salaries/paiement_salary.php @@ -57,7 +57,7 @@ restrictedArea($user, 'salaries', $object->id, 'salary', ''); * Actions */ -if ($action == 'add_payment' || ($action == 'confirm_paiement' && $confirm == 'yes')) { +if (($action == 'add_payment' || ($action == 'confirm_paiement' && $confirm == 'yes')) && $user->hasRight('salaries', 'write')) { $error = 0; if ($cancel) { diff --git a/htdocs/salaries/payment_salary/card.php b/htdocs/salaries/payment_salary/card.php index c9f0a151901..c6d73c5ec7f 100644 --- a/htdocs/salaries/payment_salary/card.php +++ b/htdocs/salaries/payment_salary/card.php @@ -20,10 +20,10 @@ */ /** - * \file htdocs/compta/payment_sc/card.php - * \ingroup facture - * \brief Onglet payment of a salary - * \remarks Fichier presque identique a fournisseur/paiement/card.php + * \file htdocs/salaries/payment_salary/card.php + * \ingroup salary + * \brief Tab to pay a salary + * \remarks File very similar with fournisseur/paiement/card.php */ // Load Dolibarr environment @@ -56,7 +56,7 @@ restrictedArea($user, 'salaries', $object->fk_salary, 'salary', ''); // $object */ // Delete payment -if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->salaries->delete) { +if ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('salaries', 'delete')) { $db->begin(); $result = $object->delete($user); @@ -70,6 +70,16 @@ if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->salaries- } } +if ($action == 'setdatep' && GETPOST('datepday') && $user->hasRight('salaries', 'write')) { + $datepaye = dol_mktime(GETPOST('datephour', 'int'), GETPOST('datepmin', 'int'), GETPOST('datepsec', 'int'), GETPOST('datepmonth', 'int'), GETPOST('datepday', 'int'), GETPOST('datepyear', 'int'), 'tzuserrel'); + $res = $object->updatePaymentDate($datepaye); + if ($res === 0) { + setEventMessages($langs->trans('PaymentDateUpdateSucceeded'), null, 'mesgs'); + } else { + setEventMessages($langs->trans('PaymentDateUpdateFailed'), null, 'errors'); + } +} + /* * View @@ -127,7 +137,7 @@ dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'id', ''); print '
'; print '
'; -print '
'; @@ -822,7 +830,7 @@ if ($resql) { } // Link to setup the group - print ''; + print ''; if (empty($obj->formula)) { print ''; print $langs->trans("ListOfAccounts"); diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index 4bbb20b18a1..07a82fc92ac 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -477,7 +477,7 @@ if ($modecompta == 'CREANCES-DETTES') { // Now output columns for row $code ('VTE', 'MAR', ...) - print '
'; From 6db9425657e51e27c23a31066e71bc7bc7d058c0 Mon Sep 17 00:00:00 2001 From: Fabrice Mouhartem Date: Thu, 29 Dec 2022 17:54:15 +0100 Subject: [PATCH 133/816] Fixed some grammar in the French error translation file --- htdocs/langs/fr_FR/errors.lang | 85 ++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/htdocs/langs/fr_FR/errors.lang b/htdocs/langs/fr_FR/errors.lang index d407d7c91b8..0a2cde05bb8 100644 --- a/htdocs/langs/fr_FR/errors.lang +++ b/htdocs/langs/fr_FR/errors.lang @@ -14,6 +14,7 @@ ErrorLoginAlreadyExists=L'identifiant %s existe déjà. ErrorGroupAlreadyExists=Le groupe %s existe déjà. ErrorEmailAlreadyExists=L'e-mail %s existe déjà. ErrorRecordNotFound=Enregistrement non trouvé. +ErrorRecordNotFoundShort=Non trouvé ErrorFailToCopyFile=Echec de la copie du fichier '%s' en '%s'. ErrorFailToCopyDir=Echec de copie du répertoire '%s' vers '%s'. ErrorFailToRenameFile=Echec du renommage du fichier '%s' en '%s'. @@ -32,28 +33,28 @@ ForbiddenBySetupRules=Interdit par les règles de configuration ErrorProdIdIsMandatory=Le %s est obligatoire ErrorAccountancyCodeCustomerIsMandatory=Le code comptable du client %s est obligatoire ErrorBadCustomerCodeSyntax=La syntaxe du code client est incorrecte -ErrorBadBarCodeSyntax=Mauvaise syntaxe pour le code barre. Peut être que vous avez défini un mauvais type de code-barres ou que vous avez défini un masque de code à barres pour la numérotation qui ne correspond pas à la valeur scannée. +ErrorBadBarCodeSyntax=Mauvaise syntaxe pour le code-barres. Peut être que vous avez défini un mauvais type de code-barres ou que vous avez défini un masque de code à barres pour la numérotation qui ne correspond pas à la valeur scannée. ErrorCustomerCodeRequired=Code client obligatoire -ErrorBarCodeRequired=Code-barre requis +ErrorBarCodeRequired=Code-barres requis ErrorCustomerCodeAlreadyUsed=Code client déjà utilisé -ErrorBarCodeAlreadyUsed=Code-barre déjà utilisé -ErrorPrefixRequired=Préfix obligatoire +ErrorBarCodeAlreadyUsed=Code-barres déjà utilisé +ErrorPrefixRequired=Préfixe obligatoire ErrorBadSupplierCodeSyntax=Mauvaise syntaxe pour le code fournisseur ErrorSupplierCodeRequired=Code fournisseur obligatoire ErrorSupplierCodeAlreadyUsed=Code fournisseur déjà utilisé ErrorBadParameters=Paramètres incorrects ErrorWrongParameters=Paramètres incorrects ou manquants ErrorBadValueForParameter=Valeur '%s' incorrecte pour le paramètre '%s' -ErrorBadImageFormat=Cet image est dans un format non pris en charge (Votre PHP ne prend pas en charge les fonctions de conversion de ce format d'image). +ErrorBadImageFormat=Cette image est dans un format non pris en charge (Votre PHP ne prend pas en charge les fonctions de conversion de ce format d'image). ErrorBadDateFormat=La valeur '%s' a un format de date non reconnu -ErrorWrongDate=La date est incorrecte +ErrorWrongDate=La date est incorrecte ! ErrorFailedToWriteInDir=Impossible d'écrire dans le répertoire %s ErrorFailedToBuildArchive=Échec de la création du fichier d'archive %s ErrorFoundBadEmailInFile=Syntaxe d'email incorrecte trouvée pour %s lignes dans le fichier (exemple ligne %s avec email=%s) ErrorUserCannotBeDelete=L'utilisateur ne peut pas être supprimé. Peut-être est-il associé à des éléments de Dolibarr. ErrorFieldsRequired=Des champs obligatoire n'ont pas été remplis. ErrorSubjectIsRequired=L'objet de l'e-mail est obligatoire -ErrorFailedToCreateDir=Echec à la création d'un répertoire. Vérifiez que le user du serveur Web ait bien les droits d'écriture dans les répertoires documents de Dolibarr. Si le paramètre safe_mode a été activé sur ce PHP, vérifiez que les fichiers php dolibarr appartiennent à l'utilisateur du serveur Web. +ErrorFailedToCreateDir=Echec à la création d'un répertoire. Vérifiez que l'utilisateur du serveur Web ait bien les droits d'écriture dans les répertoires documents de Dolibarr. Si le paramètre safe_mode a été activé sur ce PHP, vérifiez que les fichiers php dolibarr appartiennent à l'utilisateur du serveur Web. ErrorNoMailDefinedForThisUser=Email non défini pour cet utilisateur ErrorSetupOfEmailsNotComplete=La configuration de l'envoi des e-mails n'est pas terminée ErrorFeatureNeedJavascript=Cette fonctionnalité a besoin de javascript activé pour fonctionner. Modifiez dans configuration - affichage. @@ -65,7 +66,7 @@ ErrorFunctionNotAvailableInPHP=La fonction %s est requise pour cette fonc ErrorDirAlreadyExists=Un répertoire portant ce nom existe déjà. ErrorFileAlreadyExists=Un fichier portant ce nom existe déjà. ErrorDestinationAlreadyExists=Un fichier portant le nom %s existe déjà. -ErrorPartialFile=Fichier non reçu intégralement par le serveur. +ErrorPartialFile=Fichier incomplet reçu par le serveur. ErrorNoTmpDir=Répertoire temporaire de réception %s inexistant. ErrorUploadBlockedByAddon=Upload bloqué par un plugin PHP/Apache. ErrorFileSizeTooLarge=La taille du fichier est trop grande ou le fichier n'est pas fourni. @@ -96,6 +97,7 @@ ErrorWrongValueForField=Champ %s: '%s' ne respecte pas la règle < ErrorHtmlInjectionForField=Champ %s : La valeur ' %s ' contient une donnée malveillante non autorisée ErrorFieldValueNotIn=Champ %s: '%s' n'est pas une valeur disponible dans le champ %s de la table %s ErrorFieldRefNotIn=Champ %s: '%s' n'est pas une référence existante comme %s +ErrorMultipleRecordFoundFromRef=Plusieurs enregistrements ont été trouvés en recherchant la référence %s. Il nous est impossible de déterminer quel ID utiliser. ErrorsOnXLines=Erreurs sur %s enregistrement(s) source ErrorFileIsInfectedWithAVirus=L'antivirus n'a pas pu valider ce fichier (il est probablement infecté par un virus) ! ErrorNumRefModel=Une référence existe en base (%s) et est incompatible avec cette numérotation. Supprimez la ligne ou renommez la référence pour activer ce module. @@ -106,7 +108,7 @@ ErrorBadMask=Erreur sur le masque ErrorBadMaskFailedToLocatePosOfSequence=Erreur, masque sans numéro de séquence ErrorBadMaskBadRazMonth=Erreur, mauvais valeur de remise à zéro ErrorMaxNumberReachForThisMask=Nombre maximum atteint pour ce masque -ErrorCounterMustHaveMoreThan3Digits=Le compteur doit avoir au moins 3 positions +ErrorCounterMustHaveMoreThan3Digits=Le compteur doit posséder au moins 3 chiffres ErrorSelectAtLeastOne=Erreur, sélectionnez au moins une entrée. ErrorDeleteNotPossibleLineIsConsolidated=Suppression impossible car l'enregistrement porte sur au moins une transaction bancaire rapprochée ErrorProdIdAlreadyExist=%s est attribué à un autre tiers @@ -130,9 +132,9 @@ ErrorLoginHasNoEmail=Cet utilisateur n'a pas d'email. Impossible de continuer. ErrorBadValueForCode=Mauvaise valeur saisie pour le code. Réessayez avec une nouvelle valeur... ErrorBothFieldCantBeNegative=Les champs %s et %s ne peuvent être tous deux négatifs ErrorFieldCantBeNegativeOnInvoice=Le champ %s ne peut pas être négatif sur ce type de facture. Si vous devez ajouter une ligne de remise, créez d'abord la remise (à partir du champ '%s' dans la fiche du tiers) et appliquez-la à la facture. -ErrorLinesCantBeNegativeForOneVATRate=Le total des lignes (HT) ne peut pas être négatif pour un taux de TVA non null donné (Un total négatif pour le taux de %s%% a été trouvé). +ErrorLinesCantBeNegativeForOneVATRate=Le total des lignes (HT) ne peut pas être négatif pour un taux de TVA non nul donné (Un total négatif pour le taux de %s%% a été trouvé). ErrorLinesCantBeNegativeOnDeposits=Les lignes ne peuvent pas être négatives dans un acompte. Si vous le faites, vous rencontrerez des problèmes lorsque vous devrez consommer l'acompte dans la facture finale. -ErrorQtyForCustomerInvoiceCantBeNegative=La quantité d'une ligne ne peut pas être négative dans les factures clients +ErrorQtyForCustomerInvoiceCantBeNegative=La quantité d'une ligne ne peut pas être négative dans les factures clients ErrorWebServerUserHasNotPermission=Le compte d'exécution du serveur web %s n'a pas les permissions pour cela ErrorNoActivatedBarcode=Aucun type de code-barres activé ErrUnzipFails=Impossible de décompresser le fichier %s avec ZipArchive @@ -152,8 +154,8 @@ ErrorPaymentModeDefinedToWithoutSetup=Un mode de paiement a été défini de typ ErrorPHPNeedModule=Erreur, votre PHP doit avoir le module %s installé pour utiliser cette fonctionnalité. ErrorOpenIDSetupNotComplete=Vous avez configuré Dolibarr pour accepter l'authentication OpenID, mais l'URL du service OpenID n'est pas défini dans la constante %s ErrorWarehouseMustDiffers=Les entrepôts source et destination doivent être différents -ErrorBadFormat=Mauvais format -ErrorMemberNotLinkedToAThirpartyLinkOrCreateFirst=Erreur, cet adhérent n'ait pas encore lié à un tiers. Lier le tier à un tiers existant ou créer un nouveau tiers avant de créer une adhésion avec facture. +ErrorBadFormat=Mauvais format ! +ErrorMemberNotLinkedToAThirpartyLinkOrCreateFirst=Erreur, cet adhérent n'est pas encore lié à un tiers. Liez le tiers à un tiers existant ou créez un nouveau tiers avant de créer une adhésion avec facture. ErrorThereIsSomeDeliveries=Erreur, il y a des bordereaux de réception liées à ces expéditions. La suppression est refusée. ErrorCantDeletePaymentReconciliated=Impossible d'effacer un paiement qui a généré une écriture sur le compte bancaire et qui a été rapprochée. ErrorCantDeletePaymentSharedWithPayedInvoice=Impossible d'effacer un paiement qui porte sur au moins une facture qui est à l'état payée. @@ -161,11 +163,11 @@ ErrorPriceExpression1=Ne peut assigner la constante '%s' ErrorPriceExpression2=Ne peut redéfinir la fonction '%s' ErrorPriceExpression3=Variable '%s' non définie dans la définition de fonction ErrorPriceExpression4=Caractère illégal '%s' -ErrorPriceExpression5=Unexpected '%s' +ErrorPriceExpression5='%s' inattendu. ErrorPriceExpression6=Nombre incorrect d'arguments (%s donné,%s attendu) ErrorPriceExpression8=Operateur '%s' non attendu ErrorPriceExpression9=Une erreur inattendue s'est produite -ErrorPriceExpression10=Il manque l'opérande à l'opérateur '%s' +ErrorPriceExpression10=Il manque l'opérande à l'opérateur '%s' ErrorPriceExpression11=Attendu '%s' ErrorPriceExpression14=Division par zéro ErrorPriceExpression17=Variable '%s' non définie @@ -187,16 +189,16 @@ ErrorGlobalVariableUpdater2=Paramètre manquant '%s' ErrorGlobalVariableUpdater3=La donnée recherché n'a pas été trouvée ErrorGlobalVariableUpdater4=Le client SOAP a échoué avec l'erreur '%s' ErrorGlobalVariableUpdater5=Pas de variable globale -ErrorFieldMustBeANumeric=Le champ %s doit être un numérique -ErrorMandatoryParametersNotProvided=Paramètre(s) obligatoire(s) non fournis -ErrorOppStatusRequiredIfAmount=Vous avez fixé un montant estimé pour cette opportunité. Aussi, vous devez également entrer son statut +ErrorFieldMustBeANumeric=Le champ %s doit être une valeur numérique +ErrorMandatoryParametersNotProvided=Paramètre(s) obligatoire(s) non fourni(s) +ErrorOppStatusRequiredIfAmount=Vous avez fixé un montant estimé pour cette opportunité. De plus, vous devez également entrer son statut ErrorFailedToLoadModuleDescriptorForXXX=Échec de changement de la classe descripteur du module %s ErrorBadDefinitionOfMenuArrayInModuleDescriptor=Mauvaise définition du tableau Menu dans le descripteur de module (mauvaise valeur pour la clé fk_menu) ErrorSavingChanges=Une erreur est survenue lors de la sauvegarde des modifications ErrorWarehouseRequiredIntoShipmentLine=L'entrepôt est requis sur la ligne de l'expédition ErrorFileMustHaveFormat=Le fichier doit avoir le format %s ErrorFilenameCantStartWithDot=Le nom de fichier ne peut pas commencer par un '.' -ErrorSupplierCountryIsNotDefined=Le pays pour ce fournisseur n'est pas défini. Corriger cela. +ErrorSupplierCountryIsNotDefined=Le pays pour ce fournisseur n'est pas défini. Corrigez cela. ErrorsThirdpartyMerge=Echec de la fusion de 2 enregistrements. Demande annulée. ErrorStockIsNotEnoughToAddProductOnOrder=Le stock du produit %s est insuffisant pour permettre un ajout dans une nouvelle commande. ErrorStockIsNotEnoughToAddProductOnInvoice=Le stock du produit %s est insuffisant pour permettre un ajout dans une nouvelle facture. @@ -214,7 +216,7 @@ ErrorTaskAlreadyAssigned=Tâche déjà assignée à l'utilisateur ErrorModuleFileSeemsToHaveAWrongFormat=Le package du module semble avoir un mauvais format. ErrorModuleFileSeemsToHaveAWrongFormat2=Au moins un dossier obligatoire doit être présent dans l'archive zip du module : %s ou %s ErrorFilenameDosNotMatchDolibarrPackageRules=Le nom du package du module (%s) ne correspond pas à la syntaxe attendue: %s -ErrorDuplicateTrigger=Erreur, doublon du trigger nommé %s. Déjà chargé à partir de %s. +ErrorDuplicateTrigger=Erreur, doublon du déclencheur nommé %s. Déjà chargé à partir de %s. ErrorNoWarehouseDefined=Erreur, aucun entrepôts défini. ErrorBadLinkSourceSetButBadValueForRef=Le lien que vous utilisez n'est pas valide. Une 'source' pour le paiement est définie, mais la valeur pour 'ref' n'est pas valide. ErrorTooManyErrorsProcessStopped=Trop d'erreurs, Le processus a été arrêté. @@ -223,12 +225,12 @@ ErrorObjectMustHaveStatusDraftToBeValidated=L'objet %s doit être au statut 'Bro ErrorObjectMustHaveLinesToBeValidated=L'objet %s doit contenir des lignes ErrorOnlyInvoiceValidatedCanBeSentInMassAction=Seules les factures validées peuvent être envoyées à l'aide de l'action de masse "Envoyer par courrier électronique". ErrorChooseBetweenFreeEntryOrPredefinedProduct=Vous devez choisir si l'article est un produit prédéfini ou non -ErrorDiscountLargerThanRemainToPaySplitItBefore=La réduction que vous essayez d'appliquer est supérieure au montant du paiement. Auparavant, divisez le rabais en 2 rabais plus petits. +ErrorDiscountLargerThanRemainToPaySplitItBefore=La réduction que vous essayez d'appliquer est supérieure au montant du paiement. Auparavant, divisez la remise en 2 rabais plus petits. ErrorFileNotFoundWithSharedLink=Fichier non trouvé. Peut être que la clé de partage a été modifiée ou le fichier a été récemment supprimé. -ErrorProductBarCodeAlreadyExists=Le code-barre du produit %s existe déjà sur une autre référence de produit +ErrorProductBarCodeAlreadyExists=Le code-barres du produit %s existe déjà sur une autre référence de produit ErrorNoteAlsoThatSubProductCantBeFollowedByLot=Notez également que l'utilisation d'un kit pour augmenter ou réduire automatiquement les sous-produits n'est pas possible lorsqu'au moins un sous-produit (ou sous-produit de sous-produits) a besoin d'un numéro de série/lot. ErrorDescRequiredForFreeProductLines=La description est obligatoire pour les lignes avec un produit non prédéfini -ErrorAPageWithThisNameOrAliasAlreadyExists=La page / container %s a le même nom ou un autre alias que celui que vous tentez d'utiliser. +ErrorAPageWithThisNameOrAliasAlreadyExists=La page/container %s a le même nom ou un autre alias que celui que vous tentez d'utiliser. ErrorDuringChartLoad=Erreur lors du chargement du tableau de compte. Si certains comptes n'ont pas été chargés, vous pouvez toujours les entrer manuellement. ErrorBadSyntaxForParamKeyForContent=Mauvaise syntaxe pour le paramètre keyforcontent. La valeur doit commencer par %s ou %s ErrorVariableKeyForContentMustBeSet=Erreur, la constante nommée %s (avec le contenu de texte à afficher) ou %s (avec l'adresse externe à afficher) doit être fixée. @@ -237,11 +239,12 @@ ErrorURLMustStartWithHttp=L'URL %s doit commencer par http:// ou https:// ErrorHostMustNotStartWithHttp=L'URL %s ne doit PAS commencer par http:// ou https:// ErrorNewRefIsAlreadyUsed=Erreur, la nouvelle référence est déjà utilisée ErrorDeletePaymentLinkedToAClosedInvoiceNotPossible=Erreur, supprimer le paiement lié à une facture clôturée n'est pas possible. -ErrorSearchCriteriaTooSmall=Critère de recherche trop petit. -ErrorObjectMustHaveStatusActiveToBeDisabled=Les objets doivent avoir le statut 'Actif' pour être désactivés -ErrorObjectMustHaveStatusDraftOrDisabledToBeActivated=Les objets doivent avoir le statut 'Brouillon' ou 'Désactivé' pour être activés +ErrorSearchCriteriaTooSmall=Critère de recherche trop court. +ErrorObjectMustHaveStatusActiveToBeDisabled=Les objets doivent avoir le statut 'Actif' pour pouvoir être désactivés +ErrorObjectMustHaveStatusDraftOrDisabledToBeActivated=Les objets doivent avoir le statut 'Brouillon' ou 'Désactivé' pour pouvoir être activés ErrorNoFieldWithAttributeShowoncombobox=Aucun champ n'a la propriété 'showoncombobox' dans la définition de l'objet '%s'. Pas moyen d'afficher la liste de cases à cocher ErrorFieldRequiredForProduct=Le champ '%s' est obligatoire pour le produit %s +AlreadyTooMuchPostOnThisIPAdress=Trop de requêtes ont déjà été envoyées depuis cette adresse IP. ProblemIsInSetupOfTerminal=Le problème est dans la configuration du terminal %s. ErrorAddAtLeastOneLineFirst=Ajouter d'abord au moins une ligne ErrorRecordAlreadyInAccountingDeletionNotPossible=Erreur, l'enregistrement est déjà transféré dans la comptabilité, la suppression n'est pas possible. @@ -283,7 +286,7 @@ ErrorNotApproverForHoliday=Vous n'êtes pas l'approbateur du congé %s ErrorAttributeIsUsedIntoProduct=Cet attribut est utilisé dans une ou plusieurs variantes de produit ErrorAttributeValueIsUsedIntoProduct=Cette valeur d'attribut est utilisée dans une ou plusieurs variantes de produit ErrorPaymentInBothCurrency=Erreur, tous les montants doivent être entrés dans la même colonne. -ErrorYouTryToPayInvoicesInACurrencyFromBankWithAnotherCurrency=Vous essayez de payer une facture en monnaie %s depuis un compte en %s +ErrorYouTryToPayInvoicesInACurrencyFromBankWithAnotherCurrency=Vous essayez de payer une facture en devise %s depuis un compte en %s ErrorInvoiceLoadThirdParty=Impossible de charger l'objet tiers pour la facture "%s" ErrorInvoiceLoadThirdPartyKey=Clé tiers "%s" non définie pour la facture "%s" ErrorDeleteLineNotAllowedByObjectStatus=Supprimer une ligne n'est pas autorisée par l'état actuel de l'objet @@ -298,10 +301,12 @@ ErrorCharPlusNotSupportedByImapForSearch=La recherche IMAP n'est pas en mesure d ErrorTableNotFound=Table %s introuvable ErrorValueForTooLow=La valeur pour %s est trop faible ErrorValueCantBeNull=La valeur pour %s ne peut pas être nulle +ErrorDateOfMovementLowerThanDateOfFileTransmission=La date de la transaction bancaire ne peut êtse inférieure à la date d'envoi du fichier +ErrorTooMuchFileInForm=Trop de fichier dans ce formulaire. Le nombre maximal de fichier est de %s fichier(s) # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Votre paramètre PHP upload_max_filesize (%s) est supérieur au paramètre PHP post_max_size (%s). Ceci n'est pas une configuration cohérente. -WarningPasswordSetWithNoAccount=Un mot de passe a été fixé pour cet adhérent. Cependant, aucun compte d'utilisateur n'a été créé. Donc, ce mot de passe est stocké, mais ne peut être utilisé pour accéder à Dolibarr. Il peut être utilisé par un module/interface externe, mais si vous n'avez pas besoin de définir ni login ni mot de passe pour un adhérent, vous pouvez désactiver l'option «Gérer un login pour chaque adhérent" depuis la configuration du module Adhérents. Si vous avez besoin de gérer un login, mais pas de mot de passe, vous pouvez laisser ce champ vide pour éviter cet avertissement. Remarque: L'email peut également être utilisé comme login si l'adhérent est lié à un utilisateur. +WarningPasswordSetWithNoAccount=Un mot de passe a défini pour cet adhérent. Cependant, aucun compte d'utilisateur n'a été créé. Ce mot de passe a donc été stocké, mais ne peut être utilisé pour accéder à Dolibarr. Il peut être utilisé par un module/interface externe, mais si vous n'avez pas besoin de définir ni login ni mot de passe pour un adhérent, vous pouvez désactiver l'option «Gérer un login pour chaque adhérent" depuis la configuration du module Adhérents. Si vous avez besoin de gérer un login, mais pas de mot de passe, vous pouvez laisser ce champ vide pour éviter cet avertissement. Remarque: L'email peut également être utilisé comme login si l'adhérent est lié à un utilisateur. WarningMandatorySetupNotComplete=Cliquez ici pour configurer les paramètres principaux WarningEnableYourModulesApplications=Cliquez ici pour activer vos modules et applications WarningSafeModeOnCheckExecDir=Attention, l'option PHP safe_mode est active, la commande doit dont être dans un répertoire déclaré dans le paramètre php safe_mode_exec_dir. @@ -315,11 +320,11 @@ WarningUntilDirRemoved=Les alertes de sécurité sont visibles par les administr WarningCloseAlways=Attention, la fermeture se fait même lorsque le montant diffère. N'activez cette fonctionnalité qu'en connaissance de cause. WarningUsingThisBoxSlowDown=Attention, l'utilisation de cette boîte provoque de sérieux ralentissements des pages affichant cette boîte. WarningClickToDialUserSetupNotComplete=La configuration ClickToDial pour votre compte utilisateur n'est pas complète (voir l'onglet ClickToDial sur votre fiche utilisateur) -WarningFeatureDisabledWithDisplayOptimizedForBlindNoJs=Fonction désactivée quand l'affichage est en mode optimisé pour les personnes aveugles ou les navigateurs textes. +WarningFeatureDisabledWithDisplayOptimizedForBlindNoJs=Fonction désactivée quand l'affichage est en mode optimisé pour les personnes malvoyantes ou les navigateurs textes. WarningPaymentDateLowerThanInvoiceDate=La date de paiement (%s) est inférieure à la date de facturation (%s) de la facture %s. WarningTooManyDataPleaseUseMoreFilters=Trop de données (plus de %s lignes). Utilisez davantage de filtres ou régler la constante %s pour augmenter la limite à une valeur plus élevée. WarningSomeLinesWithNullHourlyRate=Des temps ont été enregistrés par des utilisateurs lorsque leur taux horaire n'était défini. Une valeur de 0 %s a été utilisée, mais cela peut entraîner une mauvaise évaluation du temps passé. -WarningYourLoginWasModifiedPleaseLogin=Votre identifiant a été modifié. Par sécurité, vous devrez vous identifier avec votre nouvel identifiant avant l'action suivante. +WarningYourLoginWasModifiedPleaseLogin=Votre identifiant a été modifié. Par sécurité, vous devrez vous identifier avec votre nouvel identifiant avant la prochaine action. WarningAnEntryAlreadyExistForTransKey=Une donnée identique existe déjà pour la traduction du code dans cette langue WarningNumberOfRecipientIsRestrictedInMassAction=Attention, le nombre de destinataires différents est limité à %s lorsque vous utilisez les actions en masse sur les listes WarningDateOfLineMustBeInExpenseReportRange=Attention, la date de la ligne n'est pas dans la plage de la note de frais @@ -338,20 +343,20 @@ WarningAutoValNotPossibleWhenStockIsDecreasedOnInvoiceVal=La validation automati # Validate RequireValidValue = Valeur non valide -RequireAtLeastXString = Requiert au moins %s caractère(s) -RequireXStringMax = Requiert %s caractère(s) maximum -RequireAtLeastXDigits = Requiert au moins %s caractère(s) -RequireXDigitsMax = Requiert %scaractère(s) maximum +RequireAtLeastXString = Nécessite au moins %s caractère(s) +RequireXStringMax = Nécessite %s caractère(s) maximum +RequireAtLeastXDigits = Nécessite au moins %s caractère(s) +RequireXDigitsMax = Nécessite %scaractère(s) maximum RequireValidNumeric = Nécessite une valeur numérique RequireValidEmail = L'adresse email n'est pas valide RequireMaxLength = La longueur doit être inférieure à %s caractères RequireMinLength = La longueur doit être supérieure à %s caractère(s) -RequireValidUrl = Une URL valide est requise -RequireValidDate = Date valide requise -RequireANotEmptyValue = Est requis -RequireValidDuration = Une durée valide est requise -RequireValidExistingElement = Une valeur existante est requise -RequireValidBool = Un booléen valide est requis +RequireValidUrl = Une URL valide est demandée +RequireValidDate = Une date valide est nécessaire +RequireANotEmptyValue = Est nécessaire +RequireValidDuration = Une durée valide est nécessaire +RequireValidExistingElement = Une valeur existante est nécessaire +RequireValidBool = Un booléen valide est nécessaire BadSetupOfField = Erreur mauvaise configuration du champ BadSetupOfFieldClassNotFoundForValidation = Erreur mauvaise configuration du champ : Classe introuvable pour validation BadSetupOfFieldFileNotFound = Erreur mauvaise configuration du champ : Fichier introuvable pour l'inclusion From f4476b905c7d65c3289ffa923938c84cd5fd1030 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 18:11:57 +0100 Subject: [PATCH 134/816] Debug v17 --- htdocs/compta/resultat/result.php | 117 ++++++++++++++++++------------ 1 file changed, 69 insertions(+), 48 deletions(-) diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index 3f3e14e2d61..856eb8a5fe8 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -339,60 +339,81 @@ if ($modecompta == 'CREANCES-DETTES') { } $result = strtr($formula, $vars); + $result = str_replace('--', '+', $result); - //var_dump($result); - //$r = $AccCat->calculate($result); - $r = dol_eval($result, 1, 1, '1'); - //var_dump($r); - - print ''.price($r).''.price($r).''.$rshort.''.$rshort.''.$rshort.''.price($r).''.$rshort.''.price($r).''.price($r).''.price($r).''.price($r).''.price($r).'
'; + // Code and Label + print ''; print dol_escape_htmltag($cat['code']); - print ''; + print ''; print dol_escape_htmltag($cat['label']); print ''.$rshort.''.$rshort.''.$rshort.''.$rshort.''.price($r).''.price($r).''.price($r).''.price($r).''.price($r).''.price($r).''.price($r).'
'; + print ''; print dol_escape_htmltag($cat['code']); print ''; - print dol_escape_htmltag($cat['label']); + $labeltoshow = dol_escape_htmltag($cat['label']); if (count($cpts) > 0 && !empty($cpts[0])) { // Show example of 5 first accounting accounts $i = 0; foreach ($cpts as $cpt) { if ($i > 5) { - print '...)'; + $labeltoshow .= '...)'; break; } if ($i > 0) { - print ', '; + $labeltoshow .= ', '; } else { - print ' ('; + $labeltoshow .= ' ('; } - print dol_escape_htmltag($cpt['account_number']); + $labeltoshow .= dol_escape_htmltag($cpt['account_number']); $i++; } if ($i <= 5) { - print ')'; + $labeltoshow .= ')'; } } else { - print ' - '.$langs->trans("GroupIsEmptyCheckSetup").''; + $labeltoshow .= ' - '.$langs->trans("GroupIsEmptyCheckSetup").''; } + print ''; + print $labeltoshow; print ''.price($totCat['NP']).'
'; + print ''; print '     '.length_accountg($cpt['account_number']); print ' - '; print $cpt['account_label']; From 34c2b20f7705b0d44352d9c7ae0bec3537276542 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 20:45:08 +0100 Subject: [PATCH 136/816] css --- htdocs/compta/resultat/result.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index 8615e595200..743fd4c0506 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -322,7 +322,7 @@ if ($modecompta == 'CREANCES-DETTES') { // Code and Label print ''; print dol_escape_htmltag($cat['code']); - print ''; + print ''; print dol_escape_htmltag($cat['label']); print ''.price($r).''.price($r).''; + print ''; print $labeltoshow; print ''.price($totCat['NP']).''.price($totCat['N']).''.price($totCat['N']).'
'; + print ''; print '     '.length_accountg($cpt['account_number']); print ' - '; print $cpt['account_label']; print ''.price($resultNP).''.price($resultN).''.price($resultN).'
'; +print '
'; // Ref /*print ''; @@ -136,21 +146,26 @@ print $form->showrefnav($object,'id','',1,'rowid','id'); print '';*/ // Date -print ''; +print '"; +print ''; // Mode -print ''; // Numero -print ''; +print ''; // Montant -print ''; +print ''; // Note -print ''; +print ''; // Bank account if (isModEnabled("banque")) { From 3cf90352bf20c4ec88870b7970fc484cd06294dc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 29 Dec 2022 23:51:47 +0100 Subject: [PATCH 139/816] Fix date timezone --- htdocs/salaries/class/paymentsalary.class.php | 1 + htdocs/salaries/payment_salary/card.php | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/salaries/class/paymentsalary.class.php b/htdocs/salaries/class/paymentsalary.class.php index a2de50aeed4..ca4df1df4f9 100644 --- a/htdocs/salaries/class/paymentsalary.class.php +++ b/htdocs/salaries/class/paymentsalary.class.php @@ -266,6 +266,7 @@ class PaymentSalary extends CommonObject $this->num_paiement = $obj->num_payment; $this->num_payment = $obj->num_payment; $this->note = $obj->note; + $this->note_private = $obj->note; $this->fk_bank = $obj->fk_bank; $this->fk_user_author = $obj->fk_user_author; $this->fk_user_modif = $obj->fk_user_modif; diff --git a/htdocs/salaries/payment_salary/card.php b/htdocs/salaries/payment_salary/card.php index c6d73c5ec7f..25d28932a40 100644 --- a/htdocs/salaries/payment_salary/card.php +++ b/htdocs/salaries/payment_salary/card.php @@ -43,6 +43,8 @@ $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm'); if ($user->socid) $socid = $user->socid; +$salary = new Salary($db); + $object = new PaymentSalary($db); if ($id > 0) { $result = $object->fetch($id); @@ -71,7 +73,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('salarie } if ($action == 'setdatep' && GETPOST('datepday') && $user->hasRight('salaries', 'write')) { - $datepaye = dol_mktime(GETPOST('datephour', 'int'), GETPOST('datepmin', 'int'), GETPOST('datepsec', 'int'), GETPOST('datepmonth', 'int'), GETPOST('datepday', 'int'), GETPOST('datepyear', 'int'), 'tzuserrel'); + $datepaye = dol_mktime(GETPOST('datephour', 'int'), GETPOST('datepmin', 'int'), GETPOST('datepsec', 'int'), GETPOST('datepmonth', 'int'), GETPOST('datepday', 'int'), GETPOST('datepyear', 'int')); // field is a date in database, not a datetime, so we must use 'gmt' not 'tzuserrel' $res = $object->updatePaymentDate($datepaye); if ($res === 0) { setEventMessages($langs->trans('PaymentDateUpdateSucceeded'), null, 'mesgs'); @@ -85,12 +87,10 @@ if ($action == 'setdatep' && GETPOST('datepday') && $user->hasRight('salaries', * View */ -llxHeader(); - -$salary = new Salary($db); - $form = new Form($db); +llxHeader('', $langs->trans("SalaryPayment")); + $h = 0; $head = array(); From 41f35d5947758b4f1f61907ea24601e8a2170c4d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 00:04:47 +0100 Subject: [PATCH 140/816] NEW Date for salary payment includes the hour/min --- htdocs/core/class/html.form.class.php | 6 +++--- htdocs/install/mysql/migration/17.0.0-18.0.0.sql | 3 +++ htdocs/install/mysql/tables/llx_payment_salary.sql | 2 +- htdocs/salaries/payment_salary/card.php | 6 +++--- htdocs/salaries/payments.php | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9c193b90776..d766c74cde1 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -96,7 +96,7 @@ class Form * @param string $preselected Value to show/edit (not used in this function) * @param object $object Object * @param boolean $perm Permission to allow button to edit parameter. Set it to 0 to have a not edited field. - * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols', 'datepicker' ('day' do not work, don't know why), 'checkbox:ckeditor:dolibarr_zzz:width:height:savemethod:1:rows:cols', 'select;xxx[:class]'...) + * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols', 'datepicker' ('day' do not work, don't know why), 'dayhour' or 'datehourpicker' 'checkbox:ckeditor:dolibarr_zzz:width:height:savemethod:1:rows:cols', 'select;xxx[:class]'...) * @param string $moreparam More param to add on a href URL. * @param int $fieldrequired 1 if we want to show field as mandatory using the "fieldrequired" CSS. * @param int $notabletag 1=Do not output table tags but output a ':', 2=Do not output table tags and no ':', 3=Do not output table tags but output a ' ' @@ -192,7 +192,7 @@ class Form * @param string $value Value to show/edit * @param object $object Object * @param boolean $perm Permission to allow button to edit parameter - * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols%', 'datepicker' ('day' do not work, don't know why), 'dayhour' or 'datepickerhour', 'ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols', 'select;xkey:xval,ykey:yval,...') + * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols%', 'datepicker' ('day' do not work, don't know why), 'dayhour' or 'datehourpicker', 'ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols', 'select;xkey:xval,ykey:yval,...') * @param string $editvalue When in edit mode, use this value as $value instead of value (for example, you can provide here a formated price instead of numeric value). Use '' to use same than $value * @param object $extObject External object * @param mixed $custommsg String or Array of custom messages : eg array('success' => 'MyMessage', 'error' => 'MyMessage') @@ -200,7 +200,7 @@ class Form * @param int $notabletag Do no output table tags * @param string $formatfunc Call a specific function to output field in view mode (For example: 'dol_print_email') * @param string $paramid Key of parameter for id ('id', 'socid') - * @param string $gm 'auto' or 'tzuser' or 'tzserver' (when $typeofdata is a date) + * @param string $gm 'auto' or 'tzuser' or 'tzuserrel' or 'tzserver' (when $typeofdata is a date) * @return string HTML edit field */ public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 0, $formatfunc = '', $paramid = 'id', $gm = 'auto') 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 2910ccee23b..ae7d51a20dd 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 @@ -42,3 +42,6 @@ ALTER TABLE llx_facture DROP COLUMN amount; ALTER TABLE llx_socpeople CHANGE fk_prospectcontactlevel fk_prospectlevel varchar(12); ALTER TABLE llx_facture ADD COLUMN prorata_discount real DEFAULT NULL; + +ALTER TABLE llx_payment_salary MODIFY COLUMN datep datetime; + diff --git a/htdocs/install/mysql/tables/llx_payment_salary.sql b/htdocs/install/mysql/tables/llx_payment_salary.sql index 308e70effc2..0dd24eb199d 100644 --- a/htdocs/install/mysql/tables/llx_payment_salary.sql +++ b/htdocs/install/mysql/tables/llx_payment_salary.sql @@ -23,7 +23,7 @@ create table llx_payment_salary tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, datec datetime, -- Create date fk_user integer DEFAULT NULL, - datep date, -- payment date + datep datetime, -- payment date datev date, -- value date (this field should not be here, only into bank tables) salary double(24,8), -- salary of user when payment was done amount double(24,8) NOT NULL DEFAULT 0, diff --git a/htdocs/salaries/payment_salary/card.php b/htdocs/salaries/payment_salary/card.php index 25d28932a40..8e48dfb0d08 100644 --- a/htdocs/salaries/payment_salary/card.php +++ b/htdocs/salaries/payment_salary/card.php @@ -73,7 +73,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('salarie } if ($action == 'setdatep' && GETPOST('datepday') && $user->hasRight('salaries', 'write')) { - $datepaye = dol_mktime(GETPOST('datephour', 'int'), GETPOST('datepmin', 'int'), GETPOST('datepsec', 'int'), GETPOST('datepmonth', 'int'), GETPOST('datepday', 'int'), GETPOST('datepyear', 'int')); // field is a date in database, not a datetime, so we must use 'gmt' not 'tzuserrel' + $datepaye = dol_mktime(GETPOST('datephour', 'int'), GETPOST('datepmin', 'int'), GETPOST('datepsec', 'int'), GETPOST('datepmonth', 'int'), GETPOST('datepday', 'int'), GETPOST('datepyear', 'int'), 'tzuserrel'); $res = $object->updatePaymentDate($datepaye); if ($res === 0) { setEventMessages($langs->trans('PaymentDateUpdateSucceeded'), null, 'mesgs'); @@ -147,9 +147,9 @@ print '';*/ // Date print '"; print ''; diff --git a/htdocs/salaries/payments.php b/htdocs/salaries/payments.php index 8fcc7183dae..75a18621ea1 100644 --- a/htdocs/salaries/payments.php +++ b/htdocs/salaries/payments.php @@ -575,7 +575,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } // Date payment - print '\n"; + print '\n"; if (!$i) { $totalarray['nbfield']++; } From e6035fee1cbb32c34ba00ebd9a17dd7523244758 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 00:12:48 +0100 Subject: [PATCH 141/816] NEW Can add the add now link on date into addfieldvalue() --- htdocs/core/class/html.form.class.php | 13 ++++++++----- htdocs/salaries/payment_salary/card.php | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index d766c74cde1..678f34c52ad 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -194,16 +194,17 @@ class Form * @param boolean $perm Permission to allow button to edit parameter * @param string $typeofdata Type of data ('string' by default, 'email', 'amount:99', 'numeric:99', 'text' or 'textarea:rows:cols%', 'datepicker' ('day' do not work, don't know why), 'dayhour' or 'datehourpicker', 'ckeditor:dolibarr_zzz:width:height:savemethod:toolbarstartexpanded:rows:cols', 'select;xkey:xval,ykey:yval,...') * @param string $editvalue When in edit mode, use this value as $value instead of value (for example, you can provide here a formated price instead of numeric value). Use '' to use same than $value - * @param object $extObject External object + * @param object $extObject External object ??? * @param mixed $custommsg String or Array of custom messages : eg array('success' => 'MyMessage', 'error' => 'MyMessage') - * @param string $moreparam More param to add on the form action href URL + * @param string $moreparam More param to add on the form on action href URL parameter * @param int $notabletag Do no output table tags * @param string $formatfunc Call a specific function to output field in view mode (For example: 'dol_print_email') * @param string $paramid Key of parameter for id ('id', 'socid') * @param string $gm 'auto' or 'tzuser' or 'tzuserrel' or 'tzserver' (when $typeofdata is a date) + * @param array $moreoptions Array with more options. For example array('addnowlink'=>1) * @return string HTML edit field */ - public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 0, $formatfunc = '', $paramid = 'id', $gm = 'auto') + public function editfieldval($text, $htmlname, $value, $object, $perm, $typeofdata = 'string', $editvalue = '', $extObject = null, $custommsg = null, $moreparam = '', $notabletag = 0, $formatfunc = '', $paramid = 'id', $gm = 'auto', $moreoptions = array()) { global $conf, $langs; @@ -276,9 +277,11 @@ class Form $ret .= dol_string_neverthesehtmltags($valuetoshow, array('textarea')); $ret .= ''; } elseif ($typeofdata == 'day' || $typeofdata == 'datepicker') { - $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form'.$htmlname, 1, 0, 0, '', '', '', '', 1, '', '', $gm); + $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink']; + $ret .= $this->selectDate($value, $htmlname, 0, 0, 1, 'form'.$htmlname, 1, $addnowlink, 0, '', '', '', '', 1, '', '', $gm); } elseif ($typeofdata == 'dayhour' || $typeofdata == 'datehourpicker') { - $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form'.$htmlname, 1, 0, 0, '', '', '', '', 1, '', '', $gm); + $addnowlink = empty($moreoptions['addnowlink']) ? 0 : $moreoptions['addnowlink']; + $ret .= $this->selectDate($value, $htmlname, 1, 1, 1, 'form'.$htmlname, 1, $addnowlink, 0, '', '', '', '', 1, '', '', $gm); } elseif (preg_match('/^select;/', $typeofdata)) { $arraydata = explode(',', preg_replace('/^select;/', '', $typeofdata)); $arraylist = array(); diff --git a/htdocs/salaries/payment_salary/card.php b/htdocs/salaries/payment_salary/card.php index 8e48dfb0d08..b35469ab27e 100644 --- a/htdocs/salaries/payment_salary/card.php +++ b/htdocs/salaries/payment_salary/card.php @@ -149,7 +149,7 @@ print '';*/ print '"; print ''; From fff3a492d5847b3eb6c27a6278f26b5902e31359 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 00:27:00 +0100 Subject: [PATCH 142/816] Fix date --- htdocs/salaries/card.php | 11 +++++++---- htdocs/salaries/paiement_salary.php | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 974407ff42d..0c4f3e57ff5 100644 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -957,9 +957,12 @@ if ($id > 0) { while ($i < $num) { $objp = $db->fetch_object($resql); - print ''; + // Date + print ''; - print '\n"; + // Date + print '\n"; $labeltype = $langs->trans("PaymentType".$objp->type_code) != ("PaymentType".$objp->type_code) ? $langs->trans("PaymentType".$objp->type_code) : $objp->paiement_type; print "\n"; if (isModEnabled("banque")) { @@ -993,8 +996,8 @@ if ($id > 0) { print ''; } - print '\n"; - print '\n"; + print '\n"; + print '\n"; $resteapayer = $object->amount - $totalpaid; $cssforamountpaymentcomplete = 'amountpaymentcomplete'; diff --git a/htdocs/salaries/paiement_salary.php b/htdocs/salaries/paiement_salary.php index 9f90e4c9ac9..0c2c757e2dc 100644 --- a/htdocs/salaries/paiement_salary.php +++ b/htdocs/salaries/paiement_salary.php @@ -66,7 +66,7 @@ if (($action == 'add_payment' || ($action == 'confirm_paiement' && $confirm == ' exit; } - $datepaye = dol_mktime(12, 0, 0, GETPOST("remonth", 'int'), GETPOST("reday", 'int'), GETPOST("reyear", 'int')); + $datepaye = dol_mktime(GETPOST("rehour", 'int'), GETPOST("remin", 'int'), GETPOST("resec", 'int'), GETPOST("remonth", 'int'), GETPOST("reday", 'int'), GETPOST("reyear", 'int'), 'tzuserrel'); if (!(GETPOST("paiementtype", 'int') > 0)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode")), null, 'errors'); @@ -210,9 +210,9 @@ if ($action == 'create') { print '';*/ print '"; print ''; From f99fa791b2c9404317cf1fd49515389ca955640d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 01:24:24 +0100 Subject: [PATCH 143/816] Fix rounding --- .../accountancy/bookkeeping/listbyaccount.php | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index c24e509ff60..00626b2558c 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -962,8 +962,8 @@ while ($i < min($num, $limit)) { } else { print ''; } - print ''; - print ''; + print ''; + print ''; print ''; print ''; // Show balance of last shown account @@ -972,13 +972,13 @@ while ($i < min($num, $limit)) { print ''; if ($balance > 0) { print ''; print ''; } else { print ''; print ''; } print ''; @@ -1233,8 +1233,8 @@ while ($i < min($num, $limit)) { if ($num > 0 && $colspan > 0) { print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; print ''; // Show balance of last shown account @@ -1243,19 +1243,29 @@ if ($num > 0 && $colspan > 0) { print ''; if ($balance > 0) { print ''; print ''; } else { print ''; print ''; } print ''; print ''; } + +// Clean total values to round them +if (!empty($totalarray['val']['totaldebit'])) { + $totalarray['val']['totaldebit'] = price2num($totalarray['val']['totaldebit'], 'MT'); +} +if (!empty($totalarray['val']['totalcredit'])) { + $totalarray['val']['totalcredit'] = price2num($totalarray['val']['totalcredit'], 'MT'); +} + + // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; From dd4810aef62901c33fbbba13dd49e13f1ffcc516 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 01:40:09 +0100 Subject: [PATCH 144/816] Fix escape --- htdocs/accountancy/bookkeeping/list.php | 4 ++-- htdocs/accountancy/bookkeeping/listbyaccount.php | 2 +- htdocs/accountancy/class/bookkeeping.class.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index ac1cc93cba7..eca5a1beadc 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -346,7 +346,7 @@ if (empty($reshook)) { $listofaccountsforgroup2 = array(); if (is_array($listofaccountsforgroup)) { foreach ($listofaccountsforgroup as $tmpval) { - $listofaccountsforgroup2[] = $tmpval['id']; + $listofaccountsforgroup2[] = "'".$db->escape($tmpval['id'])."'"; } } $filter['t.search_accounting_code_in'] = join(',', $listofaccountsforgroup2); @@ -698,7 +698,7 @@ if (count($filter) > 0) { $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); } } elseif ($key == 't.search_accounting_code_in' && !empty($value)) { - $sqlwhere[] = 't.numero_compte IN ('.$value.')'; + $sqlwhere[] = 't.numero_compte IN ('.$db->sanitize($value, 1).')'; } else { $sqlwhere[] = natural_search($key, $value, 0, 1); } diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 00626b2558c..2e434550c25 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -291,7 +291,7 @@ if (empty($reshook)) { $listofaccountsforgroup2 = array(); if (is_array($listofaccountsforgroup)) { foreach ($listofaccountsforgroup as $tmpval) { - $listofaccountsforgroup2[] = $tmpval['id']; + $listofaccountsforgroup2[] = "'".$db->escape($tmpval['id'])."'"; } } $filter['t.search_accounting_code_in'] = join(',', $listofaccountsforgroup2); diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 0458250489f..bb5a6e472b1 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -903,7 +903,7 @@ class BookKeeping extends CommonObject $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); } } elseif ($key == 't.search_accounting_code_in' && !empty($value)) { - $sqlwhere[] = 't.numero_compte IN ('.$value.')'; + $sqlwhere[] = 't.numero_compte IN ('.$this->db->sanitize($value, 1).')'; } else { $sqlwhere[] = natural_search($key, $value, 0, 1); } From 8d64f8617cfb86748874ef27ec861a10a0968df7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 01:52:41 +0100 Subject: [PATCH 145/816] Clean code --- .../class/accountingjournal.class.php | 22 +------------------ htdocs/comm/action/class/actioncomm.class.php | 4 ++-- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/htdocs/accountancy/class/accountingjournal.class.php b/htdocs/accountancy/class/accountingjournal.class.php index 4accf66e154..f56932d4985 100644 --- a/htdocs/accountancy/class/accountingjournal.class.php +++ b/htdocs/accountancy/class/accountingjournal.class.php @@ -454,27 +454,12 @@ class AccountingJournal extends CommonObject } $sql = ""; - - // FIXME sql error with Mysql 5.7 - /*if ($in_bookkeeping == 'already' || $in_bookkeeping == 'notyet') { - $sql .= "WITH in_accounting_bookkeeping(fk_docdet) AS ("; - $sql .= " SELECT DISTINCT fk_docdet"; - $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping"; - $sql .= " WHERE doc_type = 'asset'"; - $sql .= ") "; - }*/ - $sql .= "SELECT ad.fk_asset AS rowid, a.ref AS asset_ref, a.label AS asset_label, a.acquisition_value_ht AS asset_acquisition_value_ht"; $sql .= ", a.disposal_date AS asset_disposal_date, a.disposal_amount_ht AS asset_disposal_amount_ht, a.disposal_subject_to_vat AS asset_disposal_subject_to_vat"; $sql .= ", ad.rowid AS depreciation_id, ad.depreciation_mode, ad.ref AS depreciation_ref, ad.depreciation_date, ad.depreciation_ht, ad.accountancy_code_debit, ad.accountancy_code_credit"; $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation as ad"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "asset as a ON a.rowid = ad.fk_asset"; - // FIXME sql error with Mysql 5.7 - /*if ($in_bookkeeping == 'already' || $in_bookkeeping == 'notyet') { - $sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid"; - }*/ $sql .= " WHERE a.entity IN (" . getEntity('asset', 0) . ')'; // We don't share object for accountancy, we use source object sharing - // Compatibility with Mysql 5.7 if ($in_bookkeeping == 'already') { $sql .= " AND EXISTS (SELECT iab.fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS iab WHERE iab.fk_docdet = ad.rowid AND doc_type = 'asset')"; } elseif ($in_bookkeeping == 'notyet') { @@ -488,11 +473,6 @@ class AccountingJournal extends CommonObject if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) { $sql .= " AND ad.depreciation_date >= '" . $this->db->idate($conf->global->ACCOUNTING_DATE_START_BINDING) . "'"; } - // Already in bookkeeping or not - // FIXME sql error with Mysql 5.7 - /*if ($in_bookkeeping == 'already' || $in_bookkeeping == 'notyet') { - $sql .= " AND iab.fk_docdet IS" . ($in_bookkeeping == 'already' ? " NOT" : "") . " NULL"; - }*/ $sql .= " ORDER BY ad.depreciation_date"; dol_syslog(__METHOD__, LOG_DEBUG); @@ -755,7 +735,7 @@ class AccountingJournal extends CommonObject } } - $journal_data[$pre_data_id] = $element; + $journal_data[(int) $pre_data_id] = $element; } unset($pre_data); diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index efe9374a748..244b3df9405 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -477,8 +477,8 @@ class ActionComm extends CommonObject $this->elementtype = 'contract'; } - if (!is_array($this->userassigned) && !empty($this->userassigned)) { // For backward compatibility when userassigned was an int instead fo array - $tmpid = $this->userassigned; + if (!is_array($this->userassigned) && !empty($this->userassigned)) { // For backward compatibility when userassigned was an int instead of an array + $tmpid = (int) $this->userassigned; $this->userassigned = array(); $this->userassigned[$tmpid] = array('id'=>$tmpid, 'transparency'=>$this->transparency); } From 8e82bb71482f12e28de447b7c01179d8d021e4a1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 02:00:31 +0100 Subject: [PATCH 146/816] Clean code --- htdocs/adherents/card.php | 2 +- htdocs/product/card.php | 4 ++-- htdocs/societe/card.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 56e7868ec5a..9d0677a2fc9 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -565,7 +565,7 @@ if (empty($reshook)) { } if (!empty($object->url) && !isValidUrl($object->url)) { $langs->load("errors"); - setEventMessages('', $langs->trans("ErrorBadUrl", $object->url), 'errors'); + setEventMessages($langs->trans("ErrorBadUrl", $object->url), null, 'errors'); } $public = 0; if (isset($public)) { diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 173c96fd297..2bfe94f418a 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -541,7 +541,7 @@ if (empty($reshook)) { if ($result < 0) { $error++; $mesg = 'Failed to get bar code type information '; - setEventMessages($mesg.$stdobject->error, $mesg.$stdobject->errors, 'errors'); + setEventMessages($mesg.$stdobject->error, $stdobject->errors, 'errors'); } $object->barcode_type_code = $stdobject->barcode_type_code; $object->barcode_type_coder = $stdobject->barcode_type_coder; @@ -780,7 +780,7 @@ if (empty($reshook)) { if ($result < 0) { $error++; $mesg = 'Failed to get bar code type information '; - setEventMessages($mesg.$stdobject->error, $mesg.$stdobject->errors, 'errors'); + setEventMessages($mesg.$stdobject->error, $stdobject->errors, 'errors'); } $object->barcode_type_code = $stdobject->barcode_type_code; $object->barcode_type_coder = $stdobject->barcode_type_coder; diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index a7389c8949c..cb2b101307b 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -570,11 +570,11 @@ if (empty($reshook)) { if (!empty($object->email) && !isValidEMail($object->email)) { $langs->load("errors"); $error++; - setEventMessages('', $langs->trans("ErrorBadEMail", $object->email), 'errors'); + setEventMessages($langs->trans("ErrorBadEMail", $object->email), null, 'errors'); } if (!empty($object->url) && !isValidUrl($object->url)) { $langs->load("errors"); - setEventMessages('', $langs->trans("ErrorBadUrl", $object->url), 'errors'); + setEventMessages($langs->trans("ErrorBadUrl", $object->url), null, 'errors'); } if (!empty($object->webservices_url)) { //Check if has transport, without any the soap client will give error From 1afa3b4f81cbd195eca973e527c5f7c8627551f7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 01:58:13 +0100 Subject: [PATCH 147/816] Fix doxygen --- htdocs/core/class/ldap.class.php | 8 ++++---- .../core/modules/stocktransfer/doc/pdf_eagle.modules.php | 2 +- .../mymodule/doc/pdf_standard_myobject.modules.php | 2 +- .../doc/pdf_standard_recruitmentjobposition.modules.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 011d8a380ef..3dc45c753bc 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -1239,10 +1239,10 @@ class Ldap /** * Load all attribute of a LDAP user * - * @param User $user User to search for. Not used if a filter is provided. - * @param string $filter Filter for search. Must start with &. - * Examples: &(objectClass=inetOrgPerson) &(objectClass=user)(objectCategory=person) &(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com) - * @return int >0 if OK, <0 if KO + * @param User|string $user Not used. + * @param string $filter Filter for search. Must start with &. + * Examples: &(objectClass=inetOrgPerson) &(objectClass=user)(objectCategory=person) &(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com) + * @return int >0 if OK, <0 if KO */ public function fetch($user, $filter) { diff --git a/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php b/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php index 22601d93dae..35a52f35bd8 100644 --- a/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php +++ b/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php @@ -895,7 +895,7 @@ class pdf_eagle extends ModelePdfStockTransfer /** * Show top header of page. * - * @param PDF $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output diff --git a/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php b/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php index 5c277b85ae4..b78a2a5f4d7 100644 --- a/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php +++ b/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php @@ -879,7 +879,7 @@ class pdf_standard_myobject extends ModelePDFMyObject /** * Show top header of page. * - * @param Tcpdf $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output diff --git a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php index 1a58085d8c9..61c2eb3ff20 100644 --- a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php +++ b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php @@ -798,7 +798,7 @@ class pdf_standard_recruitmentjobposition extends ModelePDFRecruitmentJobPositio /** * Show top header of page. * - * @param Tcpdf $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output From 6c223eafc90994a95992102fd5c6b351d792bc2e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 01:58:13 +0100 Subject: [PATCH 148/816] Fix doxygen and warnings --- htdocs/admin/modules.php | 4 ++-- htdocs/core/class/html.form.class.php | 4 ++-- htdocs/core/class/ldap.class.php | 8 ++++---- htdocs/core/modules/modHoliday.class.php | 4 ---- .../core/modules/stocktransfer/doc/pdf_eagle.modules.php | 2 +- htdocs/fourn/commande/list.php | 2 +- .../class/api_knowledgemanagement.class.php | 2 +- .../mymodule/doc/pdf_standard_myobject.modules.php | 2 +- htdocs/product/class/api_products.class.php | 6 +++--- .../doc/pdf_standard_recruitmentjobposition.modules.php | 2 +- 10 files changed, 16 insertions(+), 20 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 8c9230d190c..45534aa66f5 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -844,10 +844,10 @@ if ($mode == 'common' || $mode == 'commonkanban') { } } } - } elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) { + } elseif (preg_match('/^([^@]+)@([^@]+)$/i', (string) $objMod->config_page_url, $regs)) { $codetoconfig .= ''.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"', false, 0, 0, '', 'fa-15').''; } else { - $codetoconfig .= ''.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"', false, 0, 0, '', 'fa-15').''; + $codetoconfig .= ''.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"', false, 0, 0, '', 'fa-15').''; } } else { $codetoconfig .= img_picto($langs->trans("NothingToSetup"), "setup", 'class="opacitytransp" style="padding-right: 6px"', false, 0, 0, '', 'fa-15'); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 678f34c52ad..f3a566b6014 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -7755,7 +7755,7 @@ class Form } } if (!is_object($objecttmp)) { - dol_syslog('Error bad setup of type for field '.$InfoFieldList, LOG_WARNING); + dol_syslog('Error bad setup of type for field '.join(',', $InfoFieldList), LOG_WARNING); return 'Error bad setup of type for field '.join(',', $InfoFieldList); } @@ -9905,7 +9905,7 @@ class Form method: "POST", dataType: "json", data: { fk_c_exp_tax_cat: $(this).val(), token: \''.currentToken().'\' }, - url: "'.(DOL_URL_ROOT.'/expensereport/ajax/ajaxik.php?'.$params).'", + url: "'.(DOL_URL_ROOT.'/expensereport/ajax/ajaxik.php?'.join('&', $params)).'", }).done(function( data, textStatus, jqXHR ) { console.log(data); if (typeof data.up != "undefined") { diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 011d8a380ef..3dc45c753bc 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -1239,10 +1239,10 @@ class Ldap /** * Load all attribute of a LDAP user * - * @param User $user User to search for. Not used if a filter is provided. - * @param string $filter Filter for search. Must start with &. - * Examples: &(objectClass=inetOrgPerson) &(objectClass=user)(objectCategory=person) &(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com) - * @return int >0 if OK, <0 if KO + * @param User|string $user Not used. + * @param string $filter Filter for search. Must start with &. + * Examples: &(objectClass=inetOrgPerson) &(objectClass=user)(objectCategory=person) &(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com) + * @return int >0 if OK, <0 if KO */ public function fetch($user, $filter) { diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index 61bdc0e8f98..57ffe62e005 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -78,10 +78,6 @@ class modHoliday extends DolibarrModules // Config pages $this->config_page_url = array("holiday.php"); - - // Config pages. Put here list of php page names stored in admmin directory used to setup module. - // $this->config_page_url = array("holiday.php?leftmenu=setup@holiday"); - // Dependencies $this->hidden = false; // A condition to hide module $this->depends = array(); // List of module class names as string that must be enabled if this module is enabled diff --git a/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php b/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php index 22601d93dae..35a52f35bd8 100644 --- a/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php +++ b/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php @@ -895,7 +895,7 @@ class pdf_eagle extends ModelePdfStockTransfer /** * Show top header of page. * - * @param PDF $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index 3d458247bcf..3080a184abb 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -1208,7 +1208,7 @@ if ($resql) { include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; if ($massaction == 'prevalidate') { - print $form->formconfirm($_SERVER["PHP_SELF"].$fieldstosearchall, $langs->trans("ConfirmMassValidation"), $langs->trans("ConfirmMassValidationQuestion"), "validate", null, '', 0, 200, 500, 1); + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassValidation"), $langs->trans("ConfirmMassValidationQuestion"), "validate", null, '', 0, 200, 500, 1); } if ($massaction == 'createbills') { diff --git a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php index ccf54b1d6d9..8232287b23b 100644 --- a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php +++ b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php @@ -114,7 +114,7 @@ class KnowledgeManagement extends DolibarrApi } if ($result < 0) { - throw new RestException(503, 'Error when retrieve category list : '.array_merge(array($categories->error), $categories->errors)); + throw new RestException(503, 'Error when retrieve category list : '.join(',', array_merge(array($categories->error), $categories->errors))); } return $result; diff --git a/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php b/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php index 5c277b85ae4..b78a2a5f4d7 100644 --- a/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php +++ b/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php @@ -879,7 +879,7 @@ class pdf_standard_myobject extends ModelePDFMyObject /** * Show top header of page. * - * @param Tcpdf $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 76ee11f727e..7a10293d7e4 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -595,7 +595,7 @@ class Products extends DolibarrApi } if ($result < 0) { - throw new RestException(503, 'Error when retrieve category list : '.array_merge(array($categories->error), $categories->errors)); + throw new RestException(503, 'Error when retrieve category list : '.join(',', array_merge(array($categories->error), $categories->errors))); } return $result; @@ -628,7 +628,7 @@ class Products extends DolibarrApi } if ($result < 0) { - throw new RestException(503, 'Error when retrieve prices list : '.array_merge(array($this->product->error), $this->product->errors)); + throw new RestException(503, 'Error when retrieve prices list : '.join(',', array_merge(array($this->product->error), $this->product->errors))); } return array( @@ -719,7 +719,7 @@ class Products extends DolibarrApi } if ($result < 0) { - throw new RestException(503, 'Error when retrieve prices list : '.array_merge(array($this->product->error), $this->product->errors)); + throw new RestException(503, 'Error when retrieve prices list : '.join(',', array_merge(array($this->product->error), $this->product->errors))); } return array( diff --git a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php index 1a58085d8c9..61c2eb3ff20 100644 --- a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php +++ b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php @@ -798,7 +798,7 @@ class pdf_standard_recruitmentjobposition extends ModelePDFRecruitmentJobPositio /** * Show top header of page. * - * @param Tcpdf $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output From 3dfe09d1fee35d1de40411f6023d4b6d4b72c869 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 01:58:13 +0100 Subject: [PATCH 149/816] Fix doxygen --- htdocs/core/class/ldap.class.php | 8 ++++---- .../core/modules/stocktransfer/doc/pdf_eagle.modules.php | 2 +- .../mymodule/doc/pdf_standard_myobject.modules.php | 2 +- .../doc/pdf_standard_recruitmentjobposition.modules.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 011d8a380ef..3dc45c753bc 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -1239,10 +1239,10 @@ class Ldap /** * Load all attribute of a LDAP user * - * @param User $user User to search for. Not used if a filter is provided. - * @param string $filter Filter for search. Must start with &. - * Examples: &(objectClass=inetOrgPerson) &(objectClass=user)(objectCategory=person) &(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com) - * @return int >0 if OK, <0 if KO + * @param User|string $user Not used. + * @param string $filter Filter for search. Must start with &. + * Examples: &(objectClass=inetOrgPerson) &(objectClass=user)(objectCategory=person) &(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com) + * @return int >0 if OK, <0 if KO */ public function fetch($user, $filter) { diff --git a/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php b/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php index 22601d93dae..35a52f35bd8 100644 --- a/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php +++ b/htdocs/core/modules/stocktransfer/doc/pdf_eagle.modules.php @@ -895,7 +895,7 @@ class pdf_eagle extends ModelePdfStockTransfer /** * Show top header of page. * - * @param PDF $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output diff --git a/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php b/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php index bd5348b1566..05486989e1d 100644 --- a/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php +++ b/htdocs/modulebuilder/template/core/modules/mymodule/doc/pdf_standard_myobject.modules.php @@ -879,7 +879,7 @@ class pdf_standard_myobject extends ModelePDFMyObject /** * Show top header of page. * - * @param Tcpdf $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output diff --git a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php index 94e93c87baa..f4d2226d51d 100644 --- a/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php +++ b/htdocs/recruitment/core/modules/recruitment/doc/pdf_standard_recruitmentjobposition.modules.php @@ -798,7 +798,7 @@ class pdf_standard_recruitmentjobposition extends ModelePDFRecruitmentJobPositio /** * Show top header of page. * - * @param Tcpdf $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output From b8092f1eae50f0bd987426564e6ad1930ca4ed77 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 01:58:13 +0100 Subject: [PATCH 150/816] Fix doxygen and warnings --- htdocs/admin/modules.php | 4 ++-- htdocs/core/class/html.form.class.php | 4 ++-- htdocs/core/modules/modHoliday.class.php | 4 ---- htdocs/fourn/commande/list.php | 2 +- .../class/api_knowledgemanagement.class.php | 2 +- htdocs/product/class/api_products.class.php | 6 +++--- 6 files changed, 9 insertions(+), 13 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 93eb5524a1d..46b711875b8 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -844,10 +844,10 @@ if ($mode == 'common' || $mode == 'commonkanban') { } } } - } elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) { + } elseif (preg_match('/^([^@]+)@([^@]+)$/i', (string) $objMod->config_page_url, $regs)) { $codetoconfig .= ''.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"', false, 0, 0, '', 'fa-15').''; } else { - $codetoconfig .= ''.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"', false, 0, 0, '', 'fa-15').''; + $codetoconfig .= ''.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"', false, 0, 0, '', 'fa-15').''; } } else { $codetoconfig .= img_picto($langs->trans("NothingToSetup"), "setup", 'class="opacitytransp" style="padding-right: 6px"', false, 0, 0, '', 'fa-15'); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index a9c17a2edba..3f4579340d0 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -7720,7 +7720,7 @@ class Form } } if (!is_object($objecttmp)) { - dol_syslog('Error bad setup of type for field '.$InfoFieldList, LOG_WARNING); + dol_syslog('Error bad setup of type for field '.join(',', $InfoFieldList), LOG_WARNING); return 'Error bad setup of type for field '.join(',', $InfoFieldList); } @@ -9870,7 +9870,7 @@ class Form method: "POST", dataType: "json", data: { fk_c_exp_tax_cat: $(this).val(), token: \''.currentToken().'\' }, - url: "'.(DOL_URL_ROOT.'/expensereport/ajax/ajaxik.php?'.$params).'", + url: "'.(DOL_URL_ROOT.'/expensereport/ajax/ajaxik.php?'.join('&', $params)).'", }).done(function( data, textStatus, jqXHR ) { console.log(data); if (typeof data.up != "undefined") { diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index 61bdc0e8f98..57ffe62e005 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -78,10 +78,6 @@ class modHoliday extends DolibarrModules // Config pages $this->config_page_url = array("holiday.php"); - - // Config pages. Put here list of php page names stored in admmin directory used to setup module. - // $this->config_page_url = array("holiday.php?leftmenu=setup@holiday"); - // Dependencies $this->hidden = false; // A condition to hide module $this->depends = array(); // List of module class names as string that must be enabled if this module is enabled diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index 3d458247bcf..3080a184abb 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -1208,7 +1208,7 @@ if ($resql) { include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; if ($massaction == 'prevalidate') { - print $form->formconfirm($_SERVER["PHP_SELF"].$fieldstosearchall, $langs->trans("ConfirmMassValidation"), $langs->trans("ConfirmMassValidationQuestion"), "validate", null, '', 0, 200, 500, 1); + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassValidation"), $langs->trans("ConfirmMassValidationQuestion"), "validate", null, '', 0, 200, 500, 1); } if ($massaction == 'createbills') { diff --git a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php index ccf54b1d6d9..8232287b23b 100644 --- a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php +++ b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php @@ -114,7 +114,7 @@ class KnowledgeManagement extends DolibarrApi } if ($result < 0) { - throw new RestException(503, 'Error when retrieve category list : '.array_merge(array($categories->error), $categories->errors)); + throw new RestException(503, 'Error when retrieve category list : '.join(',', array_merge(array($categories->error), $categories->errors))); } return $result; diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 76ee11f727e..7a10293d7e4 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -595,7 +595,7 @@ class Products extends DolibarrApi } if ($result < 0) { - throw new RestException(503, 'Error when retrieve category list : '.array_merge(array($categories->error), $categories->errors)); + throw new RestException(503, 'Error when retrieve category list : '.join(',', array_merge(array($categories->error), $categories->errors))); } return $result; @@ -628,7 +628,7 @@ class Products extends DolibarrApi } if ($result < 0) { - throw new RestException(503, 'Error when retrieve prices list : '.array_merge(array($this->product->error), $this->product->errors)); + throw new RestException(503, 'Error when retrieve prices list : '.join(',', array_merge(array($this->product->error), $this->product->errors))); } return array( @@ -719,7 +719,7 @@ class Products extends DolibarrApi } if ($result < 0) { - throw new RestException(503, 'Error when retrieve prices list : '.array_merge(array($this->product->error), $this->product->errors)); + throw new RestException(503, 'Error when retrieve prices list : '.join(',', array_merge(array($this->product->error), $this->product->errors))); } return array( From 9319f56599dec6a4686833e9f2d6ec5dcf1e04e9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 03:10:37 +0100 Subject: [PATCH 151/816] Fix css --- htdocs/asset/tpl/linkedobjectblock.tpl.php | 4 ++-- htdocs/bom/tpl/linkedobjectblock.tpl.php | 4 ++-- htdocs/comm/propal/tpl/linkedobjectblock.tpl.php | 4 ++-- htdocs/commande/tpl/linkedobjectblock.tpl.php | 4 ++-- htdocs/compta/facture/tpl/linkedobjectblock.tpl.php | 2 +- .../facture/tpl/linkedobjectblockForRec.tpl.php | 2 +- htdocs/mrp/tpl/linkedobjectblock.tpl.php | 12 ++++++------ htdocs/reception/tpl/linkedobjectblock.tpl.php | 4 ++-- htdocs/theme/eldy/global.inc.php | 3 +++ htdocs/theme/md/style.css.php | 4 +++- htdocs/ticket/tpl/linkedobjectblock.tpl.php | 4 ++-- 11 files changed, 26 insertions(+), 21 deletions(-) diff --git a/htdocs/asset/tpl/linkedobjectblock.tpl.php b/htdocs/asset/tpl/linkedobjectblock.tpl.php index aef30995432..11d94714db8 100644 --- a/htdocs/asset/tpl/linkedobjectblock.tpl.php +++ b/htdocs/asset/tpl/linkedobjectblock.tpl.php @@ -46,12 +46,12 @@ foreach ($linkedObjectBlock as $key => $objectlink) { $trclass .= ' liste_sub_total'; } echo ''; - echo ''; + echo ''; echo ''; echo ''; echo ''; - echo ''; + echo ''; echo ''; - print ''; - print ''; + print ''; print ''; print ''; print ''; - echo ''; + echo ''; echo ''; echo ''; echo ''; - print ''; + print ''; print ''; print ''; print ' - + '; - echo ''; + echo ''; - echo ''; - echo ''; + echo ''; echo ''; echo ''; echo ''; - print ''; - print ''; + print ''; print ''; print ''; print ''; diff --git a/htdocs/reception/tpl/linkedobjectblock.tpl.php b/htdocs/reception/tpl/linkedobjectblock.tpl.php index 009534b91b5..341e30e3784 100644 --- a/htdocs/reception/tpl/linkedobjectblock.tpl.php +++ b/htdocs/reception/tpl/linkedobjectblock.tpl.php @@ -50,12 +50,12 @@ foreach ($linkedObjectBlock as $key => $objectlink) { } ?> - - + - - + Date: Fri, 30 Dec 2022 04:15:10 +0100 Subject: [PATCH 152/816] Merge branch '16.0' of git@github.com:Dolibarr/dolibarr.git into 16.0 --- htdocs/core/class/commonobject.class.php | 17 ++++++++++++++++- ...ace_20_modWorkflow_WorkflowManager.class.php | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 92fa8eff40b..b8cae867d71 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -3789,7 +3789,7 @@ abstract class CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Add objects linked in llx_element_element. + * Add an object link into llx_element_element. * * @param string $origin Linked element type * @param int $origin_id Linked element id @@ -4111,6 +4111,21 @@ abstract class CommonObject } } + /** + * Clear the cache saying that all linked object were already loaded. So next fetchObjectLinked will reload all links. + * + * @return int <0 if KO, >0 if OK + * @see fetchObjectLinked() + */ + public function clearObjectLinkedCache() + { + if ($this->id > 0 && !empty($this->linkedObjectsFullLoaded[$this->id])) { + unset($this->linkedObjectsFullLoaded[$this->id]); + } + + return 1; + } + /** * Update object linked of a current object * diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index 884790c990e..2fa476c25d8 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -90,6 +90,9 @@ class InterfaceWorkflowManager extends DolibarrTriggers $this->error = $newobject->error; $this->errors[] = $newobject->error; } + + $object->clearObjectLinkedCache(); + return $ret; } } @@ -111,6 +114,9 @@ class InterfaceWorkflowManager extends DolibarrTriggers $this->error = $newobject->error; $this->errors[] = $newobject->error; } + + $object->clearObjectLinkedCache(); + return $ret; } } From ed1c0897edf2f341acf6941c107fc5482fc9e3f0 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Fri, 30 Dec 2022 10:59:45 +0100 Subject: [PATCH 153/816] NEW copyrights --- htdocs/accountancy/class/accountancyexport.class.php | 3 ++- htdocs/accountancy/tpl/export_journal.tpl.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index e101c09abd3..a421d26eb70 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -5,7 +5,8 @@ * Copyright (C) 2015 Florian Henry * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Pierre-Henry Favre - * Copyright (C) 2016-2022 Open-DSI + * Copyright (C) 2016-2022 Alexandre Spangaro + * Copyright (C) 2022 Lionel Vessiller * Copyright (C) 2013-2017 Olivier Geffroy * Copyright (C) 2017 Elarifr. Ari Elbaz * Copyright (C) 2017-2019 Frédéric France diff --git a/htdocs/accountancy/tpl/export_journal.tpl.php b/htdocs/accountancy/tpl/export_journal.tpl.php index f57d54fcfbd..8e3c914a6f5 100644 --- a/htdocs/accountancy/tpl/export_journal.tpl.php +++ b/htdocs/accountancy/tpl/export_journal.tpl.php @@ -1,5 +1,6 @@ +/* Copyright (C) 2015-2022 Alexandre Spangaro + * Copyright (C) 2022 Lionel Vessiller * Copyright (C) 2016 Charlie Benke * Copyright (C) 2022 Progiseize * From 44215be43443062881c48b645563ed00149e0083 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Fri, 30 Dec 2022 11:10:11 +0100 Subject: [PATCH 154/816] FIX reload stickler-ci From 5b94ee35daaf680089adf90b20db405c4cfaaacd Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:04:55 +0100 Subject: [PATCH 155/816] update code toward php8 compliance --- htdocs/bom/tpl/objectline_create.tpl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index e644c7813e7..96a179b93f3 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -73,7 +73,7 @@ if ($nolinesbefore) { print ''; if ($filtertype != 1) { - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { print ''; From e5f08f69840a22e4a7cdd9e4a02a97f089b355e8 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:07:05 +0100 Subject: [PATCH 156/816] update code toward php8 compliance --- htdocs/bom/tpl/objectline_edit.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/bom/tpl/objectline_edit.tpl.php b/htdocs/bom/tpl/objectline_edit.tpl.php index 88463996ebc..969b210e89b 100644 --- a/htdocs/bom/tpl/objectline_edit.tpl.php +++ b/htdocs/bom/tpl/objectline_edit.tpl.php @@ -126,7 +126,7 @@ if (($line->info_bits & 2) != 2) { print ''; if ($filtertype != 1) { - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $coldisplay++; print ''; From 32c161e576f40ab4100f9d35200528a7ed7ab486 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 12:10:23 +0100 Subject: [PATCH 157/816] Fix warnings --- htdocs/accountancy/class/accountancycategory.class.php | 4 ++-- htdocs/api/index.php | 4 ++-- htdocs/blockedlog/class/authority.class.php | 2 +- htdocs/core/class/dolgeoip.class.php | 4 ++-- htdocs/emailcollector/class/emailcollector.class.php | 2 +- htdocs/mailmanspip/class/mailmanspip.class.php | 8 +++----- htdocs/product/class/html.formproduct.class.php | 6 ++---- htdocs/webservices/server_productorservice.php | 2 +- 8 files changed, 14 insertions(+), 18 deletions(-) diff --git a/htdocs/accountancy/class/accountancycategory.class.php b/htdocs/accountancy/class/accountancycategory.class.php index 300ccff9c09..e6c4ff45922 100644 --- a/htdocs/accountancy/class/accountancycategory.class.php +++ b/htdocs/accountancy/class/accountancycategory.class.php @@ -446,7 +446,7 @@ class AccountancyCategory // extends CommonObject } else { $this->error = "Error ".$this->db->lasterror(); $this->errors[] = $this->error; - dol_syslog(__METHOD__." ".implode(','.$this->errors), LOG_ERR); + dol_syslog(__METHOD__." ".implode(',', $this->errors), LOG_ERR); return -1; } @@ -488,7 +488,7 @@ class AccountancyCategory // extends CommonObject } else { $this->error = "Error ".$this->db->lasterror(); $this->errors[] = $this->error; - dol_syslog(__METHOD__." ".implode(','.$this->errors), LOG_ERR); + dol_syslog(__METHOD__." ".implode(',', $this->errors), LOG_ERR); return -1; } diff --git a/htdocs/api/index.php b/htdocs/api/index.php index 085dd338e69..ba195b82c08 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -413,9 +413,9 @@ $result = $api->r->handle(); if (Luracast\Restler\Defaults::$returnResponse) { // We try to compress the data received data - if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && is_callable('brotli_compress')) { + if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && is_callable('brotli_compress') && defined('BROTLI_TEXT')) { header('Content-Encoding: br'); - $result = brotli_compress($result, 11, BROTLI_TEXT); + $result = brotli_compress($result, 11, constant('BROTLI_TEXT')); } elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'bz') !== false && is_callable('bzcompress')) { header('Content-Encoding: bz'); $result = bzcompress($result, 9); diff --git a/htdocs/blockedlog/class/authority.class.php b/htdocs/blockedlog/class/authority.class.php index 7240aaf0151..0b665fedc3e 100644 --- a/htdocs/blockedlog/class/authority.class.php +++ b/htdocs/blockedlog/class/authority.class.php @@ -304,7 +304,7 @@ class BlockedLogAuthority $url = $conf->global->BLOCKEDLOG_AUTHORITY_URL.'/blockedlog/ajax/authority.php?s='.$signature.'&b='.$block->signature; $res = getURLContent($url); - echo $block->signature.' '.$url.' '.$res.'
'; + echo $block->signature.' '.$url.' '.$res['content'].'
'; if ($res === 'blockalreadyadded' || $res === 'blockadded') { $block->setCertified(); } else { diff --git a/htdocs/core/class/dolgeoip.class.php b/htdocs/core/class/dolgeoip.class.php index b4218bbfd40..24726fec7c3 100644 --- a/htdocs/core/class/dolgeoip.class.php +++ b/htdocs/core/class/dolgeoip.class.php @@ -86,8 +86,8 @@ class DolGeoIP dol_syslog('DolGeoIP '.$this->errorlabel, LOG_ERR); return 0; } - } elseif (function_exists('geoip_open')) { - $this->gi = geoip_open($datfile, GEOIP_STANDARD); + } elseif (function_exists('geoip_open') && defined('GEOIP_STANDARD')) { + $this->gi = geoip_open($datfile, constant('GEOIP_STANDARD')); } elseif (function_exists('geoip_country_code_by_name')) { $this->gi = 'NOGI'; // We are using embedded php geoip functions //print 'function_exists(geoip_country_code_by_name))='.function_exists('geoip_country_code_by_name'); diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 8d72666ad53..4d7ef042e69 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2305,7 +2305,7 @@ class EmailCollector extends CommonObject 'class' => 'compta/facture/class/facture.class.php', 'object' => 'Facture'), 'fournisseur/facture' => array('table' => 'facture_fourn', - 'fields' => array('ref', ref_client), + 'fields' => array('ref', 'ref_client'), 'class' => 'fourn/class/fournisseur.facture.class.php', 'object' => 'FactureFournisseur'), 'produit' => array('table' => 'product', diff --git a/htdocs/mailmanspip/class/mailmanspip.class.php b/htdocs/mailmanspip/class/mailmanspip.class.php index bcfb1b83d6e..46701a459a6 100644 --- a/htdocs/mailmanspip/class/mailmanspip.class.php +++ b/htdocs/mailmanspip/class/mailmanspip.class.php @@ -77,7 +77,7 @@ class MailmanSpip */ public function isSpipEnabled() { - if (defined("ADHERENT_USE_SPIP") && (ADHERENT_USE_SPIP == 1)) { + if (getDolGlobalInt("ADHERENT_USE_SPIP") == 1) { return true; } @@ -91,10 +91,8 @@ class MailmanSpip */ public function checkSpipConfig() { - if (defined('ADHERENT_SPIP_SERVEUR') && defined('ADHERENT_SPIP_USER') && defined('ADHERENT_SPIP_PASS') && defined('ADHERENT_SPIP_DB')) { - if (ADHERENT_SPIP_SERVEUR != '' && ADHERENT_SPIP_USER != '' && ADHERENT_SPIP_PASS != '' && ADHERENT_SPIP_DB != '') { - return true; - } + if (getDolGlobalString('ADHERENT_SPIP_SERVEUR') != '' && getDolGlobalString('ADHERENT_SPIP_USER') != '' && getDolGlobalString('ADHERENT_SPIP_PASS') != '' && getDolGlobalString('ADHERENT_SPIP_DB') != '') { + return true; } return false; diff --git a/htdocs/product/class/html.formproduct.class.php b/htdocs/product/class/html.formproduct.class.php index 75a929f53e5..b4da53f4635 100644 --- a/htdocs/product/class/html.formproduct.class.php +++ b/htdocs/product/class/html.formproduct.class.php @@ -781,9 +781,7 @@ class FormProduct */ public function selectLotDataList($htmlname = 'batch_id', $empty = 0, $fk_product = 0, $fk_entrepot = 0, $objectLines = array()) { - global $conf, $langs; - - dol_syslog(get_class($this)."::selectLotDataList $htmlname, $empty, $fk_product, $fk_entrepot,$objectLines", LOG_DEBUG); + dol_syslog(get_class($this)."::selectLotDataList $htmlname, $empty, $fk_product, $fk_entrepot", LOG_DEBUG); $out = ''; $productIdArray = array(); @@ -817,7 +815,7 @@ class FormProduct if (empty($fk_entrepot) || $fk_entrepot == $arraytypes['entrepot_id']) { $label = $arraytypes['entrepot_label'] . ' - '; $label .= $arraytypes['batch']; - $out .= ''; + $out .= ''; } } } diff --git a/htdocs/webservices/server_productorservice.php b/htdocs/webservices/server_productorservice.php index 25eeec6430f..bf46b063e64 100644 --- a/htdocs/webservices/server_productorservice.php +++ b/htdocs/webservices/server_productorservice.php @@ -962,7 +962,7 @@ function getListOfProductsOrServices($authentication, $filterproduct) * Get list of products for a category * * @param array $authentication Array of authentication information - * @param array $id Category id + * @param int $id Category id * @param Translate $lang Force lang * @return array Array result */ From 8abde17e954f17ff94d84a32865cfa566c407aac Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 12:15:18 +0100 Subject: [PATCH 158/816] Fix warning --- htdocs/core/modules/DolibarrModules.class.php | 4 ++-- htdocs/product/card.php | 4 ++-- qodana.yaml | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 7297b17a6b7..afc19a12e92 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -299,10 +299,10 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it public $picto; /** - * @var string[] List of config pages + * @var string[]|string List of config pages (Old modules uses a string. New one must use an array) * * Name of php pages stored into module/admin directory, used to setup module. - * e.g.: "admin.php@module" + * e.g.: array("setup.php@mymodule") */ public $config_page_url; diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 5574984b5fd..031dccadc53 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -541,7 +541,7 @@ if (empty($reshook)) { if ($result < 0) { $error++; $mesg = 'Failed to get bar code type information '; - setEventMessages($mesg.$stdobject->error, $mesg.$stdobject->errors, 'errors'); + setEventMessages($mesg.$stdobject->error, $stdobject->errors, 'errors'); } $object->barcode_type_code = $stdobject->barcode_type_code; $object->barcode_type_coder = $stdobject->barcode_type_coder; @@ -780,7 +780,7 @@ if (empty($reshook)) { if ($result < 0) { $error++; $mesg = 'Failed to get bar code type information '; - setEventMessages($mesg.$stdobject->error, $mesg.$stdobject->errors, 'errors'); + setEventMessages($mesg.$stdobject->error, $stdobject->errors, 'errors'); } $object->barcode_type_code = $stdobject->barcode_type_code; $object->barcode_type_coder = $stdobject->barcode_type_coder; diff --git a/qodana.yaml b/qodana.yaml index 08dc6c18395..b1a76747a5b 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -61,4 +61,5 @@ exclude: - name: PhpClassConstantAccessedViaChildClassInspection - name: RegExpUnnecessaryNonCapturingGroup - name: PhpPregMatchReplaceWithComparisonInspection - - name: PhpArrayWriteIsNotUsedInspection \ No newline at end of file + - name: PhpArrayWriteIsNotUsedInspection + - name: PhpUndefinedNamespaceInspection \ No newline at end of file From c6dc5989445d78e9e47998ff3b4694799abedd10 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 12:39:09 +0100 Subject: [PATCH 159/816] Add qodana as github action --- .github/workflows/code_quality.yml | 18 ++++++++++++++++++ .../{exakat.yml => exakat.yml.disabled} | 0 2 files changed, 18 insertions(+) create mode 100644 .github/workflows/code_quality.yml rename .github/workflows/{exakat.yml => exakat.yml.disabled} (100%) diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml new file mode 100644 index 00000000000..ef097e161e7 --- /dev/null +++ b/.github/workflows/code_quality.yml @@ -0,0 +1,18 @@ +name: Qodana +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + - 'releases/*' + +jobs: + qodana: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: 'Qodana Scan' + uses: JetBrains/qodana-action@v2022.3.0 diff --git a/.github/workflows/exakat.yml b/.github/workflows/exakat.yml.disabled similarity index 100% rename from .github/workflows/exakat.yml rename to .github/workflows/exakat.yml.disabled From 218f1c8cc3968c43f2a3a04dee05263c3c9bd160 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 12:40:01 +0100 Subject: [PATCH 160/816] Fix qodana script --- .github/workflows/code_quality.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index ef097e161e7..e39ffc4fa12 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -4,8 +4,7 @@ on: pull_request: push: branches: - - main - - 'releases/*' + - develop jobs: qodana: From 081cfcc137aadfe986b0e31ce291b8c198c9a566 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 12:42:45 +0100 Subject: [PATCH 161/816] Add missing secret key --- .github/workflows/code_quality.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index e39ffc4fa12..b27b64428e7 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -15,3 +15,5 @@ jobs: fetch-depth: 0 - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2022.3.0 + env: + QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} \ No newline at end of file From f6765fcd982c1d65849fb79f1875c0d5a5ac913f Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:43:12 +0100 Subject: [PATCH 162/816] update code toward php8 compliance --- htdocs/bom/tpl/objectline_title.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/bom/tpl/objectline_title.tpl.php b/htdocs/bom/tpl/objectline_title.tpl.php index 5252baf61ca..0ede4190279 100644 --- a/htdocs/bom/tpl/objectline_title.tpl.php +++ b/htdocs/bom/tpl/objectline_title.tpl.php @@ -67,7 +67,7 @@ print ''; print '
'; if ($filtertype != 1) { - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { print ''; } From 4c51b2bb6bdca3d1ae70d720d569a9fbec117c49 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:43:57 +0100 Subject: [PATCH 163/816] update code toward php8 compliance --- htdocs/bom/tpl/objectline_view.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index b7087b27288..d20692ac99a 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -119,7 +119,7 @@ echo price($line->qty, 0, '', 0, 0); // Yes, it is a quantity, not a price, but print ''; if ($filtertype != 1) { - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { print ''; //} print ''; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { print ''; } print ''; @@ -1594,7 +1594,7 @@ if ($action == 'create') { // Quantity print ''; // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { print ''; } // Discount @@ -1739,7 +1739,7 @@ if ($action == 'create') { print ''; // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { print ''; @@ -1765,7 +1765,7 @@ if ($action == 'create') { if (isModEnabled('margin') && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) { $colspan++; } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $colspan++; } From c46e55aaeb503ad5a4d94dfda28eee67073f4ec2 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:45:22 +0100 Subject: [PATCH 165/816] update code toward php8 compliance --- 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 82012400f68..076a9682ff5 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -651,7 +651,7 @@ abstract class CommonDocGenerator ); // Units - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $resarray['line_unit'] = $outputlangs->trans($line->getLabelOfUnit('long')); $resarray['line_unit_short'] = $outputlangs->trans($line->getLabelOfUnit('short')); } From 5f3cea32f1d2ff8caf29f0d9331a8efd2a27e553 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:45:54 +0100 Subject: [PATCH 166/816] update code toward php8 compliance --- htdocs/core/class/commonobject.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index d9b86ae01da..2a7fb703dac 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5100,7 +5100,7 @@ abstract class CommonObject print ''; } print ''; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { print ''; } print ''; @@ -5238,7 +5238,7 @@ abstract class CommonObject $this->tpl['total_ht'] = price($line->total_ht); $this->tpl['multicurrency_price'] = price($line->multicurrency_subprice); $this->tpl['qty'] = (($line->info_bits & 2) != 2) ? $line->qty : ' '; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->tpl['unit'] = $langs->transnoentities($line->getLabelOfUnit('long')); } $this->tpl['remise_percent'] = (($line->info_bits & 2) != 2) ? vatrate($line->remise_percent, true) : ' '; From 6617d595a6b1ed76e08aebdcfdf7280fee0cb96b Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:46:43 +0100 Subject: [PATCH 167/816] update code toward php8 compliance --- htdocs/core/class/html.form.class.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index f3a566b6014..d7ce577acb6 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2545,7 +2545,7 @@ class Form $outarray = array(); // Units - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $langs->load('other'); } @@ -2589,7 +2589,7 @@ class Form $selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref"; } // Units - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units"; $selectFields .= ', unit_long, unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units'; } @@ -2634,7 +2634,7 @@ class Form $sql .= " LEFT JOIN ".$this->db->prefix()."product_customer_price as pcp ON pcp.fk_soc=".((int) $socid)." AND pcp.fk_product=p.rowid"; } // Units - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $sql .= " LEFT JOIN ".$this->db->prefix()."c_units u ON u.rowid = p.fk_unit"; } // Multilang : we add translation @@ -2941,7 +2941,7 @@ class Form // Units $outvalUnits = ''; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { if (!empty($objp->unit_short)) { $outvalUnits .= ' - '.$objp->unit_short; } @@ -3277,7 +3277,7 @@ class Form $langs->load('stocks'); // Units - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $langs->load('other'); } @@ -3292,7 +3292,7 @@ class Form $sql .= ", p.description"; } // Units - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $sql .= ", u.label as unit_long, u.short_label as unit_short, p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units, p.surface, p.surface_units, p.volume, p.volume_units"; } if (isModEnabled('barcode')) { @@ -3305,7 +3305,7 @@ class Form } $sql .= " LEFT JOIN ".$this->db->prefix()."societe as s ON pfp.fk_soc = s.rowid"; // Units - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $sql .= " LEFT JOIN ".$this->db->prefix()."c_units u ON u.rowid = p.fk_unit"; } $sql .= " WHERE p.entity IN (".getEntity('product').")"; @@ -3398,7 +3398,7 @@ class Form // Units $outvalUnits = ''; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { if (!empty($objp->unit_short)) { $outvalUnits .= ' - '.$objp->unit_short; } From 19796c9db1da40a0a8ff51aa27e9accfe9b04d20 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:47:18 +0100 Subject: [PATCH 168/816] update code toward php8 compliance --- htdocs/core/modules/modProduct.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index 5224f82a2f5..16906c95f86 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -233,7 +233,7 @@ class modProduct extends DolibarrModules if (getDolGlobalInt('MAIN_MULTILANGS')) { $this->export_fields_array[$r] = array_merge($this->export_fields_array[$r], array('l.lang'=>'Language', 'l.label'=>'TranslatedLabel', 'l.description'=>'TranslatedDescription', 'l.note'=>'TranslatedNote')); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->export_fields_array[$r]['p.fk_unit'] = 'Unit'; } $this->export_TypeFields_array[$r] = array( @@ -640,7 +640,7 @@ class modProduct extends DolibarrModules if (isModEnabled('barcode')) { $this->import_fields_array[$r] = array_merge($this->import_fields_array[$r], array('p.barcode'=>'BarCode')); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->import_fields_array[$r]['p.fk_unit'] = 'Unit'; } @@ -724,7 +724,7 @@ class modProduct extends DolibarrModules if (isModEnabled('barcode')) { $import_sample = array_merge($import_sample, array('p.barcode'=>'')); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $import_sample = array_merge( $import_sample, array( From 7cc97b2b09a11210d3e64906402ebe1418f75fc6 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:47:52 +0100 Subject: [PATCH 169/816] update code toward php8 compliance --- htdocs/core/modules/modService.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index 868303c231b..a316c746acb 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -198,7 +198,7 @@ class modService extends DolibarrModules if (getDolGlobalInt('MAIN_MULTILANGS')) { $this->export_fields_array[$r] = array_merge($this->export_fields_array[$r], array('l.lang'=>'Language', 'l.label'=>'TranslatedLabel', 'l.description'=>'TranslatedDescription', 'l.note'=>'TranslatedNote')); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->export_fields_array[$r]['p.fk_unit'] = 'Unit'; } $this->export_TypeFields_array[$r] = array( @@ -587,7 +587,7 @@ class modService extends DolibarrModules if (isModEnabled('barcode')) { $this->import_fields_array[$r] = array_merge($this->import_fields_array[$r], array('p.barcode'=>'BarCode')); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->import_fields_array[$r]['p.fk_unit'] = 'Unit'; } // Add extra fields @@ -678,7 +678,7 @@ class modService extends DolibarrModules if (isModEnabled('barcode')) { $import_sample = array_merge($import_sample, array('p.barcode'=>'')); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $import_sample = array_merge( $import_sample, array( From 9d5670faa8a2849aed650cce66d25c08caa28be3 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:48:27 +0100 Subject: [PATCH 170/816] update code toward php8 compliance --- htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php b/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php index 2bdda4421dc..8ebd1051a06 100644 --- a/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php +++ b/htdocs/core/modules/asset/doc/pdf_standard_asset.modules.php @@ -1319,7 +1319,7 @@ class pdf_standard_asset extends ModelePDFAsset ), 'border-left' => true, // add left line separator ); - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->cols['unit']['status'] = true; } From e8fe061071d0a322d8fa45ff78869993264612a3 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:49:02 +0100 Subject: [PATCH 171/816] update code toward php8 compliance --- htdocs/core/modules/commande/doc/pdf_einstein.modules.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index 4bfb6f93413..6fe07506958 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -173,7 +173,7 @@ class pdf_einstein extends ModelePDFCommandes // Define position of columns $this->posxdesc = $this->marge_gauche + 1; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->posxtva = 101; $this->posxup = 118; $this->posxqty = 135; @@ -509,7 +509,7 @@ class pdf_einstein extends ModelePDFCommandes $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); $pdf->SetXY($this->posxunit, $curY); $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); @@ -1238,7 +1238,7 @@ class pdf_einstein extends ModelePDFCommandes $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); if (empty($hidetop)) { $pdf->SetXY($this->posxunit - 1, $tab_top + 1); From c3d75cb1d4ac561f8e5365b4f1d3994677595e91 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:49:31 +0100 Subject: [PATCH 172/816] update code toward php8 compliance --- htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php index 584795d37e6..8614238c2c7 100644 --- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php @@ -1866,7 +1866,7 @@ class pdf_eratosthene extends ModelePDFCommandes ), 'border-left' => true, // add left line separator ); - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->cols['unit']['status'] = true; } From 9ad1f6df196ceff263aca7490c8e4bed32a897fb Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:50:17 +0100 Subject: [PATCH 173/816] update code toward php8 compliance --- htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 20504da255c..f223771900b 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -180,7 +180,7 @@ class pdf_crabe extends ModelePDFFactures // Define position of columns $this->posxdesc = $this->marge_gauche + 1; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->posxtva = 101; $this->posxup = 118; $this->posxqty = 135; @@ -677,7 +677,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); $pdf->SetXY($this->posxunit, $curY); $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); @@ -1710,7 +1710,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); if (empty($hidetop)) { $pdf->SetXY($this->posxunit - 1, $tab_top + 1); From e3b724b6fa5022e4bd074db42a1778e3a806831c Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:50:42 +0100 Subject: [PATCH 174/816] update code toward php8 compliance --- htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 5a206410aa7..e61d438c8a5 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -2593,7 +2593,7 @@ class pdf_sponge extends ModelePDFFactures ), 'border-left' => true, // add left line separator ); - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->cols['unit']['status'] = true; } From a990d4df19c3e20749fdd3a31e45209d5d788b02 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:52:20 +0100 Subject: [PATCH 175/816] update code toward php8 compliance --- htdocs/core/modules/propale/doc/pdf_azur.modules.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 6b16ac1c1b0..ff5283e2bb8 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -169,7 +169,7 @@ class pdf_azur extends ModelePDFPropales // Define position of columns $this->posxdesc = $this->marge_gauche + 1; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->posxtva = 101; $this->posxup = 118; $this->posxqty = 135; @@ -620,7 +620,7 @@ class pdf_azur extends ModelePDFPropales $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); $pdf->SetXY($this->posxunit, $curY); $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); @@ -1437,7 +1437,7 @@ class pdf_azur extends ModelePDFPropales $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); if (empty($hidetop)) { $pdf->SetXY($this->posxunit - 1, $tab_top + 1); From 42e8740a8d9a501c972899dffceb4480309e6b45 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:53:07 +0100 Subject: [PATCH 176/816] update code toward php8 compliance --- htdocs/core/modules/propale/doc/pdf_cyan.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index 2cf90351cd0..753e1511197 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -2009,7 +2009,7 @@ class pdf_cyan extends ModelePDFPropales ), 'border-left' => true, // add left line separator ); - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->cols['unit']['status'] = true; } From 5f240db64d6e6adf4729ae9a06c9664d09c2014e Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:53:42 +0100 Subject: [PATCH 177/816] update code toward php8 compliance --- .../modules/supplier_invoice/doc/pdf_canelle.modules.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php b/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php index f81cc03009b..802abd6a184 100644 --- a/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php +++ b/htdocs/core/modules/supplier_invoice/doc/pdf_canelle.modules.php @@ -161,7 +161,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $this->posxdiscount = 162; $this->postotalht = 174; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->posxtva = 99; $this->posxup = 114; $this->posxqty = 130; @@ -480,7 +480,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); $pdf->SetXY($this->posxunit, $curY); $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); @@ -932,7 +932,7 @@ class pdf_canelle extends ModelePDFSuppliersInvoices $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); if (empty($hidetop)) { $pdf->SetXY($this->posxunit - 1, $tab_top + 1); From 44182f6e50dbda98b3fd8a1da15fc9366367286d Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:54:28 +0100 Subject: [PATCH 178/816] update code toward php8 compliance --- htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php index c83863339c2..186ea465568 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php @@ -1623,7 +1623,7 @@ class pdf_cornas extends ModelePDFSuppliersOrders ), 'border-left' => true, // add left line separator ); - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->cols['unit']['status'] = true; } From b2f1ac3c73e198d73509df4c18eb8c97b3535534 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:55:00 +0100 Subject: [PATCH 179/816] update code toward php8 compliance --- .../modules/supplier_order/doc/pdf_muscadet.modules.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php index 5754561c707..226c9dc6efa 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php @@ -169,7 +169,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $this->posxdiscount = 162; $this->postotalht = 174; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->posxtva = 95; $this->posxup = 114; $this->posxqty = 132; @@ -552,7 +552,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); $pdf->SetXY($this->posxunit, $curY); $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); @@ -1097,7 +1097,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); if (empty($hidetop)) { $pdf->SetXY($this->posxunit - 1, $tab_top + 1); From 5256f30c3d3dbbbb9d4a3c4733c024c5ecd965be Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:55:28 +0100 Subject: [PATCH 180/816] update code toward 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 c844aec2c61..8e25a227ad7 100644 --- a/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/pdf_aurore.modules.php @@ -167,7 +167,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $this->posxdiscount = 162; $this->postotalht = 174; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $this->posxup = 112; $this->posxqty = 135; $this->posxunit = 151; @@ -527,7 +527,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $pdf->MultiCell($this->posxunit - $this->posxqty - 0.8, 4, $qty, 0, 'R'); // Enough for 6 chars // Unit - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $unit = pdf_getlineunit($object, $i, $outputlangs, $hidedetails, $hookmanager); $pdf->SetXY($this->posxunit, $curY); $pdf->MultiCell($this->posxdiscount - $this->posxunit - 0.8, 4, $unit, 0, 'L'); @@ -1200,7 +1200,7 @@ class pdf_aurore extends ModelePDFSupplierProposal $pdf->MultiCell($this->posxunit - $this->posxqty - 1, 2, $outputlangs->transnoentities("Qty"), '', 'C'); } - if (!empty($conf->global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $pdf->line($this->posxunit - 1, $tab_top, $this->posxunit - 1, $tab_top + $tab_height); if (empty($hidetop)) { $pdf->SetXY($this->posxunit - 1, $tab_top + 1); From b407712e5aae4996e12e6fca56ea6ffb90eb022c Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:55:53 +0100 Subject: [PATCH 181/816] update code toward php8 compliance --- htdocs/core/tpl/objectline_create.tpl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index f008aacc10e..8c6cf1b9b7a 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -127,7 +127,7 @@ if ($nolinesbefore) { global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { print 'global->PRODUCT_USE_UNITS)) { + if (getDolGlobalInt('PRODUCT_USE_UNITS')) { $coldisplay++; print ''; } diff --git a/htdocs/asset/admin/setup.php b/htdocs/asset/admin/setup.php index 965566c3a74..deb4b0da346 100644 --- a/htdocs/asset/admin/setup.php +++ b/htdocs/asset/admin/setup.php @@ -473,14 +473,14 @@ if ($action == 'edit') { if ($val['type'] == 'textarea') { print '\n"; } elseif ($val['type']== 'html') { require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; - $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); + $doleditor = new DolEditor($constname, getDolGlobalString($constname), '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); $doleditor->Create(); } elseif ($val['type'] == 'yesno') { - print $form->selectyesno($constname, $conf->global->{$constname}, 1); + print $form->selectyesno($constname, getDolGlobalString($constname), 1); } elseif (preg_match('/emailtemplate:/', $val['type'])) { include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; $formmail = new FormMail($db); @@ -500,7 +500,7 @@ if ($action == 'edit') { $arrayofmessagename[$modelmail->id] = $langs->trans(preg_replace('/\(|\)/', '', $modelmail->label)) . $moreonlabel; } } - print $form->selectarray($constname, $arrayofmessagename, $conf->global->{$constname}, 'None', 0, 0, '', 0, 0, 0, '', '', 1); + print $form->selectarray($constname, $arrayofmessagename, getDolGlobalString($constname), 'None', 0, 0, '', 0, 0, 0, '', '', 1); } elseif (preg_match('/category:/', $val['type'])) { require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; @@ -508,11 +508,11 @@ if ($action == 'edit') { $tmp = explode(':', $val['type']); print img_picto('', 'category', 'class="pictofixedwidth"'); - print $formother->select_categories($tmp[1], $conf->global->{$constname}, $constname, 0, $langs->trans('CustomersProspectsCategoriesShort')); + print $formother->select_categories($tmp[1], getDolGlobalString($constname), $constname, 0, $langs->trans('CustomersProspectsCategoriesShort')); } elseif (preg_match('/thirdparty_type/', $val['type'])) { require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; $formcompany = new FormCompany($db); - print $formcompany->selectProspectCustomerType($conf->global->{$constname}, $constname); + print $formcompany->selectProspectCustomerType(getDolGlobalString($constname), $constname); } elseif ($val['type'] == 'securekey') { print ''; if (!empty($conf->use_javascript_ajax)) { @@ -524,11 +524,11 @@ if ($action == 'edit') { print dolJSToSetRandomPassword($constname, 'generate_token'.$constname); } elseif ($val['type'] == 'product') { if (isModEnabled("product") || isModEnabled("service")) { - $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); + $selected = getDolGlobalString($constname); $form->select_produits($selected, $constname, '', 0); } } elseif ($val['type'] == 'accountancy_code') { - $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); + $selected = getDolGlobalString($constname); if (isModEnabled('accounting')) { require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php'; $formaccounting = new FormAccounting($db); @@ -537,7 +537,7 @@ if ($action == 'edit') { print ''; } } elseif ($val['type'] == 'accountancy_category') { - $selected = (empty($conf->global->$constname) ? '' : $conf->global->$constname); + $selected = getDolGlobalString($constname); if (isModEnabled('accounting')) { print ''; // autosuggest from existing account types if found @@ -587,9 +587,9 @@ if ($action == 'edit') { print '"; if ($tmpobj->total_ttc < 0) { print '"; - }; + } if ($tmpobj->total_ttc >= 0) { print '"; - }; + } print ''; print ""; } diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index e28e5427c0b..14f82abe1a4 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3357,7 +3357,7 @@ if ($action == 'create') { jQuery(".checkforselect").prop("disabled", false); jQuery(".checkforselect").prop("checked", true); } - }; + } }); '; @@ -3780,7 +3780,7 @@ if ($action == 'create') { if ($soc->fetch_optionals() > 0) { $object->array_options = array_merge($object->array_options, $soc->array_options); } - }; + } print $object->showOptionals($extrafields, 'create', $parameters); } diff --git a/htdocs/compta/tva/card.php b/htdocs/compta/tva/card.php index e7c7678b818..1cd655603bc 100644 --- a/htdocs/compta/tva/card.php +++ b/htdocs/compta/tva/card.php @@ -405,7 +405,7 @@ if ($action == 'create') { $("#label_type_payment").removeClass("fieldrequired"); $(".hide_if_no_auto_create_payment").hide(); } - }; + } $("#radiopayment").click(function() { $("#label").val($(this).data("label")); }); diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 82012400f68..88ee43fd713 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -687,7 +687,7 @@ abstract class CommonDocGenerator $resql = $this->db->fetch_object($resql); foreach ($extralabels as $key => $label) { - $resarray['line_product_supplier_'.$key] = $resql->{$key}; + $resarray['line_product_supplier_'.$key] = $resql->$key; } } } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 686d500875a..a6eac03cadc 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -8228,7 +8228,7 @@ class Form return { q: params.term, // search term page: params.page - }; + } }, processResults: function (data) { // parse the results into the format expected by Select2. @@ -8480,14 +8480,14 @@ class Form $out .= 'function formatResult(record, container) {'."\n"; $out .= ' if ($(record.element).attr("data-html") != undefined) return htmlEntityDecodeJs($(record.element).attr("data-html")); // If property html set, we decode html entities and use this'."\n"; $out .= ' return record.text;'; - $out .= '};'."\n"; + $out .= '}'."\n"; $out .= 'function formatSelection(record) {'."\n"; if ($elemtype == 'category') { $out .= 'return \' \'+record.text+\'\';'; } else { $out .= 'return record.text;'; } - $out .= '};'."\n"; + $out .= '}'."\n"; $out .= '$(document).ready(function () { $(\'#'.$htmlname.'\').'.$tmpplugin.'({'; if ($placeholder) { diff --git a/htdocs/core/class/html.formactions.class.php b/htdocs/core/class/html.formactions.class.php index 364a638e13f..90c9857992a 100644 --- a/htdocs/core/class/html.formactions.class.php +++ b/htdocs/core/class/html.formactions.class.php @@ -115,7 +115,7 @@ class FormActions $('.hideifna').show(); } else { - if (defaultvalue == 50 && (percentage.val() == 0 || percentage.val() == 100)) { percentage.val(50) }; + if (defaultvalue == 50 && (percentage.val() == 0 || percentage.val() == 100)) { percentage.val(50); } percentage.removeAttr('disabled'); $('.hideifna').show(); } diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 5f27cbf3477..82ab8031155 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -690,7 +690,7 @@ class FormCompany extends Form } } ); - }; + } }); '; } diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index c57ee0c5106..eb389454f82 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -662,7 +662,7 @@ class FormSetupItem { global $conf; if (isset($conf->global->{$this->confKey})) { - $this->fieldValue = $conf->global->{$this->confKey}; + $this->fieldValue = getDolGlobalString($this->confKey); return true; } else { $this->fieldValue = null; diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index eb0c7668d8c..0aa2c39de91 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -362,7 +362,7 @@ class FormTicket print ''; } diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index e1699660acc..f204acd4747 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -1039,4 +1039,4 @@ class ImportCsv extends ModeleImports function cleansep($value) { return str_replace(array(',', ';'), '/', $value); -}; +} diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index f008aacc10e..69e5795a881 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -511,7 +511,7 @@ if ((isModEnabled("service") || ($object->element == 'contrat')) && $dateSelecto print $form->selectDate($date_start, 'date_start', empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? 0 : 1, empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? 0 : 1, 1, "addproduct", 1, 0); print ' '.$langs->trans('to').' '; print $form->selectDate($date_end, 'date_end', empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? 0 : 1, empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? 0 : 1, 1, "addproduct", 1, 0); - }; + } if ($prefillDates) { echo ' '.$langs->trans('FillWithLastServiceDates').''; diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index b193048047a..43262e4f3e3 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -2212,7 +2212,7 @@ if ($action == 'create') { jQuery(".checkforselect").prop("disabled", false); jQuery(".checkforselect").prop("checked", true); } - }; + } }); '; diff --git a/htdocs/hrm/compare.php b/htdocs/hrm/compare.php index 686d5820695..d1dde23a63c 100644 --- a/htdocs/hrm/compare.php +++ b/htdocs/hrm/compare.php @@ -319,11 +319,11 @@ function rate(&$TMergedSkills, $field) foreach ($TMergedSkills as $id => &$sk) { $class = "note"; $how_many = 0; - if (empty($sk->{$field})) { + if (empty($sk->$field)) { $note = 'x'; $class .= ' none'; } else { - $note = $sk->{$field}; + $note = $sk->$field; $how_many = ($field === 'rate1') ? $sk->how_many_max1 : $sk->how_many_max2; } diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index 9a33bd25c05..579fdb74c4a 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -1354,7 +1354,7 @@ if ($step == 4 && $datatoimport) { print ' $("select.targetselectchange").find(\'option[value="\'+value+\'"]:not(:selected)\').prop("disabled", true);'."\n"; // Set to disabled except if currently selected print ' }'."\n"; print ' });'."\n"; - print '};'."\n"; + print '}'."\n"; // Function to save the selection in database print 'function saveSelection() {'."\n"; @@ -1402,7 +1402,7 @@ if ($step == 4 && $datatoimport) { } "; - print '};'."\n"; + print '}'."\n"; // If we make a change on a selectbox print '$(".targetselectchange").change(function(){'."\n"; diff --git a/htdocs/index.php b/htdocs/index.php index 06a829ea4b5..e0001adba5e 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -806,23 +806,15 @@ function getWeatherStatus($totallate) $used_conf = empty($conf->global->MAIN_USE_METEO_WITH_PERCENTAGE) ? 'MAIN_METEO_LEVEL' : 'MAIN_METEO_PERCENTAGE_LEVEL'; - $level0 = $offset; $weather->level = 0; - if (!empty($conf->global->{$used_conf.'0'})) { - $level0 = $conf->global->{$used_conf.'0'}; - } + $level0 = $offset; + $level0 = getDolGlobalString($used_conf.'0', $level0); $level1 = $offset + 1 * $factor; - if (!empty($conf->global->{$used_conf.'1'})) { - $level1 = $conf->global->{$used_conf.'1'}; - } + $level1 = getDolGlobalString($used_conf.'1', $level1); $level2 = $offset + 2 * $factor; - if (!empty($conf->global->{$used_conf.'2'})) { - $level2 = $conf->global->{$used_conf.'2'}; - } + $level2 = getDolGlobalString($used_conf.'2', $level2); $level3 = $offset + 3 * $factor; - if (!empty($conf->global->{$used_conf.'3'})) { - $level3 = $conf->global->{$used_conf.'3'}; - } + $level3 = getDolGlobalString($used_conf.'3', $level3); if ($totallate <= $level0) { $weather->picto = 'weather-clear.png'; diff --git a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php index 8f7764ad100..c51bc01376c 100644 --- a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php +++ b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php @@ -107,7 +107,7 @@ class InterfaceMyModuleTriggers extends DolibarrTriggers ); return call_user_func($callback, $action, $object, $user, $langs, $conf); - }; + } // Or you can execute some code here switch ($action) { diff --git a/htdocs/multicurrency/class/multicurrency.class.php b/htdocs/multicurrency/class/multicurrency.class.php index 8b42f7cb25b..4305aed6f3b 100644 --- a/htdocs/multicurrency/class/multicurrency.class.php +++ b/htdocs/multicurrency/class/multicurrency.class.php @@ -615,8 +615,8 @@ class MultiCurrency extends CommonObject if ($conf->currency != $conf->global->MULTICURRENCY_APP_SOURCE) { $alternate_source = 'USD'.$conf->currency; - if (!empty($TRate->{$alternate_source})) { - $coef = $TRate->USDUSD / $TRate->{$alternate_source}; + if (!empty($TRate->$alternate_source)) { + $coef = $TRate->USDUSD / $TRate->$alternate_source; foreach ($TRate as $attr => &$rate) { $rate *= $coef; } diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 0424ddaf830..788857dfd47 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -1529,7 +1529,7 @@ if ($action == 'edit_price' && $object->getRights()->creer) { otherPrices.show(); minPrice1.show(); } - }; + } jQuery(document).ready(function () { showHidePriceRules(); diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index d1644623ce1..2520eb8f559 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -78,12 +78,12 @@ while ($tmpobj = $db->fetch_object($resWar)) { $listofqualifiedwarehousesid .= $tmpobj->rowid; $lastWarehouseID = $tmpobj->rowid; $count++; -}; +} //MultiCompany : If only 1 Warehouse is visible, filter will automatically be set to it. if ($count == 1 && (empty($fk_entrepot) || $fk_entrepot <= 0) && !empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED)) { $fk_entrepot = $lastWarehouseID; -}; +} $texte = ''; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index e7467176c10..96b4aa0b03b 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -968,7 +968,7 @@ if ($action == 'create' && $user->rights->projet->creer) { console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked")); jQuery(".classuseopportunity").hide(); } - }; + } });'; print ''; print '
'; @@ -994,7 +994,7 @@ if ($action == 'create' && $user->rights->projet->creer) { console.log("Hide task fields "+jQuery("#usage_task").prop("checked")); jQuery(".classusetask").hide(); } - }; + } });'; print ''; print '
'; @@ -1020,7 +1020,7 @@ if ($action == 'create' && $user->rights->projet->creer) { console.log("Hide bill time fields "+jQuery("#usage_bill_time").prop("checked")); jQuery(".classusebilltime").hide(); } - }; + } });'; print ''; print '
'; @@ -1046,7 +1046,7 @@ if ($action == 'create' && $user->rights->projet->creer) { console.log("Hide organize event fields "+jQuery("#usage_organize_event").prop("checked")); jQuery(".classuseorganizeevent").hide(); } - }; + } });'; print ''; } diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 91333c153f8..458921adfc6 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -1025,7 +1025,8 @@ class Task extends CommonObjectLine if (!empty($extrafields->attributes['projet']['label'])) { foreach ($extrafields->attributes['projet']['label'] as $key => $val) { if ($extrafields->attributes['projet']['type'][$key] != 'separate') { - $tasks[$i]->{'options_'.$key} = $obj->{'options_'.$key}; + $tmpvar = 'options_'.$key; + $tasks[$i]->{'options_'.$key} = $obj->$tmpvar; } } } @@ -1033,7 +1034,8 @@ class Task extends CommonObjectLine if (!empty($extrafields->attributes['projet_task']['label'])) { foreach ($extrafields->attributes['projet_task']['label'] as $key => $val) { if ($extrafields->attributes['projet_task']['type'][$key] != 'separate') { - $tasks[$i]->{'options_'.$key} = $obj->{'options_'.$key}; + $tmpvar = 'options_'.$key; + $tasks[$i]->{'options_'.$key} = $obj->$tmpvar; } } } diff --git a/htdocs/projet/jsgantt_language.js.php b/htdocs/projet/jsgantt_language.js.php index 35ab1132ae7..93b9ee5505f 100644 --- a/htdocs/projet/jsgantt_language.js.php +++ b/htdocs/projet/jsgantt_language.js.php @@ -67,7 +67,7 @@ var vLangs={'getDefaultLang(1); ?>': 'sunday':'transnoentities('Sunday'); ?>','monday':'transnoentities('Monday'); ?>','tuesday':'transnoentities('Tuesday'); ?>','wednesday':'transnoentities('Wednesday'); ?>','thursday':'transnoentities('Thursday'); ?>','friday':'transnoentities('Friday'); ?>','saturday':'transnoentities('Saturday'); ?>', 'sun':'transnoentities('SundayMin'); ?>','mon':'transnoentities('MondayMin'); ?>','tue':'transnoentities('TuesdayMin'); ?>','wed':'transnoentities('WednesdayMin'); ?>','thu':'transnoentities('ThursdayMin'); ?>','fri':'transnoentities('FridayMin'); ?>','sat':'transnoentities('SaturdayMin'); ?>' } -}; +} var vLang='getDefaultLang(1); ?>'; global->MEMBER_SKIP_TABLE) || !empty($conf->global->MEMBER_NEW if (jQuery("#morphy").val() == \'mor\') { jQuery("#trcompany").show(); } - }; + } initmorphy(); jQuery("#morphy").change(function() { initmorphy(); diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 79104817e77..e9823f2d0f7 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -2395,7 +2395,7 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme color: '#fa755a', iconColor: '#fa755a' } - }; + } var cardElement = elements.create('card', {style: style}); @@ -2435,7 +2435,7 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme ?> var cardButton = document.getElementById('buttontopay'); var clientSecret = cardButton.dataset.secret; - var options = { clientSecret: clientSecret,}; + var options = { clientSecret: clientSecret }; // Create an instance of Elements var elements = stripe.elements(options); @@ -2465,7 +2465,7 @@ if (preg_match('/^dopayment/', $action)) { // If we choosed/click on the payme color: '#fa755a', iconColor: '#fa755a' } - }; + } displayCanvasExists($action)) { data: function (params) { return { newcompany: params.term // search term - }; + } }, processResults: function (data, params) { return { results: data - }; + } }, cache: true }, @@ -2150,7 +2150,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { { jQuery(".visibleifsupplier").show(); } - }; + } $("#selectcountry_id").change(function() { document.formsoc.action.value="edit"; diff --git a/htdocs/takepos/admin/terminal.php b/htdocs/takepos/admin/terminal.php index fe03139c8a3..f93608d20b8 100644 --- a/htdocs/takepos/admin/terminal.php +++ b/htdocs/takepos/admin/terminal.php @@ -268,7 +268,7 @@ if (isModEnabled('stock')) { } print ''; - $disabled = $conf->global->{'CASHDESK_NO_DECREASE_STOCK'.$terminal}; + $disabled = getDolGlobalString('CASHDESK_NO_DECREASE_STOCK'.$terminal); print ''; // Force warehouse (this is not a default value) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index dc2bd8b684a..fb3049715cf 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -956,7 +956,7 @@ $( document ).ready(function() { return { vertical:container.scrollHeight > container.clientHeight, horizontal:container.scrollWidth > container.clientWidth - }; + } } $(window).resize(function(){ diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index ccc1fde97eb..ea262a1562f 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -174,12 +174,12 @@ if (empty($reshook)) { $bankaccount = GETPOST('accountid', 'int'); } else { if ($pay == 'LIQ') { - $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]}; // For backward compatibility + $bankaccount = getDolGlobalString('CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]); // For backward compatibility } elseif ($pay == "CHQ") { - $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]}; // For backward compatibility + $bankaccount = getDolGlobalString('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]); // For backward compatibility } else { $accountname = "CASHDESK_ID_BANKACCOUNT_".$pay.$_SESSION["takeposterminal"]; - $bankaccount = $conf->global->$accountname; + $bankaccount = getDolGlobalString($accountname); } } @@ -217,13 +217,6 @@ if (empty($reshook)) { $invoice->update($user); } - //$sav_FACTURE_ADDON = ''; - //if (!empty($conf->global->TAKEPOS_ADDON)) { - // $sav_FACTURE_ADDON = $conf->global->FACTURE_ADDON; - // if ($conf->global->TAKEPOS_ADDON == "terminal") $conf->global->FACTURE_ADDON = $conf->global->{'TAKEPOS_ADDON'.$_SESSION["takeposterminal"]}; - // else $conf->global->FACTURE_ADDON = $conf->global->TAKEPOS_ADDON; - //} - $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]; if ($error) { dol_htmloutput_errors($errormsg, null, 1); diff --git a/htdocs/takepos/smpcb.php b/htdocs/takepos/smpcb.php index 505ec27c1b0..6ce39d39bf0 100644 --- a/htdocs/takepos/smpcb.php +++ b/htdocs/takepos/smpcb.php @@ -71,7 +71,7 @@ if (GETPOST('smp-status')) { print ''; print "Transaction status registered, you can close this"; diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 52a9f941cfe..4e90bbb1bd9 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -3371,24 +3371,36 @@ class User extends CommonObject $socialnetworks = getArrayOfSocialNetworks(); - $this->firstname = $ldapuser->{$conf->global->LDAP_FIELD_FIRSTNAME}; - $this->lastname = $ldapuser->{$conf->global->LDAP_FIELD_NAME}; - $this->login = $ldapuser->{$conf->global->LDAP_FIELD_LOGIN}; - $this->pass = $ldapuser->{$conf->global->LDAP_FIELD_PASSWORD}; - $this->pass_indatabase_crypted = $ldapuser->{$conf->global->LDAP_FIELD_PASSWORD_CRYPTED}; + $tmpvar = getDolGlobalString('LDAP_FIELD_FIRSTNAME'); + $this->firstname = $ldapuser->$tmpvar; + $tmpvar = getDolGlobalString('LDAP_FIELD_NAME'); + $this->lastname = $ldapuser->$tmpvar; + $tmpvar = getDolGlobalString('LDAP_FIELD_LOGIN'); + $this->login = $ldapuser->$tmpvar; + $tmpvar = getDolGlobalString('LDAP_FIELD_PASSWORD'); + $this->pass = $ldapuser->$tmpvar; + $tmpvar = getDolGlobalString('LDAP_FIELD_PASSWORD_CRYPTED'); + $this->pass_indatabase_crypted = $ldapuser->$tmpvar; - $this->office_phone = $ldapuser->{$conf->global->LDAP_FIELD_PHONE}; - $this->user_mobile = $ldapuser->{$conf->global->LDAP_FIELD_MOBILE}; - $this->office_fax = $ldapuser->{$conf->global->LDAP_FIELD_FAX}; - $this->email = $ldapuser->{$conf->global->LDAP_FIELD_MAIL}; + $tmpvar = getDolGlobalString('LDAP_FIELD_PHONE'); + $this->office_phone = $ldapuser->$tmpvar; + $tmpvar = getDolGlobalString('LDAP_FIELD_MOBILE'); + $this->user_mobile = $ldapuser->$tmpvar; + $tmpvar = getDolGlobalString('LDAP_FIELD_FAX'); + $this->office_fax = $ldapuser->$tmpvar; + $tmpvar = getDolGlobalString('LDAP_FIELD_MAIL'); + $this->email = $ldapuser->$tmpvar; foreach ($socialnetworks as $key => $value) { - $tmpkey = 'LDAP_FIELD_'.strtoupper($value['label']); - $this->socialnetworks[$value['label']] = $ldapuser->{$conf->global->$tmpkey}; + $tmpvar = getDolGlobalString('LDAP_FIELD_'.strtoupper($value['label'])); + $this->socialnetworks[$value['label']] = $ldapuser->$tmpvar; } - $this->ldap_sid = $ldapuser->{$conf->global->LDAP_FIELD_SID}; + $tmpvar = getDolGlobalString('LDAP_FIELD_SID'); + $this->ldap_sid = $ldapuser->$tmpvar; - $this->job = $ldapuser->{$conf->global->LDAP_FIELD_TITLE}; - $this->note_public = $ldapuser->{$conf->global->LDAP_FIELD_DESCRIPTION}; + $tmpvar = getDolGlobalString('LDAP_FIELD_TITLE'); + $this->job = $ldapuser->$tmpvar; + $tmpvar = getDolGlobalString('LDAP_FIELD_DESCRIPTION'); + $this->note_public = $ldapuser->$tmpvar; $result = $this->update($user); diff --git a/htdocs/webservices/server_thirdparty.php b/htdocs/webservices/server_thirdparty.php index 800c2e0e2a2..1fe15576860 100644 --- a/htdocs/webservices/server_thirdparty.php +++ b/htdocs/webservices/server_thirdparty.php @@ -736,7 +736,7 @@ function getListOfThirdParties($authentication, $filterthirdparty) if (isset($extrafields->attributes[$elementtype]['label']) && is_array($extrafields->attributes[$elementtype]['label']) && count($extrafields->attributes[$elementtype]['label'])) { foreach ($extrafields->attributes[$elementtype]['label'] as $key => $label) { if (isset($obj->{$key})) { - $extrafieldsOptions['options_'.$key] = $obj->{$key}; + $extrafieldsOptions['options_'.$key] = $obj->$key; } } } diff --git a/htdocs/website/index.php b/htdocs/website/index.php index ae3362ab9d6..2cb775019e6 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -3294,7 +3294,7 @@ if (!GETPOST('hide_websitemenu')) { } isEditingEnabled = false; } - }; + } }); '; print $langs->trans("EditInLine"); From 0db5c98941af8e63aa64b2fb67d952f16a8222bf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 18:46:36 +0100 Subject: [PATCH 200/816] Clean code --- htdocs/societe/card.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index a5b6f21b31b..bb9d2376a47 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -3313,11 +3313,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) { $result = show_contacts($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?socid='.$object->id); } - - // Addresses list - if (!empty($conf->global->SOCIETE_ADDRESSES_MANAGEMENT)) { - $result = show_addresses($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?socid='.$object->id); - } } } From 67fea77e07023e9c9e3d7c368d3891d536193783 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 18:48:45 +0100 Subject: [PATCH 201/816] Fix warning --- htdocs/takepos/invoice.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index ccc1fde97eb..4dcd9645350 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -174,12 +174,12 @@ if (empty($reshook)) { $bankaccount = GETPOST('accountid', 'int'); } else { if ($pay == 'LIQ') { - $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]}; // For backward compatibility + $bankaccount = getDolGlobalString('CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]); // For backward compatibility } elseif ($pay == "CHQ") { - $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]}; // For backward compatibility + $bankaccount = getDolGlobalString('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]); // For backward compatibility } else { $accountname = "CASHDESK_ID_BANKACCOUNT_".$pay.$_SESSION["takeposterminal"]; - $bankaccount = $conf->global->$accountname; + $bankaccount = getDolGlobalString($accountname); } } From c593d990e458305ca1efc967effa7356befe5d60 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 18:52:19 +0100 Subject: [PATCH 202/816] Clean deprecated code for adodbtime --- htdocs/core/lib/functions.lib.php | 102 +++++++----------- .../class/partnershiputils.class.php | 2 +- 2 files changed, 42 insertions(+), 62 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 9f67a0e3909..de329ee515f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2647,12 +2647,6 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = $format = str_replace('%A', '__A__', $format); } - $useadodb = getDolGlobalInt('MAIN_USE_LEGACY_ADODB_FOR_DATE', 0); - //$useadodb = 1; // To switch to adodb - if (!empty($useadodb)) { - include_once DOL_DOCUMENT_ROOT.'/includes/adodbtime/adodb-time.inc.php'; - } - // Analyze date $reg = array(); if (preg_match('/^([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])$/i', $time, $reg)) { // Deprecated. Ex: 1970-01-01, 1970-01-01 01:00:00, 19700101010000 @@ -2671,14 +2665,37 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = $ssec = (!empty($reg[6]) ? $reg[6] : ''); $time = dol_mktime($shour, $smin, $ssec, $smonth, $sday, $syear, true); - if (empty($useadodb)) { + + if ($to_gmt) { + $tzo = new DateTimeZone('UTC'); // when to_gmt is true, base for offsettz and offsetdst (so timetouse) is UTC + } else { + $tzo = new DateTimeZone(date_default_timezone_get()); // when to_gmt is false, base for offsettz and offsetdst (so timetouse) is PHP server + } + $dtts = new DateTime(); + $dtts->setTimestamp($time); + $dtts->setTimezone($tzo); + $newformat = str_replace( + array('%Y', '%y', '%m', '%d', '%H', '%I', '%M', '%S', '%p', 'T', 'Z', '__a__', '__A__', '__b__', '__B__'), + array('Y', 'y', 'm', 'd', 'H', 'h', 'i', 's', 'A', '__£__', '__$__', '__{__', '__}__', '__[__', '__]__'), + $format); + $ret = $dtts->format($newformat); + $ret = str_replace( + array('__£__', '__$__', '__{__', '__}__', '__[__', '__]__'), + array('T', 'Z', '__a__', '__A__', '__b__', '__B__'), + $ret + ); + } else { + // Date is a timestamps + if ($time < 100000000000) { // Protection against bad date values + $timetouse = $time + $offsettz + $offsetdst; // TODO We could be able to disable use of offsettz and offsetdst to use only offsettzstring. + if ($to_gmt) { $tzo = new DateTimeZone('UTC'); // when to_gmt is true, base for offsettz and offsetdst (so timetouse) is UTC } else { $tzo = new DateTimeZone(date_default_timezone_get()); // when to_gmt is false, base for offsettz and offsetdst (so timetouse) is PHP server } $dtts = new DateTime(); - $dtts->setTimestamp($time); + $dtts->setTimestamp($timetouse); $dtts->setTimezone($tzo); $newformat = str_replace( array('%Y', '%y', '%m', '%d', '%H', '%I', '%M', '%S', '%p', 'T', 'Z', '__a__', '__A__', '__b__', '__B__'), @@ -2688,36 +2705,8 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = $ret = str_replace( array('__£__', '__$__', '__{__', '__}__', '__[__', '__]__'), array('T', 'Z', '__a__', '__A__', '__b__', '__B__'), - $ret); - } else { - $ret = adodb_strftime($format, $time + $offsettz + $offsetdst, $to_gmt); - } - } else { - // Date is a timestamps - if ($time < 100000000000) { // Protection against bad date values - $timetouse = $time + $offsettz + $offsetdst; // TODO We could be able to disable use of offsettz and offsetdst to use only offsettzstring. - - if (empty($useadodb)) { - if ($to_gmt) { - $tzo = new DateTimeZone('UTC'); // when to_gmt is true, base for offsettz and offsetdst (so timetouse) is UTC - } else { - $tzo = new DateTimeZone(date_default_timezone_get()); // when to_gmt is false, base for offsettz and offsetdst (so timetouse) is PHP server - } - $dtts = new DateTime(); - $dtts->setTimestamp($timetouse); - $dtts->setTimezone($tzo); - $newformat = str_replace( - array('%Y', '%y', '%m', '%d', '%H', '%I', '%M', '%S', '%p', 'T', 'Z', '__a__', '__A__', '__b__', '__B__'), - array('Y', 'y', 'm', 'd', 'H', 'h', 'i', 's', 'A', '__£__', '__$__', '__{__', '__}__', '__[__', '__]__'), - $format); - $ret = $dtts->format($newformat); - $ret = str_replace( - array('__£__', '__$__', '__{__', '__}__', '__[__', '__]__'), - array('T', 'Z', '__a__', '__A__', '__b__', '__B__'), - $ret); - } else { - $ret = adodb_strftime($format, $timetouse, $to_gmt); // If to_gmt = false then adodb_strftime use TZ of server - } + $ret + ); //var_dump($ret);exit; } else { $ret = 'Bad value '.$time.' for date'; @@ -2727,20 +2716,15 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = if (preg_match('/__b__/i', $format)) { $timetouse = $time + $offsettz + $offsetdst; // TODO We could be able to disable use of offsettz and offsetdst to use only offsettzstring. - if (empty($useadodb)) { - if ($to_gmt) { - $tzo = new DateTimeZone('UTC'); // when to_gmt is true, base for offsettz and offsetdst (so timetouse) is UTC - } else { - $tzo = new DateTimeZone(date_default_timezone_get()); // when to_gmt is false, base for offsettz and offsetdst (so timetouse) is PHP server - } - $dtts = new DateTime(); - $dtts->setTimestamp($timetouse); - $dtts->setTimezone($tzo); - $month = $dtts->format("m"); + if ($to_gmt) { + $tzo = new DateTimeZone('UTC'); // when to_gmt is true, base for offsettz and offsetdst (so timetouse) is UTC } else { - // After this ret is string in PHP setup language (strftime was used). Now we convert to $outputlangs. - $month = adodb_strftime('%m', $timetouse, $to_gmt); // If to_gmt = false then adodb_strftime use TZ of server + $tzo = new DateTimeZone(date_default_timezone_get()); // when to_gmt is false, base for offsettz and offsetdst (so timetouse) is PHP server } + $dtts = new DateTime(); + $dtts->setTimestamp($timetouse); + $dtts->setTimezone($tzo); + $month = $dtts->format("m"); $month = sprintf("%02d", $month); // $month may be return with format '06' on some installation and '6' on other, so we force it to '06'. if ($encodetooutput) { $monthtext = $outputlangs->transnoentities('Month'.$month); @@ -2759,19 +2743,15 @@ function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = //print "time=$time offsettz=$offsettz offsetdst=$offsetdst offsettzstring=$offsettzstring"; $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring. - if (empty($useadodb)) { - if ($to_gmt) { - $tzo = new DateTimeZone('UTC'); - } else { - $tzo = new DateTimeZone(date_default_timezone_get()); - } - $dtts = new DateTime(); - $dtts->setTimestamp($timetouse); - $dtts->setTimezone($tzo); - $w = $dtts->format("w"); + if ($to_gmt) { + $tzo = new DateTimeZone('UTC'); } else { - $w = adodb_strftime('%w', $timetouse, $to_gmt); // If to_gmt = false then adodb_strftime use TZ of server + $tzo = new DateTimeZone(date_default_timezone_get()); } + $dtts = new DateTime(); + $dtts->setTimestamp($timetouse); + $dtts->setTimezone($tzo); + $w = $dtts->format("w"); $dayweek = $outputlangs->transnoentitiesnoconv('Day'.$w); $ret = str_replace('__A__', $dayweek, $ret); diff --git a/htdocs/partnership/class/partnershiputils.class.php b/htdocs/partnership/class/partnershiputils.class.php index 647d1492ced..86722ed1da2 100644 --- a/htdocs/partnership/class/partnershiputils.class.php +++ b/htdocs/partnership/class/partnershiputils.class.php @@ -395,7 +395,7 @@ class PartnershipUtils /** * Action to check if Dolibarr backlink not found on partner website * - * @param $website Website Partner's website + * @param string $website Partner's website URL * @return int 0 if KO, 1 if OK */ private function checkDolibarrBacklink($website = null) From 9e235f916f98f1e5ebdad7323e8425c7709bde26 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 19:06:04 +0100 Subject: [PATCH 203/816] Fix var --- htdocs/core/modules/modWorkflow.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modWorkflow.class.php b/htdocs/core/modules/modWorkflow.class.php index 58da4876d32..1fd6a89e66a 100644 --- a/htdocs/core/modules/modWorkflow.class.php +++ b/htdocs/core/modules/modWorkflow.class.php @@ -95,7 +95,7 @@ class modWorkflow extends DolibarrModules 8=>array('WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER', 'chaine', '1', 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER', 0, 'current', 0), 10=>array('WORKFLOW_TICKET_LINK_CONTRACT', 'chaine', '0', 'Automatically link a ticket to available contracts', 0, 'current', 0), 11=>array('WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS', 'chaine', '0', 'Search among parent companies contracts when automatically linking a ticket to available contracts', 0, 'current', 0), - 11=>array('WORKFLOW_TICKET_CREATE_INTERVENTION', 'chaine', '1', 'WORKFLOW_TICKET_CREATE_INTERVENTION', 0, 'current', 0) + 12=>array('WORKFLOW_TICKET_CREATE_INTERVENTION', 'chaine', '0', 'WORKFLOW_TICKET_CREATE_INTERVENTION', 0, 'current', 0) ); // Boxes From c5ca50b5db78fa3298420fefcfac7f7ad9f3d7b9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 19:27:13 +0100 Subject: [PATCH 204/816] Fix warning --- htdocs/compta/facture/class/facture-rec.class.php | 3 +-- htdocs/ticket/class/ticket.class.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 3a586dfc3e5..f02850492b5 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -188,13 +188,12 @@ class FactureRec extends CommonInvoice 'note_private' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>105), 'note_public' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>110), 'modelpdf' =>array('type'=>'varchar(255)', 'label'=>'Modelpdf', 'enabled'=>1, 'visible'=>-1, 'position'=>115), - 'date_last_gen' =>array('type'=>'varchar(7)', 'label'=>'Last gen', 'enabled'=>1, 'visible'=>-1, 'position'=>120), - 'unit_frequency' =>array('type'=>'varchar(2)', 'label'=>'Unit frequency', 'enabled'=>1, 'visible'=>-1, 'position'=>125), 'date_when' =>array('type'=>'datetime', 'label'=>'Date when', 'enabled'=>1, 'visible'=>-1, 'position'=>130), 'date_last_gen' =>array('type'=>'datetime', 'label'=>'Date last gen', 'enabled'=>1, 'visible'=>-1, 'position'=>135), 'nb_gen_done' =>array('type'=>'integer', 'label'=>'Nb gen done', 'enabled'=>1, 'visible'=>-1, 'position'=>140), 'nb_gen_max' =>array('type'=>'integer', 'label'=>'Nb gen max', 'enabled'=>1, 'visible'=>-1, 'position'=>145), 'frequency' =>array('type'=>'integer', 'label'=>'Frequency', 'enabled'=>1, 'visible'=>-1, 'position'=>150), + 'unit_frequency' =>array('type'=>'varchar(2)', 'label'=>'UnitFrequency', 'enabled'=>1, 'visible'=>-1, 'position'=>152), 'usenewprice' =>array('type'=>'integer', 'label'=>'UseNewPrice', 'enabled'=>1, 'visible'=>0, 'position'=>155), 'revenuestamp' =>array('type'=>'double(24,8)', 'label'=>'RevenueStamp', 'enabled'=>1, 'visible'=>-1, 'position'=>160, 'isameasure'=>1), 'auto_validate' =>array('type'=>'integer', 'label'=>'Auto validate', 'enabled'=>1, 'visible'=>-1, 'position'=>165), diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 6763ce02e84..d077ed3e777 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -270,7 +270,7 @@ class Ticket extends CommonObject // BEGIN MODULEBUILDER PROPERTIES public $fields = array( - 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'position'=>1, 'visible'=>-2, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>"Id"), + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>-2, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>"Id"), 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>5, 'notnull'=>1, 'index'=>1), 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'visible'=>1, 'enabled'=>1, 'position'=>10, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'css'=>'', 'showoncombobox'=>1), 'track_id' => array('type'=>'varchar(255)', 'label'=>'TicketTrackId', 'visible'=>-2, 'enabled'=>1, 'position'=>11, 'notnull'=>-1, 'searchall'=>1, 'help'=>"Help text"), From f816587cfb235040c1c24c3c1489e7271aa73fa4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 19:28:05 +0100 Subject: [PATCH 205/816] Fix warning --- htdocs/adherents/list.php | 1 - htdocs/core/modules/modCommande.class.php | 4 ++-- htdocs/core/modules/modSociete.class.php | 1 - htdocs/projet/list.php | 2 +- htdocs/user/class/user.class.php | 1 - 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index a1d929ec3e9..0c61f94a93d 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -126,7 +126,6 @@ $fieldstosearchall = array( 'd.login'=>'Login', 'd.lastname'=>'Lastname', 'd.firstname'=>'Firstname', - 'd.login'=>'Login', 'd.societe'=>"Company", 'd.email'=>'EMail', 'd.address'=>'Address', diff --git a/htdocs/core/modules/modCommande.class.php b/htdocs/core/modules/modCommande.class.php index f0486b5cb58..38b81cdb4fb 100644 --- a/htdocs/core/modules/modCommande.class.php +++ b/htdocs/core/modules/modCommande.class.php @@ -204,7 +204,7 @@ class modCommande extends DolibarrModules 'co.code'=>"CountryCode", 's.phone'=>'Phone', 's.siren'=>'ProfId1', 's.siret'=>'ProfId2', 's.ape'=>'ProfId3', 's.idprof4'=>'ProfId4', 'c.rowid'=>"Id", 'c.ref'=>"Ref", 'c.ref_client'=>"RefCustomer", 'c.fk_soc'=>"IdCompany", 'c.date_creation'=>"DateCreation", 'c.date_commande'=>"OrderDate", 'c.date_livraison'=>"DateDeliveryPlanned", 'c.amount_ht'=>"Amount", 'c.total_ht'=>"TotalHT", - 'c.total_ttc'=>"TotalTTC", 'c.facture'=>"Billed", 'c.fk_statut'=>'Status', 'c.note_public'=>"Note", 'c.date_livraison'=>'DeliveryDate', + 'c.total_ttc'=>"TotalTTC", 'c.facture'=>"Billed", 'c.fk_statut'=>'Status', 'c.note_public'=>"Note", 'c.fk_user_author'=>'CreatedById', 'uc.login'=>'CreatedByLogin', 'c.fk_user_valid'=>'ValidatedById', 'uv.login'=>'ValidatedByLogin', 'pj.ref'=>'ProjectRef', 'cd.rowid'=>'LineId', 'cd.description'=>"LineDescription", 'cd.product_type'=>'TypeOfLineServiceOrProduct', 'cd.tva_tx'=>"LineVATRate", 'cd.qty'=>"LineQty", 'cd.total_ht'=>"LineTotalHT", 'cd.total_tva'=>"LineTotalVAT", 'cd.total_ttc'=>"LineTotalTTC", @@ -236,7 +236,7 @@ class modCommande extends DolibarrModules 's.nom'=>'Text', 'ps.nom'=>'Text', 's.address'=>'Text', 's.zip'=>'Text', 's.town'=>'Text', 'co.label'=>'List:c_country:label:label', 'co.code'=>'Text', 's.phone'=>'Text', 's.siren'=>'Text', 's.siret'=>'Text', 's.ape'=>'Text', 's.idprof4'=>'Text', 'c.ref'=>"Text", 'c.ref_client'=>"Text", 'c.date_creation'=>"Date", 'c.date_commande'=>"Date", 'c.date_livraison'=>"Date", 'c.amount_ht'=>"Numeric", 'c.total_ht'=>"Numeric", - 'c.total_ttc'=>"Numeric", 'c.facture'=>"Boolean", 'c.fk_statut'=>'Status', 'c.note_public'=>"Text", 'c.date_livraison'=>'Date', 'pj.ref'=>'Text', + 'c.total_ttc'=>"Numeric", 'c.facture'=>"Boolean", 'c.fk_statut'=>'Status', 'c.note_public'=>"Text", 'pj.ref'=>'Text', 'cd.description'=>"Text", 'cd.product_type'=>'Boolean', 'cd.tva_tx'=>"Numeric", 'cd.qty'=>"Numeric", 'cd.total_ht'=>"Numeric", 'cd.total_tva'=>"Numeric", 'cd.total_ttc'=>"Numeric", 'p.rowid'=>'List:product:ref::product', 'p.ref'=>'Text', 'p.label'=>'Text', 'd.nom'=>'Text', 'c.entity'=>'List:entity:label:rowid', diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 70729f5c9dc..d63084ac5b5 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -571,7 +571,6 @@ class modSociete extends DolibarrModules 'dict' => 'DictionaryCompanyType' ), 's.capital' => array('rule' => 'numeric'), - 's.fk_stcomm' => array('rule' => 'zeroifnull'), 's.parent' => array( 'rule' => 'fetchidfromref', 'file' => '/societe/class/societe.class.php', diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 23ff9be793f..411e6d5fcd8 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -210,7 +210,7 @@ $arrayfields['s.nom'] = array('label'=>$langs->trans("ThirdParty"), 'checked'=>1 $arrayfields['s.name_alias'] = array('label'=>"AliasNameShort", 'checked'=>0, 'position'=>22); $arrayfields['commercial'] = array('label'=>$langs->trans("SaleRepresentativesOfThirdParty"), 'checked'=>0, 'position'=>23); $arrayfields['c.assigned'] = array('label'=>$langs->trans("AssignedTo"), 'checked'=>-1, 'position'=>120); -$arrayfields['opp_weighted_amount'] = array('label'=>$langs->trans('OpportunityWeightedAmountShort'), 'checked'=>0, 'position'=> 116, 'enabled'=>(empty($conf->global->PROJECT_USE_OPPORTUNITIES) ? 0 : 1), 'position'=>106); +$arrayfields['opp_weighted_amount'] = array('label'=>$langs->trans('OpportunityWeightedAmountShort'), 'checked'=>0, 'enabled'=>(empty($conf->global->PROJECT_USE_OPPORTUNITIES) ? 0 : 1), 'position'=>106); $arrayfields['u.login'] = array('label'=>"Author", 'checked'=>1, 'position'=>165); // Force some fields according to search_usage filter... if (GETPOST('search_usage_opportunity')) { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 4e90bbb1bd9..81739943ae2 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -717,7 +717,6 @@ class User extends CommonObject 'shipping' => 'expedition', 'task' => 'task@projet', 'fichinter' => 'ficheinter', - 'propale' => 'propal', 'inventory' => 'stock', 'invoice' => 'facture', 'invoice_supplier' => 'fournisseur', From 73e776a44167ce0b94c98adc67e3d50dae94ec7a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 19:29:19 +0100 Subject: [PATCH 206/816] Add option to start manually --- .github/workflows/stale-issues-safe.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale-issues-safe.yml b/.github/workflows/stale-issues-safe.yml index 4ac9fa8f5b9..af04675d48d 100644 --- a/.github/workflows/stale-issues-safe.yml +++ b/.github/workflows/stale-issues-safe.yml @@ -6,7 +6,8 @@ on: - cron: "0 21 * * *" issue_comment: types: [created] - + workflow_dispatch: + permissions: {} # none jobs: From 1fde0a70f5bbb0492f79b0421ce808094f19228e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 19:39:08 +0100 Subject: [PATCH 207/816] Fix cast bad type --- htdocs/societe/class/companybankaccount.class.php | 2 +- htdocs/user/class/userbankaccount.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/class/companybankaccount.class.php b/htdocs/societe/class/companybankaccount.class.php index d81a360e7d2..26305bb0013 100644 --- a/htdocs/societe/class/companybankaccount.class.php +++ b/htdocs/societe/class/companybankaccount.class.php @@ -349,7 +349,7 @@ class CompanyBankAccount extends Account $rib = $this->label." : "; } - $rib .= (string) $this; + $rib .= $this->iban; } return $rib; diff --git a/htdocs/user/class/userbankaccount.class.php b/htdocs/user/class/userbankaccount.class.php index 271609139b1..6e9cc8e52af 100644 --- a/htdocs/user/class/userbankaccount.class.php +++ b/htdocs/user/class/userbankaccount.class.php @@ -241,7 +241,7 @@ class UserBankAccount extends Account $rib = $this->label." : "; } - $rib .= (string) $this; + $rib .= $this->iban; } return $rib; From 41c3d9da05225e6709362efb8e76a09d06fa8bfa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 19:40:16 +0100 Subject: [PATCH 208/816] Fix warning --- htdocs/core/lib/security.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index deff1af567c..88fc7d27eaa 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -367,7 +367,7 @@ function restrictedArea(User $user, $features, $object = 0, $tableandshare = '', if ($features == 'subscription') { $features = 'adherent'; $feature2 = 'cotisation'; - }; + } if ($features == 'websitepage') { $features = 'website'; $tableandshare = 'website_page'; From 8dc89e9a9a57ce678367765b7c8f1049796eb7f4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 19:51:07 +0100 Subject: [PATCH 209/816] Fix warning --- htdocs/admin/system/dolibarr.php | 2 +- htdocs/blockedlog/class/authority.class.php | 2 +- htdocs/compta/facture/class/facture.class.php | 2 +- htdocs/core/filemanagerdol/connectors/php/connector.lib.php | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/system/dolibarr.php b/htdocs/admin/system/dolibarr.php index 4a55c1a1160..afe5d4d3520 100644 --- a/htdocs/admin/system/dolibarr.php +++ b/htdocs/admin/system/dolibarr.php @@ -264,7 +264,7 @@ $daylight = round($c - $b); $val = ($a >= 0 ? '+' : '').$a; $val .= ' ('.($a == 'unknown' ? 'unknown' : ($a >= 0 ? '+' : '').($a * 3600)).')'; $val .= '       '.getServerTimeZoneString(); -$val .= '       '.$langs->trans("DaylingSavingTime").': '.($daylight === 'unknown' ? 'unknown' : ($a == $c ?yn($daylight) : yn(0).($daylight ? '     ('.$langs->trans('YesInSummer').')' : ''))); +$val .= '       '.$langs->trans("DaylingSavingTime").': '.(is_null($daylight) ? 'unknown' : ($a == $c ?yn($daylight) : yn(0).($daylight ? '     ('.$langs->trans('YesInSummer').')' : ''))); print $form->textwithtooltip($val, $txt, 2, 1, img_info('')); print ''."\n"; // value defined in http://fr3.php.net/manual/en/timezones.europe.php print ''."\n"; diff --git a/htdocs/blockedlog/class/authority.class.php b/htdocs/blockedlog/class/authority.class.php index 0b665fedc3e..b3dd9b45f47 100644 --- a/htdocs/blockedlog/class/authority.class.php +++ b/htdocs/blockedlog/class/authority.class.php @@ -305,7 +305,7 @@ class BlockedLogAuthority $res = getURLContent($url); echo $block->signature.' '.$url.' '.$res['content'].'
'; - if ($res === 'blockalreadyadded' || $res === 'blockadded') { + if ($res['content'] === 'blockalreadyadded' || $res['content'] === 'blockadded') { $block->setCertified(); } else { $this->error = $langs->trans('ImpossibleToContactAuthority ', $url); diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 87d28de8756..0a3c1445745 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -6264,7 +6264,7 @@ class FactureLigne extends CommonInvoiceLine $sql .= ", total_localtax2=".price2num($this->total_localtax2); } $sql .= ", fk_product_fournisseur_price=".(!empty($this->fk_fournprice) ? "'".$this->db->escape($this->fk_fournprice)."'" : "null"); - $sql .= ", buy_price_ht=".(($this->pa_ht || $this->pa_ht === 0 || $this->pa_ht === '0') ? price2num($this->pa_ht) : "null"); // $this->pa_ht should always be defined (set to 0 or to sell price depending on option) + $sql .= ", buy_price_ht=".(($this->pa_ht || (string) $this->pa_ht === '0') ? price2num($this->pa_ht) : "null"); // $this->pa_ht should always be defined (set to 0 or to sell price depending on option) $sql .= ", fk_parent_line=".($this->fk_parent_line > 0 ? $this->fk_parent_line : "null"); if (!empty($this->rang)) { $sql .= ", rang=".((int) $this->rang); diff --git a/htdocs/core/filemanagerdol/connectors/php/connector.lib.php b/htdocs/core/filemanagerdol/connectors/php/connector.lib.php index 608c2ba4cd6..75c4d1e3e08 100644 --- a/htdocs/core/filemanagerdol/connectors/php/connector.lib.php +++ b/htdocs/core/filemanagerdol/connectors/php/connector.lib.php @@ -343,7 +343,8 @@ function FileUpload($resourceType, $currentFolder, $sCommand, $CKEcallback = '') include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; //var_dump($sFileName); var_dump(image_format_supported($sFileName));exit; - $isImageValid = (image_format_supported($sFileName) >= 0 ? true : false); + $imgsupported = image_format_supported($sFileName); + $isImageValid = ($imgsupported >= 0 ? true : false); if (!$isImageValid) { $sErrorNumber = '202'; } @@ -387,7 +388,7 @@ function FileUpload($resourceType, $currentFolder, $sCommand, $CKEcallback = '') if (file_exists($sFilePath)) { //previous checks failed, try once again - if (isset($isImageValid) && $isImageValid === -1 && IsImageValid($sFilePath, $sExtension) === false) { + if (isset($isImageValid) && $imgsupported === -1 && IsImageValid($sFilePath, $sExtension) === false) { dol_syslog("connector.lib.php IsImageValid is ko"); @unlink($sFilePath); $sErrorNumber = '202'; From 15c05d9b7d5c6d953b1d3395fc17130b7e4c29a7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 12:39:42 +0100 Subject: [PATCH 210/816] Fix warnings --- htdocs/comm/action/class/actioncomm.class.php | 10 ++++----- htdocs/core/class/extrafields.class.php | 18 ++++++++-------- htdocs/modulebuilder/index.php | 12 +++++------ htdocs/mrp/mo_card.php | 10 ++++----- htdocs/printing/admin/printing.php | 8 +++---- htdocs/product/admin/product.php | 11 +++++----- htdocs/projet/activity/permonth.php | 20 ++++++++++-------- htdocs/projet/activity/perweek.php | 21 ++++++++++--------- qodana.yaml | 1 + 9 files changed, 57 insertions(+), 54 deletions(-) diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 244b3df9405..e77052e0690 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -225,22 +225,22 @@ class ActionComm extends CommonObject public $transparency; /** - * @var int (0 By default) + * @var int (0 By default) */ public $priority; /** - * @var int[] Array of user ids + * @var int[] Array of user ids */ public $userassigned = array(); /** - * @var int Id of user owner = fk_user_action into table + * @var int Id of user owner = fk_user_action into table */ public $userownerid; /** - * @var int Id of user that has done the event. Used only if AGENDA_ENABLE_DONEBY is set. + * @var int Id of user that has done the event. Used only if AGENDA_ENABLE_DONEBY is set. */ public $userdoneid; @@ -429,7 +429,7 @@ class ActionComm extends CommonObject $now = dol_now(); // Check parameters - if (!isset($this->userownerid) || $this->userownerid === '') { // $this->userownerid may be 0 (anonymous event) of > 0 + if (!isset($this->userownerid) || (string) $this->userownerid === '') { // $this->userownerid may be 0 (anonymous event) or > 0 dol_syslog("You tried to create an event but mandatory property ownerid was not defined", LOG_WARNING); $this->errors[] = 'ErrorActionCommPropertyUserowneridNotDefined'; return -1; diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index b0bc0e55c06..e9817a36d6a 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1141,24 +1141,24 @@ class ExtraFields $out .= ''; } else { - print ''.img_edit().''; + print ''.img_edit().''; print '   '; print ''.img_delete().''; } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index a6eac03cadc..a8a96fb7c07 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -751,7 +751,7 @@ class Form // If info or help with smartphone, show only text (tooltip on click does not works with dialog on smaprtphone) //if (!empty($conf->dol_no_mouse_hover) && !empty($tooltiptrigger)) //{ - //if ($type == 'info' || $type == 'help') return ''.$text.'''; + //if ($type == 'info' || $type == 'help') return ''.$text.''; //} $img = ''; @@ -3041,7 +3041,7 @@ class Form $sql .= " ORDER BY date_price DESC, rowid DESC"; // Warning DESC must be both on date_price and rowid. $sql .= " LIMIT 1"; - dol_syslog(get_class($this).'::constructProductListOption search price for product '.$objp->rowid.' AND level '.$price_level.'', LOG_DEBUG); + dol_syslog(get_class($this).'::constructProductListOption search price for product '.$objp->rowid.' AND level '.$price_level, LOG_DEBUG); $result2 = $this->db->query($sql); if ($result2) { $objp2 = $this->db->fetch_object($result2); diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 25393c6ee56..47525ab5328 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -1988,7 +1988,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin if (isset($histo[$key]['socpeopleassigned']) && is_array($histo[$key]['socpeopleassigned']) && count($histo[$key]['socpeopleassigned']) > 0) { $out .= ''; } elseif ($key == 'type_code') { print ''; } elseif ($key == 'category_code') { print ''; } elseif ($key == 'severity_code') { print ''; } elseif ($key == 'fk_user_assign' || $key == 'fk_user_create') { print ''; } diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index a644880282b..96c8740a006 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1833,7 +1833,8 @@ if ($action == 'create' && $usercancreate) { // Shipping Method if (isModEnabled('expedition')) { print ''; } diff --git a/qodana.yaml b/qodana.yaml index 53cf1a04586..361afb8967f 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -69,5 +69,6 @@ exclude: - name: PhpCoveredCharacterInClassInspection - name: PhpSameParameterValueInspection - name: PhpConditionCheckedByNextConditionInspection + - name: RegExpSingleCharAlternation - name: PhpSuspiciousNameCombinationInspection \ No newline at end of file From 751f79b672a75fa5b99cb1e17f21a50aed3fba10 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 14:01:03 +0100 Subject: [PATCH 215/816] Debug v17 --- htdocs/adherents/class/adherent.class.php | 4 +- htdocs/admin/chequereceipts.php | 2 +- htdocs/comm/action/class/actioncomm.class.php | 6 +- htdocs/comm/propal/card.php | 4 +- htdocs/commande/card.php | 5 +- htdocs/compta/bank/class/account.class.php | 4 +- htdocs/compta/facture/card-rec.php | 2 +- htdocs/compta/facture/card.php | 2 +- htdocs/contact/class/contact.class.php | 4 +- htdocs/contrat/card.php | 2 +- htdocs/core/class/commonobject.class.php | 2 +- htdocs/core/class/html.form.class.php | 12 +- .../browser/default/frmfolders.php | 2 +- htdocs/core/lib/security.lib.php | 6 +- htdocs/core/tpl/login.tpl.php | 2 +- htdocs/core/tpl/objectline_create.tpl.php | 2 +- htdocs/core/tpl/objectline_edit.tpl.php | 2 +- htdocs/core/tpl/passwordforgotten.tpl.php | 4 +- htdocs/core/tpl/passwordreset.tpl.php | 4 +- htdocs/expedition/card.php | 1474 ++++++++--------- htdocs/expedition/shipment.php | 12 +- htdocs/fourn/commande/card.php | 2 +- htdocs/fourn/facture/card.php | 2 +- .../class/knowledgerecord.class.php | 4 +- htdocs/product/class/product.class.php | 4 +- htdocs/product/stock/class/entrepot.class.php | 4 +- htdocs/projet/class/project.class.php | 4 +- htdocs/societe/class/societe.class.php | 2 +- htdocs/supplier_proposal/card.php | 5 +- htdocs/ticket/class/ticket.class.php | 4 +- htdocs/user/class/user.class.php | 4 +- 31 files changed, 798 insertions(+), 794 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 4c68b3e91ec..c17a8c1207b 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -2871,8 +2871,8 @@ class Adherent extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { diff --git a/htdocs/admin/chequereceipts.php b/htdocs/admin/chequereceipts.php index cf93155b814..ed05180ef24 100644 --- a/htdocs/admin/chequereceipts.php +++ b/htdocs/admin/chequereceipts.php @@ -211,7 +211,7 @@ foreach ($dirmodels as $reldir) { print ''; } @@ -2776,7 +2776,7 @@ if ($action == 'create') { } if (!empty($object->lines)) { - $ret = $object->printObjectLines($action, $mysoc, $soc, $lineid, 1); + $object->printObjectLines($action, $mysoc, $soc, $lineid, 1); } // Form to add new line diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 383cf7581e9..66e673abf2d 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1833,7 +1833,8 @@ if ($action == 'create' && $usercancreate) { // Shipping Method if (isModEnabled('expedition')) { print ''; } @@ -2736,7 +2737,7 @@ if ($action == 'create' && $usercancreate) { // Show object lines if (!empty($object->lines)) { - $ret = $object->printObjectLines($action, $mysoc, $soc, $lineid, 1); + $object->printObjectLines($action, $mysoc, $soc, $lineid, 1); } $numlines = count($object->lines); diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index a73fd2b5f2c..4aea92a510e 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -1060,8 +1060,8 @@ class Account extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { diff --git a/htdocs/compta/facture/card-rec.php b/htdocs/compta/facture/card-rec.php index 64a37dcbed4..26fb26d4cdb 100644 --- a/htdocs/compta/facture/card-rec.php +++ b/htdocs/compta/facture/card-rec.php @@ -1635,7 +1635,7 @@ if ($action == 'create') { // Show object lines if (!empty($object->lines)) { $canchangeproduct = 1; - $ret = $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice + $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice } // Form to add new line diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 36c98a495ec..0589ad18c05 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -5423,7 +5423,7 @@ if ($action == 'create') { // Show object lines if (!empty($object->lines)) { - $ret = $object->printObjectLines($action, $mysoc, $soc, $lineid, 1); + $object->printObjectLines($action, $mysoc, $soc, $lineid, 1); } // Form to add new line diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index d535da76199..caea7e0c8d5 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1700,8 +1700,8 @@ class Contact extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 7aad6ca9c54..38efdb3cca9 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -1701,7 +1701,7 @@ if ($action == 'create') { if (empty($senderissupplier)) { print $form->select_produits((!empty($object->lines[$cursorline - 1]->fk_product) ? $object->lines[$cursorline - 1]->fk_product : 0), 'idprod'); } else { - print $form->select_produits_fournisseurs((!empty($object->lines[$cursorline - 1]->fk_product) ? $object->lines[$cursorline - 1]->fk_product : 0), 'idprod'); + $form->select_produits_fournisseurs((!empty($object->lines[$cursorline - 1]->fk_product) ? $object->lines[$cursorline - 1]->fk_product : 0), 'idprod'); } } print '
'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 599a7866da4..f1920c74931 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -9957,7 +9957,7 @@ abstract class CommonObject * @param int[]|int $categories Category ID or array of Categories IDs * @param string $type_categ Category type ('customer', 'supplier', 'website_page', ...) definied into const class Categorie type * @param boolean $remove_existing True: Remove existings categories from Object if not supplies by $categories, False: let them - * @return int <0 if KO, >0 if OK + * @return int <0 if KO, >0 if OK */ public function setCategoriesCommon($categories, $type_categ = '', $remove_existing = true) { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 3f4579340d0..c33ffe28551 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3256,7 +3256,7 @@ class Form * @param string $morecss Add more CSS * @param int $showstockinlist Show stock information (slower). * @param string $placeholder Placeholder - * @return array Array of keys for json + * @return array|string Array of keys for json or HTML component */ public function select_produits_fournisseurs_list($socid, $selected = '', $htmlname = 'productid', $filtertype = '', $filtre = '', $filterkey = '', $statut = -1, $outputmode = 0, $limit = 100, $alsoproductwithnosupplierprice = 0, $morecss = '', $showstockinlist = 0, $placeholder = '') { @@ -3658,14 +3658,14 @@ class Form include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname); - - if (empty($outputmode)) { - return $out; - } - return $outarray; } else { dol_print_error($this->db); } + + if (empty($outputmode)) { + return $out; + } + return $outarray; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps diff --git a/htdocs/core/filemanagerdol/browser/default/frmfolders.php b/htdocs/core/filemanagerdol/browser/default/frmfolders.php index d8d1fae179a..a1b03693324 100644 --- a/htdocs/core/filemanagerdol/browser/default/frmfolders.php +++ b/htdocs/core/filemanagerdol/browser/default/frmfolders.php @@ -53,7 +53,7 @@ top_httphead(); --> diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index deff1af567c..0a7e9615a70 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -723,7 +723,11 @@ function restrictedArea(User $user, $features, $object = 0, $tableandshare = '', if ($mode) { return $ok ? 1 : 0; } else { - return $ok ? 1 : accessforbidden('', 1, 1, 0, $params); + if ($ok) { + return 1; + } else { + accessforbidden('', 1, 1, 0, $params); + } } } diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php index eaf2d602571..7f97e751ded 100644 --- a/htdocs/core/tpl/login.tpl.php +++ b/htdocs/core/tpl/login.tpl.php @@ -98,7 +98,7 @@ if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { $disablenofollow = 0; } -print top_htmlhead('', $titleofloginpage, 0, 0, $arrayofjs, array(), 1, $disablenofollow); +top_htmlhead('', $titleofloginpage, 0, 0, $arrayofjs, array(), 1, $disablenofollow); $colorbackhmenu1 = '60,70,100'; // topmenu diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index c3b94332909..ef6987e0e6c 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -214,7 +214,7 @@ if ($nolinesbefore) { echo ' '; } } - echo $form->select_type_of_lines(GETPOSTISSET("type") ? GETPOST("type", 'alpha', 2) : -1, 'type', 1, 1, $forceall); + $form->select_type_of_lines(GETPOSTISSET("type") ? GETPOST("type", 'alpha', 2) : -1, 'type', 1, 1, $forceall); echo ''; } // Predefined product/service diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index 5520215d89a..dbc8b407fa5 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -120,7 +120,7 @@ $coldisplay++; print ''; } else { if ($senderissupplier) { - print $form->select_produits_fournisseurs(!empty($line->fk_product) ? $line->fk_product : 0, 'productid'); + $form->select_produits_fournisseurs(!empty($line->fk_product) ? $line->fk_product : 0, 'productid'); } else { print $form->select_produits(!empty($line->fk_product) ? $line->fk_product : 0, 'productid'); } diff --git a/htdocs/core/tpl/passwordforgotten.tpl.php b/htdocs/core/tpl/passwordforgotten.tpl.php index 3fdbcd14ef3..e9d7de9a1bf 100644 --- a/htdocs/core/tpl/passwordforgotten.tpl.php +++ b/htdocs/core/tpl/passwordforgotten.tpl.php @@ -76,7 +76,7 @@ if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { $disablenofollow = 0; } -print top_htmlhead('', $titleofpage, 0, 0, $arrayofjs, array(), 1, $disablenofollow); +top_htmlhead('', $titleofpage, 0, 0, $arrayofjs, array(), 1, $disablenofollow); $colorbackhmenu1 = '60,70,100'; // topmenu @@ -253,7 +253,7 @@ if ($mode == 'dolibarr' || !$disabled) { diff --git a/htdocs/core/tpl/passwordreset.tpl.php b/htdocs/core/tpl/passwordreset.tpl.php index 1f35b1a251a..e9d518dba64 100644 --- a/htdocs/core/tpl/passwordreset.tpl.php +++ b/htdocs/core/tpl/passwordreset.tpl.php @@ -77,7 +77,7 @@ if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { $disablenofollow = 0; } -print top_htmlhead('', $titleofpage, 0, 0, $arrayofjs, array(), 1, $disablenofollow); +top_htmlhead('', $titleofpage, 0, 0, $arrayofjs, array(), 1, $disablenofollow); $colorbackhmenu1 = '60,70,100'; // topmenu @@ -292,7 +292,7 @@ if ($mode == 'dolibarr' || !$disabled) { diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index ab8c4a28cbc..3e096bcc55d 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -1647,7 +1647,7 @@ if ($action == 'create') { dol_print_error($db); } } -} elseif ($id || $ref) { +} elseif ($object->id > 0) { /* *************************************************************************** */ /* */ /* Edit and view mode */ @@ -1657,828 +1657,826 @@ if ($action == 'create') { $num_prod = count($lines); - if ($object->id > 0) { - if (!empty($object->origin) && $object->origin_id > 0) { - $typeobject = $object->origin; - $origin = $object->origin; - $origin_id = $object->origin_id; - $object->fetch_origin(); // Load property $object->commande, $object->propal, ... + if (!empty($object->origin) && $object->origin_id > 0) { + $typeobject = $object->origin; + $origin = $object->origin; + $origin_id = $object->origin_id; + $object->fetch_origin(); // Load property $object->commande, $object->propal, ... + } + + $soc = new Societe($db); + $soc->fetch($object->socid); + + $res = $object->fetch_optionals(); + + $head = shipping_prepare_head($object); + print dol_get_fiche_head($head, 'shipping', $langs->trans("Shipment"), -1, $object->picto); + + $formconfirm = ''; + + // Confirm deleteion + if ($action == 'delete') { + $formquestion = array(); + if ($object->statut == Expedition::STATUS_CLOSED && !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) { + $formquestion = array( + array( + 'label' => $langs->trans('ShipmentIncrementStockOnDelete'), + 'name' => 'alsoUpdateStock', + 'type' => 'checkbox', + 'value' => 0 + ), + ); + } + $formconfirm = $form->formconfirm( + $_SERVER['PHP_SELF'].'?id='.$object->id, + $langs->trans('DeleteSending'), + $langs->trans("ConfirmDeleteSending", $object->ref), + 'confirm_delete', + $formquestion, + 0, + 1 + ); + } + + // Confirmation validation + if ($action == 'valid') { + $objectref = substr($object->ref, 1, 4); + if ($objectref == 'PROV') { + $numref = $object->getNextNumRef($soc); + } else { + $numref = $object->ref; } - $soc = new Societe($db); - $soc->fetch($object->socid); + $text = $langs->trans("ConfirmValidateSending", $numref); - $res = $object->fetch_optionals(); + if (isModEnabled('notification')) { + require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; + $notify = new Notify($db); + $text .= '
'; + $text .= $notify->confirmMessage('SHIPPING_VALIDATE', $object->socid, $object); + } - $head = shipping_prepare_head($object); - print dol_get_fiche_head($head, 'shipping', $langs->trans("Shipment"), -1, $object->picto); + $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateSending'), $text, 'confirm_valid', '', 0, 1); + } + // Confirm cancelation + if ($action == 'cancel') { + $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelSending'), $langs->trans("ConfirmCancelSending", $object->ref), 'confirm_cancel', '', 0, 1); + } - $formconfirm = ''; + // Call Hook formConfirm + $parameters = array('formConfirm' => $formconfirm); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $formconfirm .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $formconfirm = $hookmanager->resPrint; + } - // Confirm deleteion - if ($action == 'delete') { - $formquestion = array(); - if ($object->statut == Expedition::STATUS_CLOSED && !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) { - $formquestion = array( - array( - 'label' => $langs->trans('ShipmentIncrementStockOnDelete'), - 'name' => 'alsoUpdateStock', - 'type' => 'checkbox', - 'value' => 0 - ), - ); + // Print form confirm + print $formconfirm; + + // Calculate totalWeight and totalVolume for all products + // by adding weight and volume of each product line. + $tmparray = $object->getTotalWeightVolume(); + $totalWeight = $tmparray['weight']; + $totalVolume = $tmparray['volume']; + + + if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) { + $objectsrc = new Commande($db); + $objectsrc->fetch($object->$typeobject->id); + } + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { + $objectsrc = new Propal($db); + $objectsrc->fetch($object->$typeobject->id); + } + + // Shipment card + $linkback = ''.$langs->trans("BackToList").''; + $morehtmlref = '
'; + // Ref customer shipment + $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', 0, 1); + $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':'.$conf->global->THIRDPARTY_REF_INPUT_SIZE : ''), '', null, null, '', 1); + // Thirdparty + $morehtmlref .= '
'.$object->thirdparty->getNomUrl(1); + // Project + if (isModEnabled('project')) { + $langs->load("projects"); + $morehtmlref .= '
'; + if (0) { // Do not change on shipment + $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"'); + if ($action != 'classify') { + $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $formconfirm = $form->formconfirm( - $_SERVER['PHP_SELF'].'?id='.$object->id, - $langs->trans('DeleteSending'), - $langs->trans("ConfirmDeleteSending", $object->ref), - 'confirm_delete', - $formquestion, - 0, - 1 - ); - } - - // Confirmation validation - if ($action == 'valid') { - $objectref = substr($object->ref, 1, 4); - if ($objectref == 'PROV') { - $numref = $object->getNextNumRef($soc); - } else { - $numref = $object->ref; - } - - $text = $langs->trans("ConfirmValidateSending", $numref); - - if (isModEnabled('notification')) { - require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; - $notify = new Notify($db); - $text .= '
'; - $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); - } - // Confirm cancelation - if ($action == 'cancel') { - $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelSending'), $langs->trans("ConfirmCancelSending", $object->ref), 'confirm_cancel', '', 0, 1); - } - - // Call Hook formConfirm - $parameters = array('formConfirm' => $formconfirm); - $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook - if (empty($reshook)) { - $formconfirm .= $hookmanager->resPrint; - } elseif ($reshook > 0) { - $formconfirm = $hookmanager->resPrint; - } - - // Print form confirm - print $formconfirm; - - // Calculate totalWeight and totalVolume for all products - // by adding weight and volume of each product line. - $tmparray = $object->getTotalWeightVolume(); - $totalWeight = $tmparray['weight']; - $totalVolume = $tmparray['volume']; - - - if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) { - $objectsrc = new Commande($db); - $objectsrc->fetch($object->$typeobject->id); - } - if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { - $objectsrc = new Propal($db); - $objectsrc->fetch($object->$typeobject->id); - } - - // Shipment card - $linkback = ''.$langs->trans("BackToList").''; - $morehtmlref = '
'; - // Ref customer shipment - $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', 0, 1); - $morehtmlref .= $form->editfieldval("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string'.(isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':'.$conf->global->THIRDPARTY_REF_INPUT_SIZE : ''), '', null, null, '', 1); - // Thirdparty - $morehtmlref .= '
'.$object->thirdparty->getNomUrl(1); - // Project - if (isModEnabled('project')) { - $langs->load("projects"); - $morehtmlref .= '
'; - if (0) { // Do not change on shipment - $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"'); - if ($action != 'classify') { - $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; - } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $objectsrc->socid, $objectsrc->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, ($action == 'classify' ? 1 : 0), 0, 1, ''); - } else { - if (!empty($objectsrc) && !empty($objectsrc->fk_project)) { - $proj = new Project($db); - $proj->fetch($objectsrc->fk_project); - $morehtmlref .= $proj->getNomUrl(1); - if ($proj->title) { - $morehtmlref .= ' - '.dol_escape_htmltag($proj->title).''; - } + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $objectsrc->socid, $objectsrc->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, ($action == 'classify' ? 1 : 0), 0, 1, ''); + } else { + if (!empty($objectsrc) && !empty($objectsrc->fk_project)) { + $proj = new Project($db); + $proj->fetch($objectsrc->fk_project); + $morehtmlref .= $proj->getNomUrl(1); + if ($proj->title) { + $morehtmlref .= ' - '.dol_escape_htmltag($proj->title).''; } } } - $morehtmlref .= '
'; + } + $morehtmlref .= '
'; - dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); - print '
'; - print '
'; - print '
'; + print '
'; + print '
'; + print '
'; - print '
'.$langs->trans('Ref').'
'.$langs->trans('Date').''.dol_print_date($object->datep, 'day').'
'; +print $form->editfieldkey("Date", 'datep', $object->datep, $object, 1, 'datepicker'); +print ''; +print $form->editfieldval("Date", 'datep', $object->datep, $object, 1, 'datepicker'); +print "
'.$langs->trans('Mode').''; +print '
'.$langs->trans('Mode').''; print $langs->trans("PaymentType".$object->type_code); print '
'.$langs->trans('Numero').''.$object->num_payment.'
'.$langs->trans('Numero').''.dol_escape_htmltag($object->num_payment).'
'.$langs->trans('Amount').''.price($object->amount, 0, $outputlangs, 1, -1, -1, $conf->currency).'
'.$langs->trans('Amount').''.price($object->amount, 0, $langs, 1, -1, -1, $conf->currency).'
'.$langs->trans('Note').''.nl2br($object->note).'
'.$langs->trans('Note').''.dol_nl2br($object->note).'
'; -print $form->editfieldkey("Date", 'datep', $object->datep, $object, 1, 'datepicker'); +print $form->editfieldkey("Date", 'datep', $object->datep, $object, 1, 'datehourpicker'); print ''; -print $form->editfieldval("Date", 'datep', $object->datep, $object, 1, 'datepicker'); +print $form->editfieldval("Date", 'datep', $object->datep, $object, 1, 'datehourpicker', '', null, null, '', 0, '', 'id', 'tzuserrel'); print "
'.dol_print_date($db->jdate($obj->datep), 'day')."'.dol_print_date($db->jdate($obj->datep), 'dayhour', 'tzuserrel')."
'; print $form->editfieldkey("Date", 'datep', $object->datep, $object, 1, 'datehourpicker'); print ''; -print $form->editfieldval("Date", 'datep', $object->datep, $object, 1, 'datehourpicker', '', null, null, '', 0, '', 'id', 'tzuserrel'); +print $form->editfieldval("Date", 'datep', $object->datep, $object, 1, 'datehourpicker', '', null, null, '', 0, '', 'id', 'tzuserrel', array('addnowlink'=>1)); print "
'; + print '
'; print ''.img_object($langs->trans("Payment"), "payment").' '.$objp->rowid.''.dol_print_date($db->jdate($objp->dp), 'day')."'.dol_print_date($db->jdate($objp->dp), 'dayhour', 'tzuserrel')."".$labeltype.' '.$objp->num_payment."
'.$langs->trans("AlreadyPaid")." :".price($totalpaid)."
'.$langs->trans("AmountExpected")." :".price($object->amount)."
'.$langs->trans("AlreadyPaid").' :'.price($totalpaid)."
'.$langs->trans("AmountExpected").' :'.price($object->amount)."
'.$langs->trans("RemainderToPay").''.price($total-$sumpaid,0,$outputlangs,1,-1,-1,$conf->currency).'
'.$langs->trans("Date").''; - $datepaye = dol_mktime(12, 0, 0, GETPOST("remonth", 'int'), GETPOST("reday", 'int'), GETPOST("reyear", 'int')); + $datepaye = dol_mktime(GETPOST("rehour", 'int'), GETPOST("remin", 'int'), GETPOST("resec", 'int'), GETPOST("remonth", 'int'), GETPOST("reday", 'int'), GETPOST("reyear", 'int')); $datepayment = empty($conf->global->MAIN_AUTOFILL_DATE) ? (GETPOST("remonth") ? $datepaye : -1) : ''; - print $form->selectDate($datepayment, '', '', '', '', "add_payment", 1, 1); + print $form->selectDate($datepayment, '', 1, 1, 0, "add_payment", 1, 1); print "
' . $langs->trans("TotalForAccount") . ' ' . length_accountg($displayed_account_number) . ':'.price($sous_total_debit).''.price($sous_total_credit).''.price(price2num($sous_total_debit, 'MT')).''.price(price2num($sous_total_credit, 'MT')).'
'.$langs->trans("Balance").':'; - print price($sous_total_debit - $sous_total_credit); + print price(price2num($sous_total_debit - $sous_total_credit, 'MT')); print ''; - print price($sous_total_credit - $sous_total_debit); + print price(price2num($sous_total_credit - $sous_total_debit, 'MT')); print '
'.$langs->trans("TotalForAccount").' '.$accountg.':'.price($sous_total_debit).''.price($sous_total_credit).''.price(price2num($sous_total_debit, 'MT')).''.price(price2num($sous_total_credit, 'MT')).'
'.$langs->trans("Balance").':'; - print price($sous_total_debit - $sous_total_credit); + print price(price2num($sous_total_debit - $sous_total_credit, 'MT')); print ''; - print price($sous_total_credit - $sous_total_debit); + print price(price2num($sous_total_credit - $sous_total_debit, 'MT')); print '
'.$langs->trans("Asset"); + echo ''.$langs->trans("Asset"); if (!empty($showImportButton) && !empty($conf->global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES)) { print ' '; - echo ''.$objectlink->getNomUrl(1).''.$objectlink->getNomUrl(1).''.$objectlink->label.''.dol_print_date($objectlink->date_start, 'day').''; diff --git a/htdocs/bom/tpl/linkedobjectblock.tpl.php b/htdocs/bom/tpl/linkedobjectblock.tpl.php index 8a98c078bc5..1765e9a84c1 100644 --- a/htdocs/bom/tpl/linkedobjectblock.tpl.php +++ b/htdocs/bom/tpl/linkedobjectblock.tpl.php @@ -47,12 +47,12 @@ foreach ($linkedObjectBlock as $key => $objectlink) { $trclass .= ' liste_sub_total'; } echo '
'.$langs->trans("Bom"); + echo ''.$langs->trans("Bom"); if (!empty($showImportButton) && $conf->global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES) { print ' '; - echo ''.$objectlink->getNomUrl(1).''.$objectlink->getNomUrl(1).''; $result = $product_static->fetch($objectlink->fk_product); diff --git a/htdocs/comm/propal/tpl/linkedobjectblock.tpl.php b/htdocs/comm/propal/tpl/linkedobjectblock.tpl.php index 613f06a6feb..6539efd6a27 100644 --- a/htdocs/comm/propal/tpl/linkedobjectblock.tpl.php +++ b/htdocs/comm/propal/tpl/linkedobjectblock.tpl.php @@ -52,13 +52,13 @@ foreach ($linkedObjectBlock as $key => $objectlink) { $trclass .= ' liste_sub_total'; } print '
'.$langs->trans("Proposal"); + print ''.$langs->trans("Proposal"); if (!empty($showImportButton) && $conf->global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES) { $url = DOL_URL_ROOT.'/comm/propal/card.php?id='.$objectlink->id; print ' '; } print ''.$objectlink->getNomUrl(1).''.$objectlink->getNomUrl(1).''.$objectlink->ref_client.''.dol_print_date($objectlink->date, 'day').''; diff --git a/htdocs/commande/tpl/linkedobjectblock.tpl.php b/htdocs/commande/tpl/linkedobjectblock.tpl.php index 819a6ecb74f..a6a1fde3851 100644 --- a/htdocs/commande/tpl/linkedobjectblock.tpl.php +++ b/htdocs/commande/tpl/linkedobjectblock.tpl.php @@ -46,12 +46,12 @@ foreach ($linkedObjectBlock as $key => $objectlink) { $trclass .= ' liste_sub_total'; } echo '
'.$langs->trans("CustomerOrder"); + echo ''.$langs->trans("CustomerOrder"); if (!empty($showImportButton) && !empty($conf->global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES)) { print ' '; - echo ''.$objectlink->getNomUrl(1).''.$objectlink->getNomUrl(1).''.$objectlink->ref_client.''.dol_print_date($objectlink->date, 'day').''; diff --git a/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php b/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php index 92204520b35..71cb16ec818 100644 --- a/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php +++ b/htdocs/compta/facture/tpl/linkedobjectblock.tpl.php @@ -67,7 +67,7 @@ foreach ($linkedObjectBlock as $key => $objectlink) { break; } print ''.$objectlink->getNomUrl(1).''.$objectlink->getNomUrl(1).''.$objectlink->ref_client.''.dol_print_date($objectlink->date, 'day').''; diff --git a/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php b/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php index d7e68e274fa..c3c774b79e7 100644 --- a/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php +++ b/htdocs/compta/facture/tpl/linkedobjectblockForRec.tpl.php @@ -47,7 +47,7 @@ foreach ($linkedObjectBlock as $key => $objectlink) { ?>
trans("RepeatableInvoice"); ?>getNomUrl(1); ?>getNomUrl(1); ?> date_when, 'day'); ?> element == 'mo') { $trclass = 'oddeven'; echo '
' . $langs->trans("ManufacturingOrder"); + echo '' . $langs->trans("ManufacturingOrder"); if (!empty($showImportButton) && $conf->global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES) { print ' '; - echo '' . $objectlink->getNomUrl(1) . '' . $objectlink->getNomUrl(1) . ''; + echo ''; // $result = $product_static->fetch($objectlink->fk_product); print '' . dol_print_date($objectlink->date_creation, 'day') . '' . dol_print_date($objectlink->date_creation, 'day') . '-' . $objectlink->getLibStatut(3) . ''; @@ -93,14 +93,14 @@ if ($object->element == 'mo') { $trclass .= ' liste_sub_total'; } print '
'.$langs->trans("ManufacturingOrder"); + print ''.$langs->trans("ManufacturingOrder"); if (!empty($showImportButton) && $conf->global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES) { $url = DOL_URL_ROOT.'/mrp/mo_card.php?id='.$objectlink->id; print ' '; } print ''.$objectlink->getNomUrl(1).''.$objectlink->getNomUrl(1).''.$objectlink->ref_client.''.dol_print_date($objectlink->date_start_planned, 'day').'-
trans("Reception"); ?> + trans("Reception"); ?> global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES) { print ' getNomUrl(1); ?>getNomUrl(1); ?> ref_supplier); ?> date_delivery, 'day'); ?> $objectlink) { } ?>
trans("Ticket"); ?> + trans("Ticket"); ?> global->MAIN_ENABLE_IMPORT_LINKED_OBJECT_LINES) { print ' getNomUrl(1); ?>getNomUrl(1); ?> ref_client; ?> datec, 'day'); ?> '.$langs->trans('Qty').''; print ''; print $langs->trans('Unit'); @@ -145,7 +145,7 @@ print ''; print ''; print ''.$form->textwithpicto($langs->trans('Qty'), ($filtertype != 1) ? $langs->trans("QtyRequiredIfNoLoss") : '').'' . $langs->trans('Unit') . ''; $label = $tmpproduct->getLabelOfUnit('long'); if ($label !== '') { From 0710031b32afc9804980c99f80c371423663b7cc Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Fri, 30 Dec 2022 12:44:36 +0100 Subject: [PATCH 164/816] update code toward php8 compliance --- htdocs/contrat/card.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 220356310fa..ae2302b55f5 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -1513,7 +1513,7 @@ if ($action == 'create') { // print ''.$langs->trans("PriceUHTCurrency").''.$langs->trans("Qty").''.$langs->trans("Unit").''.$langs->trans("ReductionShort").''.$objp->qty.''.$langs->trans($object->lines[$cursorline - 1]->getLabelOfUnit()).''; print $form->selectUnits($objp->fk_unit, "unit"); print ''.$langs->trans('PriceUHTCurrency').''.$langs->trans('Qty').''.$langs->trans('Unit').''.$langs->trans('ReductionShort').'trans('Qty'); ?> '; print ''; print $langs->trans('Unit'); @@ -424,7 +424,7 @@ if ($nolinesbefore) { "> '; print $form->selectUnits(empty($line->fk_unit) ? $conf->global->PRODUCT_USE_UNITS : $line->fk_unit, "units"); From 2df271f76c6014c655b60cec349b1fb0fdbaa300 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 12:58:08 +0100 Subject: [PATCH 182/816] Fix qodana by cron only --- .github/workflows/code_quality.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index b27b64428e7..2b01a676db1 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -1,10 +1,11 @@ name: Qodana on: - workflow_dispatch: - pull_request: - push: - branches: - - develop + schedule: + - cron: "0 20 * * *" +# workflow_dispatch: +# push: +# branches: +# - develop jobs: qodana: From b4e76da867051167d26b392badf9eeb687f81df7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 13:41:12 +0100 Subject: [PATCH 183/816] Fix warning --- htdocs/emailcollector/class/emailcollector.class.php | 2 +- qodana.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 5f577421cae..12531a57c5e 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1518,7 +1518,7 @@ class EmailCollector extends CommonObject $trackidfoundintorecipientid = 0; $reg = array(); // See also later list of all supported tags... - if (preg_match('/\+(thi|ctc|use|mem|sub|proj|tas|con|tic|job|pro|ord|inv|spro|sor|sin|leav|stockinv|job|surv|salary)([0-9]+)@/', $emailto, $reg)) { + if (preg_match('/\+(thi|ctc|use|mem|sub|proj|tas|con|tic|pro|ord|inv|spro|sor|sin|leav|stockinv|job|surv|salary)([0-9]+)@/', $emailto, $reg)) { $trackidfoundintorecipienttype = $reg[1]; $trackidfoundintorecipientid = $reg[2]; } elseif (preg_match('/\+emailing-(\w+)@/', $emailto, $reg)) { // Can be 'emailing-test' or 'emailing-IdMailing-IdRecipient' diff --git a/qodana.yaml b/qodana.yaml index b1a76747a5b..9de5ffc19de 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -1,6 +1,6 @@ version: "1.0" linter: jetbrains/qodana-php:2022.3-eap -failThreshold: 0 +failThreshold: 20000 profile: name: qodana.recommended exclude: From e8ea213503be7bd550b40ec9c0774bf7c6dfa411 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 13:51:58 +0100 Subject: [PATCH 184/816] Fix warning --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 85cb8a9cdfe..9f67a0e3909 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5058,7 +5058,7 @@ function dol_print_error($db = '', $error = '', $errors = null) } elseif (is_array($errors)) { $errors = array_merge(array($error), $errors); } else { - $errors = array_merge(array($error)); + $errors = array_merge(array($error), array($errors)); } foreach ($errors as $msg) { From db877b0bcb0997ca68de67f6e257e4523e3e7976 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 14:23:24 +0100 Subject: [PATCH 185/816] Fix warning --- .../compta/prelevement/class/bonprelevement.class.php | 10 ++++++++++ htdocs/opensurvey/class/opensurveysondage.class.php | 2 ++ htdocs/website/class/websitepage.class.php | 2 ++ 3 files changed, 14 insertions(+) diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 959630a5538..373615ecdfb 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -72,6 +72,7 @@ class BonPrelevement extends CommonObject public $date_trans; public $user_trans; + public $method_trans; public $total; public $fetched; @@ -83,6 +84,15 @@ class BonPrelevement extends CommonObject public $invoice_in_error = array(); public $thirdparty_in_error = array(); + public $amount; + public $note; + public $datec; + + public $date_credit; + public $user_credit; + + public $type; + const STATUS_DRAFT = 0; const STATUS_TRANSFERED = 1; const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type diff --git a/htdocs/opensurvey/class/opensurveysondage.class.php b/htdocs/opensurvey/class/opensurveysondage.class.php index 2014e57f629..f5dadd90f2e 100644 --- a/htdocs/opensurvey/class/opensurveysondage.class.php +++ b/htdocs/opensurvey/class/opensurveysondage.class.php @@ -83,6 +83,8 @@ class Opensurveysondage extends CommonObject public $date_fin = ''; + public $date_m; + /** * @var int status */ diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 8660ca0b0c1..55916fc4fe2 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -56,6 +56,8 @@ class WebsitePage extends CommonObject */ public $fk_website; + public $fk_page; // If translation of another page + public $pageurl; public $aliasalt; public $type_container; From 24e3e278ed2ac65fd0a530466e5f141359f2b1b1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 13:51:58 +0100 Subject: [PATCH 186/816] Fix warning --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 10eb7b389a8..5b791594fea 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5058,7 +5058,7 @@ function dol_print_error($db = '', $error = '', $errors = null) } elseif (is_array($errors)) { $errors = array_merge(array($error), $errors); } else { - $errors = array_merge(array($error)); + $errors = array_merge(array($error), array($errors)); } foreach ($errors as $msg) { From 5d840843965974ac65e85e5157afb1c08fe43d6d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 14:23:24 +0100 Subject: [PATCH 187/816] Fix warning --- .../compta/prelevement/class/bonprelevement.class.php | 10 ++++++++++ htdocs/opensurvey/class/opensurveysondage.class.php | 2 ++ htdocs/website/class/websitepage.class.php | 2 ++ 3 files changed, 14 insertions(+) diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 959630a5538..373615ecdfb 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -72,6 +72,7 @@ class BonPrelevement extends CommonObject public $date_trans; public $user_trans; + public $method_trans; public $total; public $fetched; @@ -83,6 +84,15 @@ class BonPrelevement extends CommonObject public $invoice_in_error = array(); public $thirdparty_in_error = array(); + public $amount; + public $note; + public $datec; + + public $date_credit; + public $user_credit; + + public $type; + const STATUS_DRAFT = 0; const STATUS_TRANSFERED = 1; const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type diff --git a/htdocs/opensurvey/class/opensurveysondage.class.php b/htdocs/opensurvey/class/opensurveysondage.class.php index 2014e57f629..f5dadd90f2e 100644 --- a/htdocs/opensurvey/class/opensurveysondage.class.php +++ b/htdocs/opensurvey/class/opensurveysondage.class.php @@ -83,6 +83,8 @@ class Opensurveysondage extends CommonObject public $date_fin = ''; + public $date_m; + /** * @var int status */ diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 8660ca0b0c1..55916fc4fe2 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -56,6 +56,8 @@ class WebsitePage extends CommonObject */ public $fk_website; + public $fk_page; // If translation of another page + public $pageurl; public $aliasalt; public $type_container; From 95986647b411827fa05496533c85f0753ad0ab13 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 14:56:55 +0100 Subject: [PATCH 188/816] Fix php8 compatibility --- .../actions_adherentcard_default.class.php | 25 ---- .../actions_contactcard_default.class.php | 25 ---- htdocs/core/class/canvas.class.php | 1 + .../product/actions_card_product.class.php | 139 ------------------ .../service/actions_card_service.class.php | 100 ------------- htdocs/product/card.php | 1 - 6 files changed, 1 insertion(+), 290 deletions(-) diff --git a/htdocs/adherents/canvas/default/actions_adherentcard_default.class.php b/htdocs/adherents/canvas/default/actions_adherentcard_default.class.php index c79143ab345..d5465abfcdd 100644 --- a/htdocs/adherents/canvas/default/actions_adherentcard_default.class.php +++ b/htdocs/adherents/canvas/default/actions_adherentcard_default.class.php @@ -116,30 +116,5 @@ class ActionsAdherentCardDefault extends ActionsAdherentCardCommon $this->tpl['action_delete'] = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$this->object->id, $langs->trans("DeleteAdherent"), $langs->trans("ConfirmDeleteAdherent"), "confirm_delete", '', 0, 1); } } - - if ($action == 'list') { - $this->LoadListDatas($limit, $offset, $sortfield, $sortorder); - } - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Fetch datas list and save into ->list_datas - * - * @param int $limit Limit number of responses - * @param int $offset Offset for first response - * @param string $sortfield Sort field - * @param string $sortorder Sort order ('ASC' or 'DESC') - * @return void - */ - public function LoadListDatas($limit, $offset, $sortfield, $sortorder) - { - // phpcs:enable - global $conf, $langs; - - //$this->getFieldList(); - - $this->list_datas = array(); } } diff --git a/htdocs/contact/canvas/default/actions_contactcard_default.class.php b/htdocs/contact/canvas/default/actions_contactcard_default.class.php index 846f7440f97..f126b8c32a0 100644 --- a/htdocs/contact/canvas/default/actions_contactcard_default.class.php +++ b/htdocs/contact/canvas/default/actions_contactcard_default.class.php @@ -115,30 +115,5 @@ class ActionsContactCardDefault extends ActionsContactCardCommon $this->tpl['action_delete'] = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$this->object->id, $langs->trans("DeleteContact"), $langs->trans("ConfirmDeleteContact"), "confirm_delete", '', 0, 1); } } - - if ($action == 'list') { - $this->LoadListDatas($limit, $offset, $sortfield, $sortorder); - } - } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Fetch datas list and save into ->list_datas - * - * @param int $limit Limit number of responses - * @param int $offset Offset for first response - * @param string $sortfield Sort field - * @param string $sortorder Sort order ('ASC' or 'DESC') - * @return void - */ - public function LoadListDatas($limit, $offset, $sortfield, $sortorder) - { - // phpcs:enable - global $conf, $langs; - - //$this->getFieldList(); - - $this->list_datas = array(); } } diff --git a/htdocs/core/class/canvas.class.php b/htdocs/core/class/canvas.class.php index 67443a7bdb8..b40f086a1aa 100644 --- a/htdocs/core/class/canvas.class.php +++ b/htdocs/core/class/canvas.class.php @@ -164,6 +164,7 @@ class Canvas */ public function displayCanvasExists($action) { + // template_dir should be '/'.$this->dirmodule.'/canvas/'.$this->canvas.'/tpl/', for example '/mymodule/canvas/product/tpl' if (empty($this->template_dir)) { return 0; } diff --git a/htdocs/product/canvas/product/actions_card_product.class.php b/htdocs/product/canvas/product/actions_card_product.class.php index 9e6db35754e..56ebab13344 100644 --- a/htdocs/product/canvas/product/actions_card_product.class.php +++ b/htdocs/product/canvas/product/actions_card_product.class.php @@ -39,7 +39,6 @@ class ActionsCardProduct // List of fiels for action=list public $field_list = array(); - public $list_datas = array(); /** @@ -88,8 +87,6 @@ class ActionsCardProduct } $this->object = $tmpobject; - //parent::assign_values($action); - foreach ($this->object as $key => $value) { $this->tpl[$key] = $value; } @@ -227,10 +224,6 @@ class ActionsCardProduct $this->tpl['fiche_end'] = dol_get_fiche_end(); } - - if ($action == 'list') { - $this->LoadListDatas($limit, $offset, $sortfield, $sortorder); - } } @@ -281,136 +274,4 @@ class ActionsCardProduct dol_print_error($this->db, $sql); } } - - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Fetch datas list and save into ->list_datas - * - * @param int $limit Limit number of responses - * @param int $offset Offset for first response - * @param string $sortfield Sort field - * @param string $sortorder Sort order ('ASC' or 'DESC') - * @return void - */ - public function LoadListDatas($limit, $offset, $sortfield, $sortorder) - { - // phpcs:enable - global $conf, $langs; - - $this->getFieldListCanvas(); - - $this->list_datas = array(); - - // Clean parameters - $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); - - foreach ($this->field_list as $field) { - if ($field['enabled']) { - $fieldname = "s".$field['alias']; - $$fieldname = GETPOST($fieldname); - } - } - - $sql = 'SELECT DISTINCT '; - - // Fields requiered - $sql .= 'p.rowid, p.price_base_type, p.fk_product_type, p.seuil_stock_alerte, p.entity'; - - // Fields not requiered - foreach ($this->field_list as $field) { - if ($field['enabled']) { - $sql .= ", ".$field['name']." as ".$field['alias']; - } - } - - $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; - $sql .= " WHERE p.entity IN (".getEntity('product').")"; - - if ($sall) { - $clause = ''; - $sql .= " AND ("; - foreach ($this->field_list as $field) { - if ($field['enabled']) { - $sql .= $clause." ".$field['name']." LIKE '%".$this->db->escape($sall)."%'"; - if ($clause == '') { - $clause = ' OR'; - } - } - } - $sql .= ")"; - } - - // Search fields - foreach ($this->field_list as $field) { - if ($field['enabled']) { - $fieldname = "s".$field['alias']; - if (${$fieldname}) { - $sql .= " AND ".$field['name']." LIKE '%".$this->db->escape(${$fieldname})."%'"; - } - } - } - - if (GETPOSTISSET("tosell")) { - $sql .= " AND p.tosell = ".((int) GETPOST("tosell", "int")); - } - if (GETPOSTISSET("canvas")) { - $sql .= " AND p.canvas = '".$this->db->escape(GETPOST("canvas"))."'"; - } - $sql .= $this->db->order($sortfield, $sortorder); - $sql .= $this->db->plimit($limit + 1, $offset); - //print $sql; - - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - - $i = 0; - while ($i < min($num, $limit)) { - $datas = array(); - - $obj = $this->db->fetch_object($resql); - - $datas["id"] = $obj->rowid; - - foreach ($this->field_list as $field) { - if ($field['enabled']) { - $alias = $field['alias']; - - if ($alias == 'ref') { - $this->id = $obj->rowid; - $this->ref = $obj->$alias; - $this->type = $obj->fk_product_type; - $this->entity = $obj->entity; - $datas[$alias] = $this->getNomUrl(1, '', 24); - } elseif ($alias == 'stock') { - $this->load_stock(); - if ($this->stock_reel < $obj->seuil_stock_alerte) { - $datas[$alias] = $this->stock_reel.' '.img_warning($langs->trans("StockTooLow")); - } else { - $datas[$alias] = $this->stock_reel; - } - } elseif ($alias == 'label') { - $datas[$alias] = dol_trunc($obj->$alias, 40); - } elseif (preg_match('/price/i', $alias)) { - $datas[$alias] = price($obj->$alias); - } elseif ($alias == 'datem') { - $datas[$alias] = dol_print_date($this->db->jdate($obj->$alias), 'day'); - } elseif ($alias == 'status') { - $datas[$alias] = $this->LibStatut($obj->$alias, 5); - } else { - $datas[$alias] = $obj->$alias; - } - } - } - - array_push($this->list_datas, $datas); - - $i++; - } - $this->db->free($resql); - } else { - dol_print_error($this->db); - } - } } diff --git a/htdocs/product/canvas/service/actions_card_service.class.php b/htdocs/product/canvas/service/actions_card_service.class.php index b07c3d96a52..021de9b215e 100644 --- a/htdocs/product/canvas/service/actions_card_service.class.php +++ b/htdocs/product/canvas/service/actions_card_service.class.php @@ -37,7 +37,6 @@ class ActionsCardService // List of fiels for action=list public $field_list = array(); - public $list_datas = array(); public $id; public $ref; @@ -92,8 +91,6 @@ class ActionsCardService } $this->object = $tmpobject; - //parent::assign_values($action); - foreach ($this->object as $key => $value) { $this->tpl[$key] = $value; } @@ -213,10 +210,6 @@ class ActionsCardService $this->tpl['fiche_end'] = dol_get_fiche_end(); } - - if ($action == 'list') { - $this->LoadListDatas($limit, $offset, $sortfield, $sortorder); - } } @@ -267,97 +260,4 @@ class ActionsCardService dol_print_error($this->db, $sql); } } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Fetch datas list and save into ->list_datas - * - * @param int $limit Limit number of responses - * @param int $offset Offset for first response - * @param string $sortfield Sort field - * @param string $sortorder Sort order ('ASC' or 'DESC') - * @return void - */ - public function LoadListDatas($limit, $offset, $sortfield, $sortorder) - { - // phpcs:enable - global $conf; - global $search_categ, $sall, $sref, $search_barcode, $snom, $catid; - - $this->getFieldListCanvas(); - - $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type,'; - $sql .= ' p.fk_product_type, p.tms as datem,'; - $sql .= ' p.duration, p.tosell as statut, p.seuil_stock_alerte'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; - // 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"; - } - $fourn_id = 0; - if (GETPOST("fourn_id", 'int') > 0) { - $fourn_id = GETPOST("fourn_id", 'int'); - $sql .= ", ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; - } - $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 ($sall) { - $sql .= " AND (p.ref LIKE '%".$this->db->escape($sall)."%' OR p.label LIKE '%".$this->db->escape($sall)."%' OR p.description LIKE '%".$this->db->escape($sall)."%' OR p.note LIKE '%".$this->db->escape($sall)."%')"; - } - if ($sref) { - $sql .= " AND p.ref LIKE '%".$this->db->escape($sref)."%'"; - } - if ($search_barcode) { - $sql .= " AND p.barcode LIKE '%".$this->db->escape($search_barcode)."%'"; - } - if ($snom) { - $sql .= " AND p.label LIKE '%".$this->db->escape($snom)."%'"; - } - if (GETPOSTISSET("tosell")) { - $sql .= " AND p.tosell = ".((int) GETPOST("tosell", 'int')); - } - if (GETPOSTISSET("canvas")) { - $sql .= " AND p.canvas = '".$this->db->escape(GETPOST("canvas"))."'"; - } - if ($catid) { - $sql .= " AND cp.fk_categorie = ".((int) $catid); - } - if ($fourn_id > 0) { - $sql .= " AND p.rowid = pfp.fk_product AND pfp.fk_soc = ".((int) $fourn_id); - } - // Insert categ filter - if ($search_categ) { - $sql .= " AND cp.fk_categorie = ".((int) $search_categ); - } - $sql .= $this->db->order($sortfield, $sortorder); - $sql .= $this->db->plimit($limit + 1, $offset); - - $this->list_datas = array(); - - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - - $i = 0; - while ($i < min($num, $limit)) { - $datas = array(); - $obj = $this->db->fetch_object($resql); - - $datas["id"] = $obj->rowid; - $datas["ref"] = $obj->ref; - $datas["label"] = $obj->label; - $datas["barcode"] = $obj->barcode; - $datas["statut"] = $obj->statut; - - array_push($this->list_datas, $datas); - - $i++; - } - $this->db->free($resql); - } else { - print $sql; - } - } } diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 2bfe94f418a..a7b3c1958b5 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1250,7 +1250,6 @@ if (isModEnabled('barcode') && !empty($conf->global->BARCODE_PRODUCT_ADDON_NUM)) } } - if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // ----------------------------------------- // When used with CANVAS From 65e465fefbb3cbd919dd063fde8896470e560b16 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 14:59:20 +0100 Subject: [PATCH 189/816] Fix threshold --- qodana.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qodana.yaml b/qodana.yaml index 79ca8d5af59..d63f7b16999 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -1,6 +1,6 @@ version: "1.0" linter: jetbrains/qodana-php:2022.3-eap -failThreshold: 20000 +failThreshold: 0 profile: name: qodana.recommended exclude: From 10445b1e987c3beb437ea660c9b09fa5e3079521 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 14:59:32 +0100 Subject: [PATCH 190/816] Doc --- htdocs/core/class/canvas.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/canvas.class.php b/htdocs/core/class/canvas.class.php index 67443a7bdb8..a0f5a5f1fe4 100644 --- a/htdocs/core/class/canvas.class.php +++ b/htdocs/core/class/canvas.class.php @@ -157,7 +157,7 @@ class Canvas } /** - * Return the template to display canvas (if it exists) + * Return if a template exists to display as canvas (if it exists) * * @param string $action Action code * @return int 0=Canvas template file does not exist, 1=Canvas template file exists From 2130587613a51674f6be8a83ee3995a3a4af2bf8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 30 Dec 2022 15:14:01 +0100 Subject: [PATCH 191/816] Fix warnings --- htdocs/core/class/html.form.class.php | 2 +- htdocs/emailcollector/class/emailcollector.class.php | 5 +++-- htdocs/societe/class/companybankaccount.class.php | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index f3a566b6014..686d500875a 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4203,7 +4203,7 @@ class Form if ($deposit_percent >= 0) { $out .= ' '; $out .= ' '."\n"; diff --git a/htdocs/admin/system/database.php b/htdocs/admin/system/database.php index 8cd1ad3d597..fd983a10924 100644 --- a/htdocs/admin/system/database.php +++ b/htdocs/admin/system/database.php @@ -113,7 +113,8 @@ if (!count($listofvars) && !count($listofstatus)) { if ($key != $param) { continue; } - $val2 = ${$val['var']}; + $tmpvar = $val['var']; + $val2 = ${$tmpvar}; $text = 'Should be in line with value of param '.$val['var'].' thas is '.($val2 ? $val2 : "'' (=".$val['valifempty'].")").''; $show = 1; } diff --git a/htdocs/admin/webhook.php b/htdocs/admin/webhook.php index b589eac4079..6ba932c007b 100644 --- a/htdocs/admin/webhook.php +++ b/htdocs/admin/webhook.php @@ -293,14 +293,14 @@ if ($action == 'edit') { if ($val['type'] == 'textarea') { print '\n"; } elseif ($val['type']== 'html') { require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; - $doleditor = new DolEditor($constname, $conf->global->{$constname}, '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); + $doleditor = new DolEditor($constname, getDolGlobalString($constname), '', 160, 'dolibarr_notes', '', false, false, $conf->fckeditor->enabled, ROWS_5, '90%'); $doleditor->Create(); } elseif ($val['type'] == 'yesno') { - print $form->selectyesno($constname, $conf->global->{$constname}, 1); + print $form->selectyesno($constname, getDolGlobalString($constname), 1); } elseif (preg_match('/emailtemplate:/', $val['type'])) { include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; $formmail = new FormMail($db); @@ -382,9 +382,9 @@ if ($action == 'edit') { print ''; if ($val['type'] == 'textarea') { - print dol_nl2br($conf->global->{$constname}); + print dol_nl2br(getDolGlobalString($constname)); } elseif ($val['type']== 'html') { - print $conf->global->{$constname}; + print getDolGlobalString($constname); } elseif ($val['type'] == 'yesno') { print ajax_constantonoff($constname); } elseif (preg_match('/emailtemplate:/', $val['type'])) { @@ -393,14 +393,14 @@ if ($action == 'edit') { $tmp = explode(':', $val['type']); - $template = $formmail->getEMailTemplate($db, $tmp[1], $user, $langs, $conf->global->{$constname}); + $template = $formmail->getEMailTemplate($db, $tmp[1], $user, $langs, getDolGlobalString($constname)); if ($template<0) { setEventMessages(null, $formmail->errors, 'errors'); } print $langs->trans($template->label); } elseif (preg_match('/category:/', $val['type'])) { $c = new Categorie($db); - $result = $c->fetch($conf->global->{$constname}); + $result = $c->fetch(getDolGlobalString($constname)); if ($result < 0) { setEventMessages(null, $c->errors, 'errors'); } elseif ($result > 0 ) { @@ -412,25 +412,25 @@ if ($action == 'edit') { print '
    ' . implode(' ', $toprint) . '
'; } } elseif (preg_match('/thirdparty_type/', $val['type'])) { - if ($conf->global->{$constname}==2) { + if (getDolGlobalInt($constname)==2) { print $langs->trans("Prospect"); - } elseif ($conf->global->{$constname}==3) { + } elseif (getDolGlobalInt($constname)==3) { print $langs->trans("ProspectCustomer"); - } elseif ($conf->global->{$constname}==1) { + } elseif (getDolGlobalInt($constname)==1) { print $langs->trans("Customer"); - } elseif ($conf->global->{$constname}==0) { + } elseif (getDolGlobalInt($constname)==0) { print $langs->trans("NorProspectNorCustomer"); } } elseif ($val['type'] == 'product') { $product = new Product($db); - $resprod = $product->fetch($conf->global->{$constname}); + $resprod = $product->fetch(getDolGlobalInt($constname)); if ($resprod > 0) { print $product->ref; } elseif ($resprod < 0) { setEventMessages(null, $object->errors, "errors"); } } else { - print $conf->global->{$constname}; + print getDolGlobalString($constname); } print '
'; if ($val['type'] == 'textarea') { - print dol_nl2br($conf->global->{$constname}); + print dol_nl2br(getDolGlobalString($constname)); } elseif ($val['type']== 'html') { - print $conf->global->{$constname}; + print getDolGlobalString($constname); } elseif ($val['type'] == 'yesno') { print ajax_constantonoff($constname); } elseif (preg_match('/emailtemplate:/', $val['type'])) { @@ -598,14 +598,14 @@ if ($action == 'edit') { $tmp = explode(':', $val['type']); - $template = $formmail->getEMailTemplate($db, $tmp[1], $user, $langs, $conf->global->{$constname}); + $template = $formmail->getEMailTemplate($db, $tmp[1], $user, $langs, getDolGlobalString($constname)); if ($template<0) { setEventMessages(null, $formmail->errors, 'errors'); } print $langs->trans($template->label); } elseif (preg_match('/category:/', $val['type'])) { $c = new Categorie($db); - $result = $c->fetch($conf->global->{$constname}); + $result = $c->fetch(getDolGlobalInt($constname)); if ($result < 0) { setEventMessages(null, $c->errors, 'errors'); } elseif ($result > 0 ) { @@ -617,18 +617,18 @@ if ($action == 'edit') { print '
    ' . implode(' ', $toprint) . '
'; } } elseif (preg_match('/thirdparty_type/', $val['type'])) { - if ($conf->global->{$constname}==2) { + if (getDolGlobalInt($constname)==2) { print $langs->trans("Prospect"); - } elseif ($conf->global->{$constname}==3) { + } elseif (getDolGlobalInt($constname)==3) { print $langs->trans("ProspectCustomer"); - } elseif ($conf->global->{$constname}==1) { + } elseif (getDolGlobalInt($constname)==1) { print $langs->trans("Customer"); - } elseif ($conf->global->{$constname}==0) { + } elseif (getDolGlobalInt($constname)==0) { print $langs->trans("NorProspectNorCustomer"); } } elseif ($val['type'] == 'product') { $product = new Product($db); - $resprod = $product->fetch($conf->global->{$constname}); + $resprod = $product->fetch(getDolGlobalInt($constname)); if ($resprod > 0) { print $product->ref; } elseif ($resprod < 0) { @@ -638,11 +638,11 @@ if ($action == 'edit') { if (isModEnabled('accounting')) { require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php'; $accountingaccount = new AccountingAccount($db); - $accountingaccount->fetch('', $conf->global->{$constname}, 1); + $accountingaccount->fetch('', getDolGlobalString($constname), 1); print $accountingaccount->getNomUrl(0, 1, 1, '', 1); } else { - print $conf->global->{$constname}; + print getDolGlobalString($constname); } } else { print $conf->global->{$constname}; diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index f0399fa6350..d1329e40454 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1602,7 +1602,7 @@ if ($action == 'create') { $("#select_actioncommsendmodel_mail").closest("tr").show(); } else { $("#select_actioncommsendmodel_mail").closest("tr").hide(); - }; + } }); })'; print ''."\n"; @@ -2104,7 +2104,7 @@ if ($id > 0) { $("#select_actioncommsendmodel_mail").closest("tr").show(); } else { $("#select_actioncommsendmodel_mail").closest("tr").hide(); - }; + } }); })'; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 383cf7581e9..a644880282b 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1898,7 +1898,7 @@ if ($action == 'create' && $usercancreate) { if ($soc->fetch_optionals() > 0) { $object->array_options = array_merge($object->array_options, $soc->array_options); } - }; + } print $object->showOptionals($extrafields, 'create', $parameters); } diff --git a/htdocs/compta/bank/treso.php b/htdocs/compta/bank/treso.php index d3e573f21bf..e75402ba429 100644 --- a/htdocs/compta/bank/treso.php +++ b/htdocs/compta/bank/treso.php @@ -353,10 +353,10 @@ if (GETPOST("account") || GETPOST("ref")) { print "
".$refcomp."'.price(abs($total_ttc))."  '.price($total_ttc)."'.price($solde).'
'.$langs->trans("CashDeskIdWareHouse").'
  => '.$langs->trans("CurrentHour").''.dol_print_date(dol_now('gmt'), 'dayhour', 'tzserver').'
'; $contact = new Contact($db); - foreach ($histo[$key]['socpeopleassigned'] as $cid => $value) { + foreach ($histo[$key]['socpeopleassigned'] as $cid => $cvalue) { $result = $contact->fetch($cid); if ($result < 0) { diff --git a/htdocs/core/lib/cron.lib.php b/htdocs/core/lib/cron.lib.php index 7078d7488ad..ccce2ec7f94 100644 --- a/htdocs/core/lib/cron.lib.php +++ b/htdocs/core/lib/cron.lib.php @@ -128,7 +128,7 @@ function dol_print_cron_urls() $pathtoscript = $conf->global->MAIN_DOL_SCRIPTS_ROOT; } - $file = $pathtoscript.'/scripts/cron/cron_run_jobs.php '.(empty($conf->global->CRON_KEY) ? 'securitykey' : ''.$conf->global->CRON_KEY.'').' '.$logintouse.' [cronjobid]'; + $file = $pathtoscript.'/scripts/cron/cron_run_jobs.php '.(empty($conf->global->CRON_KEY) ? 'securitykey' : ''.$conf->global->CRON_KEY).' '.$logintouse.' [cronjobid]'; print '
\n"; print '
'; @@ -145,7 +145,7 @@ function dol_print_cron_urls() if ($linuxlike) { print $langs->trans("CronExplainHowToRunUnix"); print '
'; - print '
'; + print '
'; } else { print $langs->trans("CronExplainHowToRunWin"); } diff --git a/htdocs/eventorganization/conferenceorbooth_card.php b/htdocs/eventorganization/conferenceorbooth_card.php index b6932c2cf09..9928b8af33b 100644 --- a/htdocs/eventorganization/conferenceorbooth_card.php +++ b/htdocs/eventorganization/conferenceorbooth_card.php @@ -568,13 +568,13 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.$withProjectUrl.'&action=presend&token='.newToken().'&mode=init#formmailbeforetitle'); } - print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.$withProjectUrl.'&action=edit&token='.newToken().'', '', $permissiontoadd); + print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.$withProjectUrl.'&action=edit&token='.newToken(), '', $permissiontoadd); // Clone print dolGetButtonAction('', $langs->trans('ToClone'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.$withProjectUrl.'&socid='.$object->socid.'&action=clone&token='.newToken().'&object=scrumsprint', '', $permissiontoadd); // Delete (need delete permission, or if draft, just need create/modify permission) - print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER['PHP_SELF'].'?id='.$object->id.$withProjectUrl.'&action=delete&token='.newToken().'', '', $permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)); + print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER['PHP_SELF'].'?id='.$object->id.$withProjectUrl.'&action=delete&token='.newToken(), '', $permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)); } print ''."\n"; } diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 0125becd21c..81da058b919 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -1470,7 +1470,7 @@ class Holiday extends CommonObject $sql .= " value = '".$this->db->escape($value)."'"; $sql .= " WHERE name = '".$this->db->escape($name)."'"; - dol_syslog(get_class($this).'::updateConfCP name='.$name.'', LOG_DEBUG); + dol_syslog(get_class($this).'::updateConfCP name='.$name, LOG_DEBUG); $result = $this->db->query($sql); if ($result) { return true; diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index a14467c0184..b804f3d9c8f 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -281,7 +281,7 @@ if ($dirins && $action == 'initmodule' && $modulename) { // Delete dir and files that can be generated in sub tabs later if we need them (we want a minimal module first) dol_delete_dir_recursive($destdir.'/build/doxygen'); dol_delete_dir_recursive($destdir.'/core/modules/mailings'); - dol_delete_dir_recursive($destdir.'/core/modules/'.strtolower($modulename).''); + dol_delete_dir_recursive($destdir.'/core/modules/'.strtolower($modulename)); dol_delete_dir_recursive($destdir.'/core/tpl'); dol_delete_dir_recursive($destdir.'/core/triggers'); dol_delete_dir_recursive($destdir.'/doc'); diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index ac5d612394b..43760d808b2 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -834,7 +834,7 @@ class MouvementStock extends CommonObject $sql .= " WHERE fk_product = ".((int) $productidselected); $sql .= " AND datem < '".$this->db->idate($datebefore)."'"; - dol_syslog(get_class($this).__METHOD__.'', LOG_DEBUG); + dol_syslog(get_class($this).__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $obj = $this->db->fetch_object($resql); diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index ffe59b01d61..1f9ad46cdb0 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -279,9 +279,9 @@ class Stripe extends CommonObject global $stripearrayofkeysbyenv; \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); if (empty($key)) { // If the Stripe connect account not set, we use common API usage - $stripepaymentmethod = \Stripe\PaymentMethod::retrieve(''.$paymentmethod->id.''); + $stripepaymentmethod = \Stripe\PaymentMethod::retrieve((string) $paymentmethod->id); } else { - $stripepaymentmethod = \Stripe\PaymentMethod::retrieve(''.$paymentmethod->id.'', array("stripe_account" => $key)); + $stripepaymentmethod = \Stripe\PaymentMethod::retrieve((string) $paymentmethod->id, array("stripe_account" => $key)); } } catch (Exception $e) { $this->error = $e->getMessage(); @@ -307,9 +307,9 @@ class Stripe extends CommonObject global $stripearrayofkeysbyenv; \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); if (empty($key)) { // If the Stripe connect account not set, we use common API usage - $selectedreader = \Stripe\Terminal\Reader::retrieve(''.$reader.''); + $selectedreader = \Stripe\Terminal\Reader::retrieve((string) $reader); } else { - $stripepaymentmethod = \Stripe\Terminal\Reader::retrieve(''.$reader.'', array("stripe_account" => $key)); + $stripepaymentmethod = \Stripe\Terminal\Reader::retrieve((string) $reader, array("stripe_account" => $key)); } } catch (Exception $e) { $this->error = $e->getMessage(); diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index ea262a1562f..27b340249c3 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -1424,7 +1424,7 @@ if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) { $htmlforlines .= '" onclick="AddProduct(\''.$place.'\', '.$row->id.')">'; if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) { $htmlforlines .= '
'; - $htmlforlines .= $row->label.''.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency); + $htmlforlines .= $row->label.' '.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency); $htmlforlines .= ''."\n"; } else { $htmlforlines .= '
'; diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index 4c4dce5a428..79db9e0e73e 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -836,15 +836,15 @@ foreach ($object->fields as $key => $val) { print ''; - $formTicket->selectTypesTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key.'', '', 2, 1, 1, 0, (!empty($val['css']) ? $val['css'] : 'maxwidth150'), 1); + $formTicket->selectTypesTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key, '', 2, 1, 1, 0, (!empty($val['css']) ? $val['css'] : 'maxwidth150'), 1); print ''; - $formTicket->selectGroupTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key.'', '', 2, 1, 1, 0, (!empty($val['css']) ? $val['css'] : 'maxwidth150')); + $formTicket->selectGroupTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key, '', 2, 1, 1, 0, (!empty($val['css']) ? $val['css'] : 'maxwidth150')); print ''; - $formTicket->selectSeveritiesTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key.'', '', 2, 1, 1, 0, (!empty($val['css']) ? $val['css'] : 'maxwidth150')); + $formTicket->selectSeveritiesTickets(dol_escape_htmltag(empty($search[$key]) ? '' : $search[$key]), 'search_'.$key, '', 2, 1, 1, 0, (!empty($val['css']) ? $val['css'] : 'maxwidth150')); print ''; diff --git a/htdocs/webservices/server_order.php b/htdocs/webservices/server_order.php index 65357174019..0f0eb79d10e 100644 --- a/htdocs/webservices/server_order.php +++ b/htdocs/webservices/server_order.php @@ -741,9 +741,9 @@ function createOrder($authentication, $order) $extrafields = new ExtraFields($db); $extrafields->fetch_name_optionals_label($elementtype, true); if (isset($extrafields->attributes[$elementtype]['label']) && is_array($extrafields->attributes[$elementtype]['label']) && count($extrafields->attributes[$elementtype]['label'])) { - foreach ($extrafields->attributes[$elementtype]['label'] as $key => $label) { - $key = 'options_'.$key; - $newline->array_options[$key] = $line[$key]; + foreach ($extrafields->attributes[$elementtype]['label'] as $tmpkey => $tmplabel) { + $tmpkey = 'options_'.$tmpkey; + $newline->array_options[$tmpkey] = $line[$tmpkey]; } } diff --git a/qodana.yaml b/qodana.yaml index 5ed80e029f3..853ee69fab5 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -64,4 +64,6 @@ exclude: - name: PhpArrayWriteIsNotUsedInspection - name: PhpUndefinedNamespaceInspection - name: PhpArraySearchInBooleanContextInspection - - name: PhpPropertyOnlyWrittenInspection \ No newline at end of file + - name: PhpLoopCanBeReplacedWithStrRepeatInspection + - name: PhpPropertyOnlyWrittenInspection + - name: PhpCoveredCharacterInClassInspection \ No newline at end of file diff --git a/scripts/user/sync_groups_ldap2dolibarr.php b/scripts/user/sync_groups_ldap2dolibarr.php index 67c14a4ee5d..2fe89b92ccb 100755 --- a/scripts/user/sync_groups_ldap2dolibarr.php +++ b/scripts/user/sync_groups_ldap2dolibarr.php @@ -176,17 +176,17 @@ if ($result >= 0) { // 1 - Association des utilisateurs du groupe LDAP au groupe Dolibarr $userList = array(); $userIdList = array(); - foreach ($ldapgroup[$conf->global->LDAP_GROUP_FIELD_GROUPMEMBERS] as $key => $userdn) { - if ($key === 'count') { + foreach ($ldapgroup[getDolGlobalString('LDAP_GROUP_FIELD_GROUPMEMBERS')] as $tmpkey => $userdn) { + if ($tmpkey === 'count') { continue; } if (empty($userList[$userdn])) { // Récupération de l'utilisateur // Schéma rfc2307: les membres sont listés dans l'attribut memberUid sous form de login uniquement - if ($conf->global->LDAP_GROUP_FIELD_GROUPMEMBERS === 'memberUid') { + if (getDolGlobalString('LDAP_GROUP_FIELD_GROUPMEMBERS') === 'memberUid') { $userKey = array($userdn); } else { // Pour les autres schémas, les membres sont listés sous forme de DN complets $userFilter = explode(',', $userdn); - $userKey = $ldap->getAttributeValues('('.$userFilter[0].')', $conf->global->LDAP_KEY_USERS); + $userKey = $ldap->getAttributeValues('('.$userFilter[0].')', getDolGlobalString('LDAP_KEY_USERS')); } if (!is_array($userKey)) { continue; @@ -194,9 +194,9 @@ if ($result >= 0) { $fuser = new User($db); - if ($conf->global->LDAP_KEY_USERS == $conf->global->LDAP_FIELD_SID) { + if (getDolGlobalString('LDAP_KEY_USERS') == getDolGlobalString('LDAP_FIELD_SID')) { $fuser->fetch('', '', $userKey[0]); // Chargement du user concerné par le SID - } elseif ($conf->global->LDAP_KEY_USERS == $conf->global->LDAP_FIELD_LOGIN) { + } elseif (getDolGlobalString('LDAP_KEY_USERS') == getDolGlobalString('LDAP_FIELD_LOGIN')) { $fuser->fetch('', $userKey[0]); // Chargement du user concerné par le login } From cef9a8e8d48e525ab63e561ceace90ca24b2ab7d Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Sat, 31 Dec 2022 13:36:31 +0100 Subject: [PATCH 212/816] Fix Price by qty for multiprices --- htdocs/core/lib/ajax.lib.php | 2 +- htdocs/core/tpl/objectline_create.tpl.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index a6d269a6bb2..63d4605b8fb 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -187,7 +187,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen $("#'.$htmlnamejquery.'").attr("data-ref-customer", ui.item.ref_customer); $("#'.$htmlnamejquery.'").attr("data-tvatx", ui.item.tva_tx); '; - if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) { + if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) { $script .= ' // For customer price when PRODUIT_CUSTOMER_PRICES_BY_QTY is on $("#'.$htmlnamejquery.'").attr("data-pbq", ui.item.pbq); diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 5ce4ab76448..f4e83192ac4 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -911,7 +911,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) { ?> global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) {?> + if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) {?> /* To process customer price per quantity (PRODUIT_CUSTOMER_PRICES_BY_QTY works only if combo product is not an ajax after x key pressed) */ var pbq = parseInt($('option:selected', this).attr('data-pbq')); // When select is done from HTML select if (isNaN(pbq)) { pbq = jQuery('#idprod').attr('data-pbq'); } // When select is done from HTML input with autocomplete From 8774f4f092021d4cd548bec6cc683e9dad199dc8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 13:44:11 +0100 Subject: [PATCH 213/816] Fix warning qodana --- htdocs/core/lib/functions.lib.php | 14 +++++++------- htdocs/core/lib/project.lib.php | 6 ++++-- .../asset/doc/doc_generic_asset_odt.modules.php | 2 +- .../bom/doc/doc_generic_bom_odt.modules.php | 2 +- .../commande/doc/doc_generic_order_odt.modules.php | 2 +- .../doc/doc_generic_contract_odt.modules.php | 2 +- .../doc/doc_generic_shipment_odt.modules.php | 2 +- .../doc/doc_generic_invoice_odt.modules.php | 2 +- .../member/doc/doc_generic_member_odt.class.php | 2 +- .../modules/mrp/doc/doc_generic_mo_odt.modules.php | 2 +- .../doc/doc_generic_product_odt.modules.php | 2 +- .../doc/doc_generic_project_odt.modules.php | 2 +- .../doc/doc_generic_proposal_odt.modules.php | 2 +- .../doc/doc_generic_reception_odt.modules.php | 2 +- .../stock/doc/doc_generic_stock_odt.modules.php | 2 +- .../doc_generic_supplier_invoice_odt.modules.php | 2 +- .../doc/doc_generic_supplier_order_odt.modules.php | 2 +- .../doc_generic_supplier_proposal_odt.modules.php | 2 +- .../ticket/doc/doc_generic_ticket_odt.modules.php | 2 +- .../user/doc/doc_generic_user_odt.modules.php | 2 +- .../doc/doc_generic_usergroup_odt.modules.php | 2 +- .../doc/doc_generic_myobject_odt.modules.php | 2 +- ..._generic_recruitmentjobposition_odt.modules.php | 2 +- qodana.yaml | 6 +++++- test/phpunit/FunctionsLibTest.php | 7 +++++++ 25 files changed, 44 insertions(+), 31 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index de329ee515f..6241eaaa8b1 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -368,7 +368,7 @@ function getBrowserInfo($user_agent) // MS products at end $name = 'ie'; $version = end($reg); - } elseif (preg_match('/l(i|y)n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) { + } elseif (preg_match('/l[iy]n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) { // MS products at end $name = 'lynxlinks'; $version = $reg[4]; @@ -3804,7 +3804,7 @@ function isValidMXRecord($domain) } } - // function idn_to_ascii or checkdnsrr does not exists + // function idn_to_ascii or checkdnsrr or getmxrr does not exists return -1; } @@ -10208,12 +10208,12 @@ function dol_mimetype($file, $default = 'application/octet-stream', $mode = 0) $imgmime = 'mdb.png'; $famime = 'file-o'; } - if (preg_match('/\.doc(x|m)?$/i', $tmpfile)) { + if (preg_match('/\.doc[xm]?$/i', $tmpfile)) { $mime = 'application/msword'; $imgmime = 'doc.png'; $famime = 'file-word-o'; } - if (preg_match('/\.dot(x|m)?$/i', $tmpfile)) { + if (preg_match('/\.dot[xm]?$/i', $tmpfile)) { $mime = 'application/msword'; $imgmime = 'doc.png'; $famime = 'file-word-o'; @@ -10233,17 +10233,17 @@ function dol_mimetype($file, $default = 'application/octet-stream', $mode = 0) $imgmime = 'xls.png'; $famime = 'file-excel-o'; } - if (preg_match('/\.xls(b|m|x)$/i', $tmpfile)) { + if (preg_match('/\.xls[bmx]$/i', $tmpfile)) { $mime = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; $imgmime = 'xls.png'; $famime = 'file-excel-o'; } - if (preg_match('/\.pps(m|x)?$/i', $tmpfile)) { + if (preg_match('/\.pps[mx]?$/i', $tmpfile)) { $mime = 'application/vnd.ms-powerpoint'; $imgmime = 'ppt.png'; $famime = 'file-powerpoint-o'; } - if (preg_match('/\.ppt(m|x)?$/i', $tmpfile)) { + if (preg_match('/\.ppt[mx]?$/i', $tmpfile)) { $mime = 'application/x-mspowerpoint'; $imgmime = 'ppt.png'; $famime = 'file-powerpoint-o'; diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 7fdb3aecda1..a59ebe658b0 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -1624,8 +1624,10 @@ function projectLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsr // Duration print ''; - $dayWorkLoad = !empty($projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id]) ? $projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id] : 0; - if (!isset($totalforeachday[$preselectedday])) $totalforeachday[$preselectedday] = 0; + $dayWorkLoad = empty($projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id]) ? 0 : $projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id]; + if (!isset($totalforeachday[$preselectedday])) { + $totalforeachday[$preselectedday] = 0; + } $totalforeachday[$preselectedday] += $dayWorkLoad; $alreadyspent = ''; diff --git a/htdocs/core/modules/asset/doc/doc_generic_asset_odt.modules.php b/htdocs/core/modules/asset/doc/doc_generic_asset_odt.modules.php index 8be86dda944..ba4f39919bf 100644 --- a/htdocs/core/modules/asset/doc/doc_generic_asset_odt.modules.php +++ b/htdocs/core/modules/asset/doc/doc_generic_asset_odt.modules.php @@ -262,7 +262,7 @@ class doc_generic_asset_odt extends ModelePDFAsset if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref.'_'.$newfiletmp; diff --git a/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php b/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php index bec28b941aa..ea877432c17 100644 --- a/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php +++ b/htdocs/core/modules/bom/doc/doc_generic_bom_odt.modules.php @@ -273,7 +273,7 @@ class doc_generic_bom_odt extends ModelePDFBom if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref . '_' . $newfiletmp; diff --git a/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php b/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php index 5e94397bc91..bbace838183 100644 --- a/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php +++ b/htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php @@ -279,7 +279,7 @@ class doc_generic_order_odt extends ModelePDFCommandes if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref . '_' . $newfiletmp; diff --git a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php index dad1ebc9122..83e8f2551f7 100644 --- a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php +++ b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php @@ -276,7 +276,7 @@ class doc_generic_contract_odt extends ModelePDFContract if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php b/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php index 73793c5a757..f8280aab301 100644 --- a/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php +++ b/htdocs/core/modules/expedition/doc/doc_generic_shipment_odt.modules.php @@ -277,7 +277,7 @@ class doc_generic_shipment_odt extends ModelePdfExpedition if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref . '_' . $newfiletmp; diff --git a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php index 0b8fa2d4621..f5dcfb86936 100644 --- a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php +++ b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php @@ -276,7 +276,7 @@ class doc_generic_invoice_odt extends ModelePDFFactures if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php b/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php index ed48c93c4de..2d125d2743a 100644 --- a/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php +++ b/htdocs/core/modules/member/doc/doc_generic_member_odt.class.php @@ -266,7 +266,7 @@ class doc_generic_member_odt extends ModelePDFMember if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php b/htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php index b89c4eab2cd..90d1f2f8d6b 100644 --- a/htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php +++ b/htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php @@ -266,7 +266,7 @@ class doc_generic_mo_odt extends ModelePDFMo if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref . '_' . $newfiletmp; diff --git a/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php b/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php index d5321b92ceb..6fde0ce16c4 100644 --- a/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php +++ b/htdocs/core/modules/product/doc/doc_generic_product_odt.modules.php @@ -274,7 +274,7 @@ class doc_generic_product_odt extends ModelePDFProduct if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php index 2015da21f61..f08a93b4339 100644 --- a/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php +++ b/htdocs/core/modules/project/doc/doc_generic_project_odt.modules.php @@ -557,7 +557,7 @@ class doc_generic_project_odt extends ModelePDFProjects if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref . '_' . $newfiletmp; diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index 6715b2e39a5..de6554137df 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -307,7 +307,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php b/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php index 4ebc742b4bb..84d95a5036c 100644 --- a/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php +++ b/htdocs/core/modules/reception/doc/doc_generic_reception_odt.modules.php @@ -270,7 +270,7 @@ class doc_generic_reception_odt extends ModelePdfReception if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref . '_' . $newfiletmp; diff --git a/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php b/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php index eb6ba838d7a..358369d1f43 100644 --- a/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php +++ b/htdocs/core/modules/stock/doc/doc_generic_stock_odt.modules.php @@ -277,7 +277,7 @@ class doc_generic_stock_odt extends ModelePDFStock if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/supplier_invoice/doc/doc_generic_supplier_invoice_odt.modules.php b/htdocs/core/modules/supplier_invoice/doc/doc_generic_supplier_invoice_odt.modules.php index 8d1f9713c00..c9e18e7c4ab 100644 --- a/htdocs/core/modules/supplier_invoice/doc/doc_generic_supplier_invoice_odt.modules.php +++ b/htdocs/core/modules/supplier_invoice/doc/doc_generic_supplier_invoice_odt.modules.php @@ -266,7 +266,7 @@ class doc_generic_supplier_invoice_odt extends ModelePDFSuppliersInvoices if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref.'_'.$newfiletmp; diff --git a/htdocs/core/modules/supplier_order/doc/doc_generic_supplier_order_odt.modules.php b/htdocs/core/modules/supplier_order/doc/doc_generic_supplier_order_odt.modules.php index 12bbcc12edc..ca7d1b3d61b 100644 --- a/htdocs/core/modules/supplier_order/doc/doc_generic_supplier_order_odt.modules.php +++ b/htdocs/core/modules/supplier_order/doc/doc_generic_supplier_order_odt.modules.php @@ -261,7 +261,7 @@ class doc_generic_supplier_order_odt extends ModelePDFSuppliersOrders if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref . '_' . $newfiletmp; diff --git a/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php b/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php index 55a7710c5a4..8fca5110896 100644 --- a/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php +++ b/htdocs/core/modules/supplier_proposal/doc/doc_generic_supplier_proposal_odt.modules.php @@ -295,7 +295,7 @@ class doc_generic_supplier_proposal_odt extends ModelePDFSupplierProposal if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php b/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php index 1a2d1e537cc..3ae972fef49 100644 --- a/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php +++ b/htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php @@ -264,7 +264,7 @@ class doc_generic_ticket_odt extends ModelePDFTicket if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php b/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php index 1c3e346203b..00edf04fac0 100644 --- a/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php +++ b/htdocs/core/modules/user/doc/doc_generic_user_odt.modules.php @@ -295,7 +295,7 @@ class doc_generic_user_odt extends ModelePDFUser if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php b/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php index 4bbb39c0086..a5447260a2f 100644 --- a/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php +++ b/htdocs/core/modules/usergroup/doc/doc_generic_usergroup_odt.modules.php @@ -277,7 +277,7 @@ class doc_generic_usergroup_odt extends ModelePDFUserGroup if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/modulebuilder/template/core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php b/htdocs/modulebuilder/template/core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php index b7dfc374a52..f89360e8774 100644 --- a/htdocs/modulebuilder/template/core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php +++ b/htdocs/modulebuilder/template/core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php @@ -278,7 +278,7 @@ class doc_generic_myobject_odt extends ModelePDFMyObject if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); diff --git a/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php b/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php index cfbf91463e8..147e8ec3519 100644 --- a/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php +++ b/htdocs/recruitment/core/modules/recruitment/doc/doc_generic_recruitmentjobposition_odt.modules.php @@ -264,7 +264,7 @@ class doc_generic_recruitmentjobposition_odt extends ModelePDFRecruitmentJobPosi if (file_exists($dir)) { //print "srctemplatepath=".$srctemplatepath; // Src filename $newfile = basename($srctemplatepath); - $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile); $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); $newfiletmp = $objectref.'_'.$newfiletmp; diff --git a/qodana.yaml b/qodana.yaml index 853ee69fab5..53cf1a04586 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -66,4 +66,8 @@ exclude: - name: PhpArraySearchInBooleanContextInspection - name: PhpLoopCanBeReplacedWithStrRepeatInspection - name: PhpPropertyOnlyWrittenInspection - - name: PhpCoveredCharacterInClassInspection \ No newline at end of file + - name: PhpCoveredCharacterInClassInspection + - name: PhpSameParameterValueInspection + - name: PhpConditionCheckedByNextConditionInspection + - name: PhpSuspiciousNameCombinationInspection + \ No newline at end of file diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 12c8683bb8f..ef5507d8601 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -442,6 +442,13 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase $this->assertEquals('ios', $tmp['browseros']); $this->assertEquals('tablet', $tmp['layout']); $this->assertEquals('iphone', $tmp['phone']); + + //iPad + $user_agent = 'Lynx/2.8.8dev.3 libwww‑FM/2.14 SSL‑MM/1.4.1'; + $tmp=getBrowserInfo($user_agent); + $this->assertEquals('lynxlinks', $tmp['browsername']); + $this->assertEquals('unknown', $tmp['browseros']); + $this->assertEquals('classic', $tmp['layout']); } From 3ca8e8c4935251250c39e01ff4d7b50d103753ed Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 13:47:09 +0100 Subject: [PATCH 214/816] Fix warning --- htdocs/comm/propal/card.php | 2 +- htdocs/commande/card.php | 3 ++- qodana.yaml | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index a21e227d822..a3896f7de3c 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1830,7 +1830,7 @@ if ($action == 'create') { } print '
'.$langs->trans('SendingMethod').''; print img_picto('', 'object_dollyrevert', 'class="pictofixedwidth"'); - print $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx'); + $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx'); print '
'.$langs->trans('SendingMethod').''; - print img_picto('', 'object_dolly', 'class="pictofixedwidth"').$form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx'); + print img_picto('', 'object_dolly', 'class="pictofixedwidth"'); + $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx'); print '
'; print $form->textwithpicto('', $htmltooltip, 1, 0); - if ($conf->global->CHEQUERECEIPTS_ADDON.'.php' == $file) { // If module is the one used, we show existing errors + if (getDolGlobalString('CHEQUERECEIPTS_ADDON').'.php' == $file) { // If module is the one used, we show existing errors if (!empty($module->error)) { dol_htmloutput_mesg($module->error, '', 'error', 1); } diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 64d01817c85..cc43d0fb818 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -1800,8 +1800,8 @@ class ActionComm extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { @@ -1835,7 +1835,7 @@ class ActionComm extends CommonObject $c->add_type($this, Categorie::TYPE_ACTIONCOMM); } } - return; + return 1; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 07729fd55de..e4cd4f9491f 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1830,7 +1830,7 @@ if ($action == 'create') { } print '
'.$langs->trans('SendingMethod').''; print img_picto('', 'object_dollyrevert', 'class="pictofixedwidth"'); - print $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx'); + $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx'); print '
'.$langs->trans('SendingMethod').''; - print img_picto('', 'object_dolly', 'class="pictofixedwidth"').$form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx'); + print img_picto('', 'object_dolly', 'class="pictofixedwidth"'); + $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1, '', 0, 'maxwidth200 widthcentpercentminusx'); print '
'; + print '
'; - // Linked documents - if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) { - print ''; - print '\n"; - print ''; - } - if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { - print ''; - print '\n"; - print ''; - } - - // Date creation - print ''; - print '\n"; - print ''; - - // Delivery date planned - print ''; - print ''; - - // Weight + // Linked documents + if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) { print ''; - - // Width - print ''; - - // Height - print ''; - - // Depth - print ''; - - // Volume - print ''; + print $langs->trans("RefOrder").''; print '\n"; print ''; - - // Other attributes - $cols = 2; - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; - - print '
'; - print $langs->trans("RefOrder").''; - print $objectsrc->getNomUrl(1, 'commande'); - print "
'; - print $langs->trans("RefProposal").''; - print $objectsrc->getNomUrl(1, 'expedition'); - print "
'.$langs->trans("DateCreation").''.dol_print_date($object->date_creation, "dayhour")."
'; - print ''; - - if ($action != 'editdate_livraison') { - print ''; - } - print '
'; - print $langs->trans('DateDeliveryPlanned'); - print 'id.'">'.img_edit($langs->trans('SetDeliveryDate'), 1).'
'; - print '
'; - if ($action == 'editdate_livraison') { - print ''; - print ''; - print ''; - print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0); - print ''; - print ''; - } else { - print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : ' '; - } - print '
'; - print $form->editfieldkey("Weight", 'trueWeight', $object->trueWeight, $object, $user->rights->expedition->creer); - print ''; - - if ($action == 'edittrueWeight') { - print '
'; - print ''; - print ''; - print ''; - print ''; - print $formproduct->selectMeasuringUnits("weight_units", "weight", $object->weight_units, 0, 2); - print ' '; - print ' '; - print '
'; - } else { - print $object->trueWeight; - print ($object->trueWeight && $object->weight_units != '') ? ' '.measuringUnitString(0, "weight", $object->weight_units) : ''; - } - - // Calculated - if ($totalWeight > 0) { - if (!empty($object->trueWeight)) { - print ' ('.$langs->trans("SumOfProductWeights").': '; - } - print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND) ? $conf->global->MAIN_WEIGHT_DEFAULT_ROUND : -1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT) ? $conf->global->MAIN_WEIGHT_DEFAULT_UNIT : 'no'); - if (!empty($object->trueWeight)) { - print ')'; - } - } - print '
'.$form->editfieldkey("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->expedition->creer).''; - print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->expedition->creer); - print ($object->trueWidth && $object->width_units != '') ? ' '.measuringUnitString(0, "size", $object->width_units) : ''; - print '
'.$form->editfieldkey("Height", 'trueHeight', $object->trueHeight, $object, $user->rights->expedition->creer).''; - if ($action == 'edittrueHeight') { - print '
'; - print ''; - print ''; - print ''; - print ''; - print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2); - print ' '; - print ' '; - print '
'; - } else { - print $object->trueHeight; - print ($object->trueHeight && $object->height_units != '') ? ' '.measuringUnitString(0, "size", $object->height_units) : ''; - } - - print '
'.$form->editfieldkey("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->expedition->creer).''; - print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->expedition->creer); - print ($object->trueDepth && $object->depth_units != '') ? ' '.measuringUnitString(0, "size", $object->depth_units) : ''; - print '
'; - print $langs->trans("Volume"); - print ''; - $calculatedVolume = 0; - $volumeUnit = 0; - if ($object->trueWidth && $object->trueHeight && $object->trueDepth) { - $calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth); - $volumeUnit = $object->size_units * 3; - } - // If sending volume not defined we use sum of products - if ($calculatedVolume > 0) { - if ($volumeUnit < 50) { - print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no'); - } else { - print $calculatedVolume.' '.measuringUnitString(0, "volume", $volumeUnit); - } - } - if ($totalVolume > 0) { - if ($calculatedVolume) { - print ' ('.$langs->trans("SumOfProductVolumes").': '; - } - print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no'); - //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')'; - if ($calculatedVolume) { - print ')'; - } - } + print $objectsrc->getNomUrl(1, 'commande'); print "
'; - - print '
'; - print '
'; - print '
'; - - print ''; - - // Sending method - print ''; + } + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { + print ''; + print '\n"; print ''; + } - // Tracking Number - print ''; + // Date creation + print ''; + print '\n"; + print ''; - // Incoterms - if (isModEnabled('incoterm')) { - print ''; - print ''; + // Delivery date planned + print ''; + print ''; + + // Weight + print '
'; - print ''; - - if ($action != 'editshipping_method_id') { - print ''; - } - print '
'; - print $langs->trans('SendingMethod'); - print 'id.'">'.img_edit($langs->trans('SetSendingMethod'), 1).'
'; - print '
'; - if ($action == 'editshipping_method_id') { - print '
'; - print ''; - print ''; - $object->fetch_delivery_methods(); - print $form->selectarray("shipping_method_id", $object->meths, $object->shipping_method_id, 1, 0, 0, "", 1); - if ($user->admin) { - print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); - } - print ''; - print '
'; - } else { - if ($object->shipping_method_id > 0) { - // Get code using getLabelFromKey - $code = $langs->getLabelFromKey($db, $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code'); - print $langs->trans("SendingMethod".strtoupper($code)); - } - } - print '
'; + print $langs->trans("RefProposal").''; + print $objectsrc->getNomUrl(1, 'expedition'); + print "
'.$form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->rights->expedition->creer).''; - print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->rights->expedition->creer, 'safehtmlstring', $object->tracking_number); - print '
'.$langs->trans("DateCreation").''.dol_print_date($object->date_creation, "dayhour")."
'; - print '
'; - print $langs->trans('IncotermLabel'); - print ''; - if ($user->rights->expedition->creer) { - print ''.img_edit().''; - } else { - print ' '; - } - print '
'; - print '
'; - if ($action != 'editincoterm') { - print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1); - } else { - print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id); - } - print '
'; + print ''; + + if ($action != 'editdate_livraison') { + print ''; + } + print '
'; + print $langs->trans('DateDeliveryPlanned'); + print 'id.'">'.img_edit($langs->trans('SetDeliveryDate'), 1).'
'; + print '
'; + if ($action == 'editdate_livraison') { + print '
'; + print ''; + print ''; + print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0); + print ''; + print '
'; + } else { + print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : ' '; + } + print '
'; + print $form->editfieldkey("Weight", 'trueWeight', $object->trueWeight, $object, $user->rights->expedition->creer); + print ''; + + if ($action == 'edittrueWeight') { + print '
'; + print ''; + print ''; + print ''; + print ''; + print $formproduct->selectMeasuringUnits("weight_units", "weight", $object->weight_units, 0, 2); + print ' '; + print ' '; + print '
'; + } else { + print $object->trueWeight; + print ($object->trueWeight && $object->weight_units != '') ? ' '.measuringUnitString(0, "weight", $object->weight_units) : ''; + } + + // Calculated + if ($totalWeight > 0) { + if (!empty($object->trueWeight)) { + print ' ('.$langs->trans("SumOfProductWeights").': '; } - - // Other attributes - $parameters = array('colspan' => ' colspan="3"', 'cols' => '3'); - $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - - print "
"; - - print '
'; - print ''; - - print '
'; - - - // Lines of products - - if ($action == 'editline') { - print '
- - - - - '; + print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND) ? $conf->global->MAIN_WEIGHT_DEFAULT_ROUND : -1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT) ? $conf->global->MAIN_WEIGHT_DEFAULT_UNIT : 'no'); + if (!empty($object->trueWeight)) { + print ')'; } - print '
'; + } + print '
'; - print ''; - print ''; - // Adds a line numbering column - if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { - print ''; - } - // Product/Service - print ''; - // Qty - print ''; - if ($origin && $origin_id > 0) { - print ''; - } - if ($action == 'editline') { - $editColspan = 3; - if (!isModEnabled('stock')) { - $editColspan--; - } - if (empty($conf->productbatch->enabled)) { - $editColspan--; - } - print ''; + // Width + print ''; + + // Height + print ''; + + // Depth + print ''; + + // Volume + print ''; + print ''; - } else { - print ''; - } - if (isModEnabled('stock')) { - print ''; - } - - if (isModEnabled('productbatch')) { - print ''; - } + print $calculatedVolume.' '.measuringUnitString(0, "volume", $volumeUnit); } - print ''; - print ''; - //print ''; - if ($object->statut == 0) { - print ''; - print ''; + } + if ($totalVolume > 0) { + if ($calculatedVolume) { + print ' ('.$langs->trans("SumOfProductVolumes").': '; } - print "\n"; - print ''; + print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no'); + //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')'; + if ($calculatedVolume) { + print ')'; + } + } + print "\n"; + print ''; - $outputlangs = $langs; + // Other attributes + $cols = 2; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; - if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { - $object->fetch_thirdparty(); - $newlang = ''; - if (empty($newlang) && GETPOST('lang_id', 'aZ09')) { - $newlang = GETPOST('lang_id', 'aZ09'); - } - if (empty($newlang)) { - $newlang = $object->thirdparty->default_lang; - } - if (!empty($newlang)) { - $outputlangs = new Translate("", $conf); - $outputlangs->setDefaultLang($newlang); - } + print '
 '.$langs->trans("Products").''.$langs->trans("QtyOrdered").''.$langs->trans("QtyInOtherShipments").''; - if ($object->statut <= 1) { - print $langs->trans("QtyToShip").' - '; - } else { - print $langs->trans("QtyShipped").' - '; - } - if (isModEnabled('stock')) { - print $langs->trans("WarehouseSource").' - '; - } - if (isModEnabled('productbatch')) { - print $langs->trans("Batch"); - } - print '
'.$form->editfieldkey("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->expedition->creer).''; + print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->expedition->creer); + print ($object->trueWidth && $object->width_units != '') ? ' '.measuringUnitString(0, "size", $object->width_units) : ''; + print '
'.$form->editfieldkey("Height", 'trueHeight', $object->trueHeight, $object, $user->rights->expedition->creer).''; + if ($action == 'edittrueHeight') { + print ''; + print ''; + print ''; + print ''; + print ''; + print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2); + print ' '; + print ' '; + print ''; + } else { + print $object->trueHeight; + print ($object->trueHeight && $object->height_units != '') ? ' '.measuringUnitString(0, "size", $object->height_units) : ''; + } + + print '
'.$form->editfieldkey("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->expedition->creer).''; + print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->expedition->creer); + print ($object->trueDepth && $object->depth_units != '') ? ' '.measuringUnitString(0, "size", $object->depth_units) : ''; + print '
'; + print $langs->trans("Volume"); + print ''; + $calculatedVolume = 0; + $volumeUnit = 0; + if ($object->trueWidth && $object->trueHeight && $object->trueDepth) { + $calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth); + $volumeUnit = $object->size_units * 3; + } + // If sending volume not defined we use sum of products + if ($calculatedVolume > 0) { + if ($volumeUnit < 50) { + print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no'); } else { - if ($object->statut <= 1) { - print ''.$langs->trans("QtyToShip").''.$langs->trans("QtyShipped").''.$langs->trans("WarehouseSource").''.$langs->trans("Batch").''.$langs->trans("CalculatedWeight").''.$langs->trans("CalculatedVolume").''.$langs->trans("Size").'
'; + + print ''; + print '
'; + print '
'; + + print ''; + + // Sending method + print ''; + print ''; + + // Tracking Number + print ''; + + // Incoterms + if (isModEnabled('incoterm')) { + print ''; + print ''; + } + + // Other attributes + $parameters = array('colspan' => ' colspan="3"', 'cols' => '3'); + $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + print "
'; + print ''; + + if ($action != 'editshipping_method_id') { + print ''; + } + print '
'; + print $langs->trans('SendingMethod'); + print 'id.'">'.img_edit($langs->trans('SetSendingMethod'), 1).'
'; + print '
'; + if ($action == 'editshipping_method_id') { + print '
'; + print ''; + print ''; + $object->fetch_delivery_methods(); + print $form->selectarray("shipping_method_id", $object->meths, $object->shipping_method_id, 1, 0, 0, "", 1); + if ($user->admin) { + print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); + } + print ''; + print '
'; + } else { + if ($object->shipping_method_id > 0) { + // Get code using getLabelFromKey + $code = $langs->getLabelFromKey($db, $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code'); + print $langs->trans("SendingMethod".strtoupper($code)); + } + } + print '
'.$form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->rights->expedition->creer).''; + print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->rights->expedition->creer, 'safehtmlstring', $object->tracking_number); + print '
'; + print '
'; + print $langs->trans('IncotermLabel'); + print ''; + if ($user->rights->expedition->creer) { + print ''.img_edit().''; + } else { + print ' '; + } + print '
'; + print '
'; + if ($action != 'editincoterm') { + print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1); + } else { + print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id); + } + print '
"; + + print '
'; + print ''; + + print '
'; + + + // Lines of products + + if ($action == 'editline') { + print '
+ + + + + '; + } + print '
'; + + print '
'; + print ''; + print ''; + print ''; + // Adds a line numbering column + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { + print ''; + } + // Product/Service + print ''; + // Qty + print ''; + if ($origin && $origin_id > 0) { + print ''; + } + if ($action == 'editline') { + $editColspan = 3; + if (!isModEnabled('stock')) { + $editColspan--; + } + if (empty($conf->productbatch->enabled)) { + $editColspan--; + } + print ''; + } else { + if ($object->statut <= 1) { + print ''; + } else { + print ''; + } + if (isModEnabled('stock')) { + print ''; } - // Get list of products already sent for same source object into $alreadysent - $alreadysent = array(); - if ($origin && $origin_id > 0) { - $sql = "SELECT obj.rowid, obj.fk_product, obj.label, obj.description, obj.product_type as fk_product_type, obj.qty as qty_asked, obj.fk_unit, obj.date_start, obj.date_end"; - $sql .= ", ed.rowid as shipmentline_id, ed.qty as qty_shipped, ed.fk_expedition as expedition_id, ed.fk_origin_line, ed.fk_entrepot"; - $sql .= ", e.rowid as shipment_id, e.ref as shipment_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_expedition"; - //if ($conf->delivery_note->enabled) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received"; - $sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tosell as product_tosell, p.tobuy as product_tobuy, p.tobatch as product_tobatch'; - $sql .= ', p.description as product_desc'; - $sql .= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed"; - $sql .= ", ".MAIN_DB_PREFIX."expedition as e"; - $sql .= ", ".MAIN_DB_PREFIX.$origin."det as obj"; - //if ($conf->delivery_note->enabled) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."delivery as l ON l.fk_expedition = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."deliverydet as ld ON ld.fk_delivery = l.rowid AND obj.rowid = ld.fk_origin_line"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid"; - $sql .= " WHERE e.entity IN (".getEntity('expedition').")"; - $sql .= " AND obj.fk_".$origin." = ".((int) $origin_id); - $sql .= " AND obj.rowid = ed.fk_origin_line"; - $sql .= " AND ed.fk_expedition = e.rowid"; - //if ($filter) $sql.= $filter; - $sql .= " ORDER BY obj.fk_product"; + if (isModEnabled('productbatch')) { + print ''; + } + } + print ''; + print ''; + //print ''; + if ($object->statut == 0) { + print ''; + print ''; + } + print "\n"; + print ''; - dol_syslog("expedition/card.php get list of shipment lines", LOG_DEBUG); - $resql = $db->query($sql); - if ($resql) { - $num = $db->num_rows($resql); - $i = 0; + $outputlangs = $langs; - while ($i < $num) { - $obj = $db->fetch_object($resql); - if ($obj) { - // $obj->rowid is rowid in $origin."det" table - $alreadysent[$obj->rowid][$obj->shipmentline_id] = array( - 'shipment_ref'=>$obj->shipment_ref, 'shipment_id'=>$obj->shipment_id, 'warehouse'=>$obj->fk_entrepot, 'qty_shipped'=>$obj->qty_shipped, - 'product_tosell'=>$obj->product_tosell, 'product_tobuy'=>$obj->product_tobuy, 'product_tobatch'=>$obj->product_tobatch, - 'date_valid'=>$db->jdate($obj->date_valid), 'date_delivery'=>$db->jdate($obj->date_delivery)); - } - $i++; + if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { + $object->fetch_thirdparty(); + $newlang = ''; + if (empty($newlang) && GETPOST('lang_id', 'aZ09')) { + $newlang = GETPOST('lang_id', 'aZ09'); + } + if (empty($newlang)) { + $newlang = $object->thirdparty->default_lang; + } + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + } + + // Get list of products already sent for same source object into $alreadysent + $alreadysent = array(); + if ($origin && $origin_id > 0) { + $sql = "SELECT obj.rowid, obj.fk_product, obj.label, obj.description, obj.product_type as fk_product_type, obj.qty as qty_asked, obj.fk_unit, obj.date_start, obj.date_end"; + $sql .= ", ed.rowid as shipmentline_id, ed.qty as qty_shipped, ed.fk_expedition as expedition_id, ed.fk_origin_line, ed.fk_entrepot"; + $sql .= ", e.rowid as shipment_id, e.ref as shipment_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_expedition"; + //if ($conf->delivery_note->enabled) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received"; + $sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tosell as product_tosell, p.tobuy as product_tobuy, p.tobatch as product_tobatch'; + $sql .= ', p.description as product_desc'; + $sql .= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed"; + $sql .= ", ".MAIN_DB_PREFIX."expedition as e"; + $sql .= ", ".MAIN_DB_PREFIX.$origin."det as obj"; + //if ($conf->delivery_note->enabled) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."delivery as l ON l.fk_expedition = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."deliverydet as ld ON ld.fk_delivery = l.rowid AND obj.rowid = ld.fk_origin_line"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid"; + $sql .= " WHERE e.entity IN (".getEntity('expedition').")"; + $sql .= " AND obj.fk_".$origin." = ".((int) $origin_id); + $sql .= " AND obj.rowid = ed.fk_origin_line"; + $sql .= " AND ed.fk_expedition = e.rowid"; + //if ($filter) $sql.= $filter; + $sql .= " ORDER BY obj.fk_product"; + + dol_syslog("expedition/card.php get list of shipment lines", LOG_DEBUG); + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + + while ($i < $num) { + $obj = $db->fetch_object($resql); + if ($obj) { + // $obj->rowid is rowid in $origin."det" table + $alreadysent[$obj->rowid][$obj->shipmentline_id] = array( + 'shipment_ref'=>$obj->shipment_ref, 'shipment_id'=>$obj->shipment_id, 'warehouse'=>$obj->fk_entrepot, 'qty_shipped'=>$obj->qty_shipped, + 'product_tosell'=>$obj->product_tosell, 'product_tobuy'=>$obj->product_tobuy, 'product_tobatch'=>$obj->product_tobatch, + 'date_valid'=>$db->jdate($obj->date_valid), 'date_delivery'=>$db->jdate($obj->date_delivery)); } + $i++; } - //var_dump($alreadysent); + } + //var_dump($alreadysent); + } + + print ''; + + // Loop on each product to send/sent + for ($i = 0; $i < $num_prod; $i++) { + $parameters = array('i' => $i, 'line' => $lines[$i], 'line_id' => $line_id, 'num' => $num_prod, 'alreadysent' => $alreadysent, 'editColspan' => !empty($editColspan) ? $editColspan : 0, 'outputlangs' => $outputlangs); + $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } - print ''; + if (empty($reshook)) { + print ''; // id of order line + print ''; - // Loop on each product to send/sent - for ($i = 0; $i < $num_prod; $i++) { - $parameters = array('i' => $i, 'line' => $lines[$i], 'line_id' => $line_id, 'num' => $num_prod, 'alreadysent' => $alreadysent, 'editColspan' => !empty($editColspan) ? $editColspan : 0, 'outputlangs' => $outputlangs); - $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action); - if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + // # + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { + print ''; } - if (empty($reshook)) { - print ''; // id of order line - print ''; - - // # - if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { - print ''; - } - - // Predefined product or service - if ($lines[$i]->fk_product > 0) { - // Define output language - if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { - $prod = new Product($db); - $prod->fetch($lines[$i]->fk_product); - $label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product_label; - } else { - $label = (!empty($lines[$i]->label) ? $lines[$i]->label : $lines[$i]->product_label); - } - - print '\n"; + // Predefined product or service + if ($lines[$i]->fk_product > 0) { + // Define output language + if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { + $prod = new Product($db); + $prod->fetch($lines[$i]->fk_product); + $label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product_label; } else { - print '\n"; + $label = (!empty($lines[$i]->label) ? $lines[$i]->label : $lines[$i]->product_label); } - $unit_order = ''; - if (!empty($conf->global->PRODUCT_USE_UNITS)) { - $unit_order = measuringUnitString($lines[$i]->fk_unit); + print '\n"; + } else { + print ''; + if (!empty($lines[$i]->label)) { + $text .= ' '.$lines[$i]->label.''; + print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i); + } else { + print $text.' '.nl2br($lines[$i]->description); + } - // Qty in other shipments (with shipment and warehouse used) - if ($origin && $origin_id > 0) { - print '\n"; + } - $j++; - if ($j > 1) { - print '
'; - } - $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) { - $warehousestatic->fetch($shipmentline_var['warehouse']); - $htmltext .= '
'.$langs->trans("FromLocation").' : '.$warehousestatic->getNomUrl(1, '', 0, 1); - } - print ' '.$form->textwithpicto('', $htmltext, 1); + $unit_order = ''; + if (!empty($conf->global->PRODUCT_USE_UNITS)) { + $unit_order = measuringUnitString($lines[$i]->fk_unit); + } + + // Qty ordered + print ''; + + // Qty in other shipments (with shipment and warehouse used) + if ($origin && $origin_id > 0) { + print ''; } + print ''; + } - if ($action == 'editline' && $lines[$i]->id == $line_id) { - // edit mode - print ''; + } else { + // Qty to ship or shipped + print ''; + + // Warehouse source + if (isModEnabled('stock')) { + print ''; + } + + // Batch number managment + if (isModEnabled('productbatch')) { + if (isset($lines[$i]->detail_batch)) { + print ''; + print ''; - } - - // Batch number managment - if (isModEnabled('productbatch')) { - if (isset($lines[$i]->detail_batch)) { - print ''; - print ''; - } else { - print ''; - } - } - } - - // Weight - print ''; - - // Volume - print ''; - - // Size - //print ''; - - if ($action == 'editline' && $lines[$i]->id == $line_id) { - print ''; - } elseif ($object->statut == Expedition::STATUS_DRAFT) { - // edit-delete buttons - print ''; - print ''; - - // Display lines extrafields - if (!empty($rowExtrafieldsStart)) { - print $rowExtrafieldsStart; - print $rowExtrafieldsView; - print $rowEnd; - } - } - print ""; - - // Display lines extrafields. - // $line is a line of shipment - if (!empty($extrafields)) { - $colspan = 6; - if ($origin && $origin_id > 0) { - $colspan++; - } - if (isModEnabled('productbatch')) { - $colspan++; - } - if (isModEnabled('stock')) { - $colspan++; - } - - $line = $lines[$i]; - $line->fetch_optionals(); - - // TODO Show all in same line by setting $display_type = 'line' - if ($action == 'editline' && $line->id == $line_id) { - print $lines[$i]->showOptionals($extrafields, 'edit', array('colspan'=>$colspan), !empty($indiceAsked) ? $indiceAsked : '', '', 0, 'card'); } else { - print $lines[$i]->showOptionals($extrafields, 'view', array('colspan'=>$colspan), !empty($indiceAsked) ? $indiceAsked : '', '', 0, 'card'); + print ''; } } } + + // Weight + print ''; + + // Volume + print ''; + + // Size + //print ''; + + if ($action == 'editline' && $lines[$i]->id == $line_id) { + print ''; + } elseif ($object->statut == Expedition::STATUS_DRAFT) { + // edit-delete buttons + print ''; + print ''; + + // Display lines extrafields + if (!empty($rowExtrafieldsStart)) { + print $rowExtrafieldsStart; + print $rowExtrafieldsView; + print $rowEnd; + } + } + print ""; + + // Display lines extrafields. + // $line is a line of shipment + if (!empty($extrafields)) { + $colspan = 6; + if ($origin && $origin_id > 0) { + $colspan++; + } + if (isModEnabled('productbatch')) { + $colspan++; + } + if (isModEnabled('stock')) { + $colspan++; + } + + $line = $lines[$i]; + $line->fetch_optionals(); + + // TODO Show all in same line by setting $display_type = 'line' + if ($action == 'editline' && $line->id == $line_id) { + print $lines[$i]->showOptionals($extrafields, 'edit', array('colspan'=>$colspan), !empty($indiceAsked) ? $indiceAsked : '', '', 0, 'card'); + } else { + print $lines[$i]->showOptionals($extrafields, 'view', array('colspan'=>$colspan), !empty($indiceAsked) ? $indiceAsked : '', '', 0, 'card'); + } + } } - - // TODO Show also lines ordered but not delivered - - print "
 '.$langs->trans("Products").''.$langs->trans("QtyOrdered").''.$langs->trans("QtyInOtherShipments").''; + if ($object->statut <= 1) { + print $langs->trans("QtyToShip").' - '; + } else { + print $langs->trans("QtyShipped").' - '; + } + if (isModEnabled('stock')) { + print $langs->trans("WarehouseSource").' - '; + } + if (isModEnabled('productbatch')) { + print $langs->trans("Batch"); + } + print ''.$langs->trans("QtyToShip").''.$langs->trans("QtyShipped").''.$langs->trans("WarehouseSource").''.$langs->trans("Batch").''.$langs->trans("CalculatedWeight").''.$langs->trans("CalculatedVolume").''.$langs->trans("Size").'
'.($i + 1).'
'.($i + 1).''; - - // Show product and description - $product_static->type = $lines[$i]->fk_product_type; - $product_static->id = $lines[$i]->fk_product; - $product_static->ref = $lines[$i]->ref; - $product_static->status = $lines[$i]->product_tosell; - $product_static->status_buy = $lines[$i]->product_tobuy; - $product_static->status_batch = $lines[$i]->product_tobatch; - - $product_static->weight = $lines[$i]->weight; - $product_static->weight_units = $lines[$i]->weight_units; - $product_static->length = $lines[$i]->length; - $product_static->length_units = $lines[$i]->length_units; - $product_static->width = !empty($lines[$i]->width) ? $lines[$i]->width : 0; - $product_static->width_units = !empty($lines[$i]->width_units) ? $lines[$i]->width_units : 0; - $product_static->height = !empty($lines[$i]->height) ? $lines[$i]->height : 0; - $product_static->height_units = !empty($lines[$i]->height_units) ? $lines[$i]->height_units : 0; - $product_static->surface = $lines[$i]->surface; - $product_static->surface_units = $lines[$i]->surface_units; - $product_static->volume = $lines[$i]->volume; - $product_static->volume_units = $lines[$i]->volume_units; - - $text = $product_static->getNomUrl(1); - $text .= ' - '.$label; - $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($lines[$i]->description)); - print $form->textwithtooltip($text, $description, 3, '', '', $i); - print_date_range(!empty($lines[$i]->date_start) ? $lines[$i]->date_start : '', !empty($lines[$i]->date_end) ? $lines[$i]->date_end : ''); - if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) { - print (!empty($lines[$i]->description) && $lines[$i]->description != $lines[$i]->product) ? '
'.dol_htmlentitiesbr($lines[$i]->description) : ''; - } - print "
'; - if ($lines[$i]->product_type == Product::TYPE_SERVICE) { - $text = img_object($langs->trans('Service'), 'service'); - } else { - $text = img_object($langs->trans('Product'), 'product'); - } - - if (!empty($lines[$i]->label)) { - $text .= ' '.$lines[$i]->label.''; - print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i); - } else { - print $text.' '.nl2br($lines[$i]->description); - } - - print_date_range($lines[$i]->date_start, $lines[$i]->date_end); - print "'; + + // Show product and description + $product_static->type = $lines[$i]->fk_product_type; + $product_static->id = $lines[$i]->fk_product; + $product_static->ref = $lines[$i]->ref; + $product_static->status = $lines[$i]->product_tosell; + $product_static->status_buy = $lines[$i]->product_tobuy; + $product_static->status_batch = $lines[$i]->product_tobatch; + + $product_static->weight = $lines[$i]->weight; + $product_static->weight_units = $lines[$i]->weight_units; + $product_static->length = $lines[$i]->length; + $product_static->length_units = $lines[$i]->length_units; + $product_static->width = !empty($lines[$i]->width) ? $lines[$i]->width : 0; + $product_static->width_units = !empty($lines[$i]->width_units) ? $lines[$i]->width_units : 0; + $product_static->height = !empty($lines[$i]->height) ? $lines[$i]->height : 0; + $product_static->height_units = !empty($lines[$i]->height_units) ? $lines[$i]->height_units : 0; + $product_static->surface = $lines[$i]->surface; + $product_static->surface_units = $lines[$i]->surface_units; + $product_static->volume = $lines[$i]->volume; + $product_static->volume_units = $lines[$i]->volume_units; + + $text = $product_static->getNomUrl(1); + $text .= ' - '.$label; + $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($lines[$i]->description)); + print $form->textwithtooltip($text, $description, 3, '', '', $i); + print_date_range(!empty($lines[$i]->date_start) ? $lines[$i]->date_start : '', !empty($lines[$i]->date_end) ? $lines[$i]->date_end : ''); + if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) { + print (!empty($lines[$i]->description) && $lines[$i]->description != $lines[$i]->product) ? '
'.dol_htmlentitiesbr($lines[$i]->description) : ''; + } + print "
'; + if ($lines[$i]->product_type == Product::TYPE_SERVICE) { + $text = img_object($langs->trans('Service'), 'service'); + } else { + $text = img_object($langs->trans('Product'), 'product'); } - // Qty ordered - print ''.$lines[$i]->qty_asked.' '.$unit_order.''; - foreach ($alreadysent as $key => $val) { - if ($lines[$i]->fk_origin_line == $key) { - $j = 0; - foreach ($val as $shipmentline_id => $shipmentline_var) { - if ($shipmentline_var['shipment_id'] == $lines[$i]->fk_expedition) { - continue; // We want to show only "other shipments" - } + print_date_range($lines[$i]->date_start, $lines[$i]->date_end); + print "'.$lines[$i]->qty_asked.' '.$unit_order.''; + foreach ($alreadysent as $key => $val) { + if ($lines[$i]->fk_origin_line == $key) { + $j = 0; + foreach ($val as $shipmentline_id => $shipmentline_var) { + if ($shipmentline_var['shipment_id'] == $lines[$i]->fk_expedition) { + continue; // We want to show only "other shipments" } + + $j++; + if ($j > 1) { + print '
'; + } + $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) { + $warehousestatic->fetch($shipmentline_var['warehouse']); + $htmltext .= '
'.$langs->trans("FromLocation").' : '.$warehousestatic->getNomUrl(1, '', 0, 1); + } + print ' '.$form->textwithpicto('', $htmltext, 1); } } - print '
'; - if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0) { - print ''; - $line = new ExpeditionLigne($db); - foreach ($lines[$i]->detail_batch as $detail_batch) { - print ''; - // Qty to ship or shipped - print ''; - // Batch number managment - if ($lines[$i]->entrepot_id == 0) { - // only show lot numbers from src warehouse when shipping from multiple warehouses - $line->fetch($detail_batch->fk_expeditiondet); - } - $entrepot_id = !empty($detail_batch->entrepot_id)?$detail_batch->entrepot_id:$lines[$i]->entrepot_id; - print ''; - print ''; - } - // add a 0 qty lot row to be able to add a lot + if ($action == 'editline' && $lines[$i]->id == $line_id) { + // edit mode + print ''; - } else { + } elseif (!isModEnabled('stock') && empty($conf->productbatch->enabled)) { // both product batch and stock are not activated. + print ''; + print ''; // Qty to ship or shipped - print ''; - + print ''; // Warehouse source - if (isModEnabled('stock')) { - print ''; + // Batch number managment + print ''; + print ''; + } + + print '
'.$formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $entrepot_id).'
'; + if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0) { + print ''; + $line = new ExpeditionLigne($db); + foreach ($lines[$i]->detail_batch as $detail_batch) { print ''; // Qty to ship or shipped - print ''; + print ''; // Batch number managment - print ''; + if ($lines[$i]->entrepot_id == 0) { + // only show lot numbers from src warehouse when shipping from multiple warehouses + $line->fetch($detail_batch->fk_expeditiondet); + } + $entrepot_id = !empty($detail_batch->entrepot_id)?$detail_batch->entrepot_id:$lines[$i]->entrepot_id; + print ''; print ''; - } elseif (isModEnabled('stock')) { - if ($lines[$i]->fk_product > 0) { - if ($lines[$i]->entrepot_id > 0) { - print ''; - print ''; - // Qty to ship or shipped - print ''; - // Warehouse source - print ''; - // Batch number managment - print ''; - print ''; - } elseif (count($lines[$i]->details_entrepot) > 1) { - print ''; - foreach ($lines[$i]->details_entrepot as $detail_entrepot) { - print ''; - // Qty to ship or shipped - print ''; - // Warehouse source - print ''; - // Batch number managment - print ''; - print ''; - } - } else { - print ''; - print ''; - } - } else { - print ''; + } + // add a 0 qty lot row to be able to add a lot + print ''; + // Qty to ship or shipped + print ''; + // Batch number managment + print ''; + print ''; + } elseif (isModEnabled('stock')) { + if ($lines[$i]->fk_product > 0) { + if ($lines[$i]->entrepot_id > 0) { + print ''; print ''; // Qty to ship or shipped print ''; // Warehouse source - print ''; + print ''; // Batch number managment - print ''; + print ''; print ''; + } elseif (count($lines[$i]->details_entrepot) > 1) { + print ''; + foreach ($lines[$i]->details_entrepot as $detail_entrepot) { + print ''; + // Qty to ship or shipped + print ''; + // Warehouse source + print ''; + // Batch number managment + print ''; + print ''; + } + } else { + print ''; + print ''; } - } elseif (!isModEnabled('stock') && empty($conf->productbatch->enabled)) { // both product batch and stock are not activated. - print ''; + } else { + print ''; print ''; // Qty to ship or shipped - print ''; + print ''; // Warehouse source print ''; // Batch number managment print ''; print ''; } - - print '
'.$formproduct->selectLotStock('', 'batchl'.$line_id.'_0', '', 1, 0, $lines[$i]->fk_product).''.$formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $entrepot_id).'
'.$unit_order.''.$formproduct->selectWarehouses($lines[$i]->entrepot_id, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).' - '.$langs->trans("NA").'
'.$unit_order.''.$formproduct->selectWarehouses($detail_entrepot->entrepot_id, 'entl'.$detail_entrepot->line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).' - '.$langs->trans("NA").'
'.$langs->trans("NotEnoughStock").'
'.$formproduct->selectLotStock('', 'batchl'.$line_id.'_0', '', 1, 0, $lines[$i]->fk_product).'
'.$unit_order.''.$formproduct->selectWarehouses($lines[$i]->entrepot_id, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).' - '.$langs->trans("NA").'
'.$unit_order.''.$formproduct->selectWarehouses($detail_entrepot->entrepot_id, 'entl'.$detail_entrepot->line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).' - '.$langs->trans("NA").'
'.$langs->trans("NotEnoughStock").'
'.$unit_order.'
'.$lines[$i]->qty_shipped.' '.$unit_order.''; - if ($lines[$i]->entrepot_id > 0) { - $entrepot = new Entrepot($db); - $entrepot->fetch($lines[$i]->entrepot_id); - print $entrepot->getNomUrl(1); - } elseif (count($lines[$i]->details_entrepot) > 1) { - $detail = ''; - foreach ($lines[$i]->details_entrepot as $detail_entrepot) { - 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).'
'; - } + print '
'.$lines[$i]->qty_shipped.' '.$unit_order.''; + if ($lines[$i]->entrepot_id > 0) { + $entrepot = new Entrepot($db); + $entrepot->fetch($lines[$i]->entrepot_id); + print $entrepot->getNomUrl(1); + } elseif (count($lines[$i]->details_entrepot) > 1) { + $detail = ''; + foreach ($lines[$i]->details_entrepot as $detail_entrepot) { + 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).'
'; } - print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"), $detail); + } + print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"), $detail); + } + print '
'; + if ($lines[$i]->product_tobatch) { + $detail = ''; + foreach ($lines[$i]->detail_batch as $dbatch) { // $dbatch is instance of ExpeditionLineBatch + $detail .= $langs->trans("Batch").': '.$dbatch->batch; + if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { + $detail .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day"); + } + if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { + $detail .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day"); + } + $detail .= ' - '.$langs->trans("Qty").': '.$dbatch->qty; + $detail .= '
'; + } + print $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $detail); + } else { + print $langs->trans("NA"); } print '
'; - if ($lines[$i]->product_tobatch) { - $detail = ''; - foreach ($lines[$i]->detail_batch as $dbatch) { // $dbatch is instance of ExpeditionLineBatch - $detail .= $langs->trans("Batch").': '.$dbatch->batch; - if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { - $detail .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day"); - } - if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { - $detail .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day"); - } - $detail .= ' - '.$langs->trans("Qty").': '.$dbatch->qty; - $detail .= '
'; - } - print $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $detail); - } else { - print $langs->trans("NA"); - } - print '
'; - if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) { - print $lines[$i]->weight * $lines[$i]->qty_shipped.' '.measuringUnitString(0, "weight", $lines[$i]->weight_units); - } else { - print ' '; - } - print ''; - if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) { - print $lines[$i]->volume * $lines[$i]->qty_shipped.' '.measuringUnitString(0, "volume", $lines[$i]->volume_units); - } else { - print ' '; - } - print ''.$lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuringUnitString(0, "volume", $lines[$i]->volume_units).''; - print '
'; - print '
'; - print '
'; - print 'id.'">'.img_edit().''; - print ''; - print 'id.'">'.img_delete().''; - print '
'; + if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) { + print $lines[$i]->weight * $lines[$i]->qty_shipped.' '.measuringUnitString(0, "weight", $lines[$i]->weight_units); + } else { + print ' '; + } + print ''; + if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) { + print $lines[$i]->volume * $lines[$i]->qty_shipped.' '.measuringUnitString(0, "volume", $lines[$i]->volume_units); + } else { + print ' '; + } + print ''.$lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuringUnitString(0, "volume", $lines[$i]->volume_units).''; + print '
'; + print '
'; + print '
'; + print 'id.'">'.img_edit().''; + print ''; + print 'id.'">'.img_delete().''; + print '
\n"; - print ''; - print '
'; } + // TODO Show also lines ordered but not delivered + + print "\n"; + print ''; + print ''; + print dol_get_fiche_end(); diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index 9394269a03a..2adf16e4c35 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -329,7 +329,7 @@ if ($id > 0 || !empty($ref)) { $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')"; } - print ''.$langs->trans('Discounts').''; + print ''.$langs->trans('Discounts').''; $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount); $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote); @@ -393,7 +393,7 @@ if ($id > 0 || !empty($ref)) { print 'id.'">'.img_edit($langs->trans('SetAvailability'), 1).''; } print ''; - print ''; + print ''; if ($action == 'editavailability') { $form->form_availability($_SERVER['PHP_SELF'].'?id='.$object->id, $object->availability_id, 'availability_id', 1); } else { @@ -450,7 +450,7 @@ if ($id > 0 || !empty($ref)) { print 'id.'">'.img_edit($langs->trans('SetDemandReason'), 1).''; } print ''; - print ''; + print ''; if ($action == 'editdemandreason') { $form->formInputReason($_SERVER['PHP_SELF'].'?id='.$object->id, $object->demand_reason_id, 'demand_reason_id', 1); } else { @@ -500,11 +500,11 @@ if ($id > 0 || !empty($ref)) { $totalVolume = $tmparray['volume']; if ($totalWeight || $totalVolume) { print ''.$langs->trans("CalculatedWeight").''; - print ''; + print ''; print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, isset($conf->global->MAIN_WEIGHT_DEFAULT_ROUND) ? $conf->global->MAIN_WEIGHT_DEFAULT_ROUND : -1, isset($conf->global->MAIN_WEIGHT_DEFAULT_UNIT) ? $conf->global->MAIN_WEIGHT_DEFAULT_UNIT : 'no'); print ''; print ''.$langs->trans("CalculatedVolume").''; - print ''; + print ''; print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, isset($conf->global->MAIN_VOLUME_DEFAULT_ROUND) ? $conf->global->MAIN_VOLUME_DEFAULT_ROUND : -1, isset($conf->global->MAIN_VOLUME_DEFAULT_UNIT) ? $conf->global->MAIN_VOLUME_DEFAULT_UNIT : 'no'); print ''; } @@ -524,7 +524,7 @@ if ($id > 0 || !empty($ref)) { } print ''; print ''; - print ''; + print ''; if ($action != 'editincoterm') { print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1); } else { diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index f559c31a89f..3e61571dea5 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -2415,7 +2415,7 @@ if ($action == 'create') { // Show object lines if (!empty($object->lines)) { - $ret = $object->printObjectLines($action, $societe, $mysoc, $lineid, 1); + $object->printObjectLines($action, $societe, $mysoc, $lineid, 1); } $num = count($object->lines); diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 6bc9ae679bb..50e450be105 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -3628,7 +3628,7 @@ if ($action == 'create') { // Show object lines if (!empty($object->lines)) { - $ret = $object->printObjectLines($action, $societe, $mysoc, $lineid, 1); + $object->printObjectLines($action, $societe, $mysoc, $lineid, 1); } $num = count($object->lines); diff --git a/htdocs/knowledgemanagement/class/knowledgerecord.class.php b/htdocs/knowledgemanagement/class/knowledgerecord.class.php index 69e7e40c16b..1d8075c21ea 100644 --- a/htdocs/knowledgemanagement/class/knowledgerecord.class.php +++ b/htdocs/knowledgemanagement/class/knowledgerecord.class.php @@ -1058,8 +1058,8 @@ class KnowledgeRecord extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index f17a128544a..887ef6e1a44 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -6111,8 +6111,8 @@ class Product extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index b47430bffc2..e70c67412ee 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -895,8 +895,8 @@ class Entrepot extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index ccefdb4c600..c8d3be0163d 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -2289,8 +2289,8 @@ class Project extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 3643a404863..dd5ccd7ef0b 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -4886,7 +4886,7 @@ class Societe extends CommonObject * Existing categories are left untouch. * * @param int[]|int $categories Category ID or array of Categories IDs - * @param string $type_categ Category type ('customer' or 'supplier') + * @param string $type_categ Category type ('customer' or 'supplier') * @return int <0 if KO, >0 if OK */ public function setCategories($categories, $type_categ) diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 71d9668dc92..4b898a75645 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1322,7 +1322,8 @@ if ($action == 'create') { // Shipping Method if (isModEnabled("expedition")) { print ''.$langs->trans('SendingMethod').''; - print $form->selectShippingMethod(GETPOST('shipping_method_id') > 0 ? GETPOST('shipping_method_id', 'int') : "", 'shipping_method_id', '', 1); + print img_picto('', 'object_dollyrevert', 'class="pictofixedwidth"'); + $form->selectShippingMethod(GETPOST('shipping_method_id') > 0 ? GETPOST('shipping_method_id', 'int') : "", 'shipping_method_id', '', 1); print ''; } @@ -1902,7 +1903,7 @@ if ($action == 'create') { } if (!empty($object->lines)) { - $ret = $object->printObjectLines($action, $soc, $mysoc, $lineid, $dateSelector); + $object->printObjectLines($action, $soc, $mysoc, $lineid, $dateSelector); } // Form to add new line diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index d077ed3e777..27cdf8d164b 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2318,8 +2318,8 @@ class Ticket extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 75c9f1b2bae..dddcaa0ca6a 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1390,8 +1390,8 @@ class User extends CommonObject * Adds it to non existing supplied categories. * Existing categories are left untouch. * - * @param int[]|int $categories Category or categories IDs - * @return void + * @param int[]|int $categories Category or categories IDs + * @return int <0 if KO, >0 if OK */ public function setCategories($categories) { From 1934db2dd103da100c3104d9bba4722d56f11a7a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 14:37:33 +0100 Subject: [PATCH 216/816] Debug v17 --- htdocs/core/modules/import/import_csv.modules.php | 2 +- htdocs/core/modules/import/import_xlsx.modules.php | 2 +- htdocs/core/modules/movement/doc/pdf_standard.modules.php | 8 +++++++- htdocs/debugbar/class/TraceableDB.php | 2 +- htdocs/install/upgrade2.php | 4 +++- htdocs/projet/tasks/task.php | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index e1699660acc..075de9f0d2a 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -579,7 +579,7 @@ class ImportCsv extends ModeleImports } } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getsuppliercodeifauto') { if (strtolower($newval) == 'auto') { - $newval = $this->thirdpartyobject->get_codefournisseur(0, 1); + $this->thirdpartyobject->get_codefournisseur(0, 1); $newval = $this->thirdpartyobject->code_fournisseur; //print 'code_fournisseur='.$newval; } diff --git a/htdocs/core/modules/import/import_xlsx.modules.php b/htdocs/core/modules/import/import_xlsx.modules.php index 0e63ea77075..0854a0f56c5 100644 --- a/htdocs/core/modules/import/import_xlsx.modules.php +++ b/htdocs/core/modules/import/import_xlsx.modules.php @@ -624,7 +624,7 @@ class ImportXlsx extends ModeleImports } } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getsuppliercodeifauto') { if (strtolower($newval) == 'auto') { - $newval = $this->thirdpartyobject->get_codefournisseur(0, 1); + $this->thirdpartyobject->get_codefournisseur(0, 1); $newval = $this->thirdpartyobject->code_fournisseur; //print 'code_fournisseur='.$newval; } diff --git a/htdocs/core/modules/movement/doc/pdf_standard.modules.php b/htdocs/core/modules/movement/doc/pdf_standard.modules.php index 094e19a280a..a823eadbc05 100644 --- a/htdocs/core/modules/movement/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/movement/doc/pdf_standard.modules.php @@ -941,7 +941,7 @@ class pdf_standard extends ModelePDFMovement * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output * @param string $titlekey Translation key to show as title of document - * @return void + * @return int Return topshift value */ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey = "") { @@ -1108,8 +1108,13 @@ class pdf_standard extends ModelePDFMovement $posy += 2; + $top_shift = 0; // Show list of linked objects + $current_y = $pdf->getY(); //$posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size); + //if ($current_y < $pdf->getY()) { + // $top_shift = $pdf->getY() - $current_y; + //} if ($showaddress) { /* @@ -1146,6 +1151,7 @@ class pdf_standard extends ModelePDFMovement } $pdf->SetTextColor(0, 0, 0); + return $top_shift; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore diff --git a/htdocs/debugbar/class/TraceableDB.php b/htdocs/debugbar/class/TraceableDB.php index 0b862f4df70..5863f1d902e 100644 --- a/htdocs/debugbar/class/TraceableDB.php +++ b/htdocs/debugbar/class/TraceableDB.php @@ -661,7 +661,7 @@ class TraceableDB extends DoliDB */ public function free($resultset = null) { - return $this->db->free($resultset); + $this->db->free($resultset); } /** diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index bbb12e8693e..51334eaae21 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -4485,7 +4485,7 @@ function migrate_reload_modules($db, $langs, $conf, $listofmodule = array(), $fo * @param DoliDB $db Database handler * @param Translate $langs Object langs * @param Conf $conf Object conf - * @return void + * @return int <0 if KO, >0 if OK */ function migrate_reload_menu($db, $langs, $conf) { @@ -4515,6 +4515,8 @@ function migrate_reload_menu($db, $langs, $conf) print ''; } + + return 1; } /** diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index 8b19c8c0519..fccf9d2ffe1 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -467,7 +467,7 @@ if ($id > 0 || !empty($ref)) { // Task parent print ''.$langs->trans("ChildOfProjectTask").''; - print $formother->selectProjectTasks($object->fk_task_parent, $projectstatic->id, 'task_parent', ($user->admin ? 0 : 1), 0, 0, 0, $object->id); + $formother->selectProjectTasks($object->fk_task_parent, $projectstatic->id, 'task_parent', ($user->admin ? 0 : 1), 0, 0, 0, $object->id); print ''; // Date start From 26ef1cb27088c78402779c8fa3b195348079c447 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 14:43:31 +0100 Subject: [PATCH 217/816] Debug v17 --- .../modules/expedition/doc/pdf_espadon.modules.php | 11 ++++++++++- .../modules/expedition/doc/pdf_merou.modules.php | 14 +++++++++++++- .../modules/expedition/doc/pdf_rouget.modules.php | 13 ++++++++++++- .../class/conferenceorbooth.class.php | 5 ++--- htdocs/hrm/class/evaluation.class.php | 4 ++-- htdocs/hrm/class/evaluationdet.class.php | 7 ++++--- htdocs/hrm/class/job.class.php | 4 ++-- htdocs/hrm/class/position.class.php | 4 ++-- htdocs/hrm/class/skill.class.php | 4 ++-- htdocs/hrm/class/skillrank.class.php | 4 ++-- .../class/knowledgerecord.class.php | 4 ++-- htdocs/mrp/class/mo.class.php | 4 ++-- htdocs/partnership/class/partnership.class.php | 4 ++-- .../stocktransfer/class/stocktransfer.class.php | 4 ++-- .../class/stocktransferline.class.php | 4 ++-- .../class/recruitmentcandidature.class.php | 4 ++-- htdocs/webhook/class/target.class.php | 4 ++-- htdocs/workstation/class/workstation.class.php | 4 ++-- 18 files changed, 67 insertions(+), 35 deletions(-) diff --git a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php index b87298d3dd8..d486a56bb08 100644 --- a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php @@ -945,7 +945,7 @@ class pdf_espadon extends ModelePdfExpedition * @param Expedition $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output - * @return void + * @return int <0 if KO, > if OK */ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs) { @@ -1078,6 +1078,14 @@ class pdf_espadon extends ModelePdfExpedition } } + $top_shift = 0; + // Show list of linked objects + /*$current_y = $pdf->getY(); + $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size); + if ($current_y < $pdf->getY()) { + $top_shift = $pdf->getY() - $current_y; + }*/ + if ($showaddress) { // Sender properties $carac_emetteur = ''; @@ -1183,6 +1191,7 @@ class pdf_espadon extends ModelePdfExpedition } $pdf->SetTextColor(0, 0, 0); + return $top_shift; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore diff --git a/htdocs/core/modules/expedition/doc/pdf_merou.modules.php b/htdocs/core/modules/expedition/doc/pdf_merou.modules.php index e847dc26fec..2bf6e583826 100644 --- a/htdocs/core/modules/expedition/doc/pdf_merou.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_merou.modules.php @@ -520,7 +520,7 @@ class pdf_merou extends ModelePdfExpedition * @param Expedition $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output - * @return void + * @return int <0 if KO, > if OK */ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs) { @@ -700,6 +700,16 @@ class pdf_merou extends ModelePdfExpedition $widthrecbox = $blW; + $top_shift = 0; + // Show list of linked objects + /* + $current_y = $pdf->getY(); + $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size); + if ($current_y < $pdf->getY()) { + $top_shift = $pdf->getY() - $current_y; + } + */ + // Show Recipient frame $pdf->SetFont('', 'B', $default_font_size - 3); $pdf->SetXY($blDestX, $Yoff - 4); @@ -717,5 +727,7 @@ class pdf_merou extends ModelePdfExpedition $pdf->SetFont('', '', $default_font_size - 3); $pdf->SetXY($blDestX, $posy); $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L'); + + return $top_shift; } } diff --git a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php index 71fb4c4c194..2c7af07b32f 100644 --- a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php @@ -890,7 +890,7 @@ class pdf_rouget extends ModelePdfExpedition * @param Expedition $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output - * @return void + * @return int <0 if KO, > if OK */ protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs) { @@ -1023,6 +1023,16 @@ class pdf_rouget extends ModelePdfExpedition } } + $top_shift = 0; + // Show list of linked objects + /* + $current_y = $pdf->getY(); + $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size); + if ($current_y < $pdf->getY()) { + $top_shift = $pdf->getY() - $current_y; + } + */ + if ($showaddress) { // Sender properties $carac_emetteur = ''; @@ -1128,6 +1138,7 @@ class pdf_rouget extends ModelePdfExpedition } $pdf->SetTextColor(0, 0, 0); + return $top_shift; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index cdb67a2c37b..556443a25e8 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -217,7 +217,6 @@ class ConferenceOrBooth extends ActionComm $this->socid = $this->fk_soc; $this->datef = $this->datep2; $this->note_private = $this->note; - $this->fk_user_author = $this->fk_user_author; } /** @@ -716,8 +715,8 @@ class ConferenceOrBooth extends ActionComm $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_conferenceorbooth = '.((int) $this->id))); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/hrm/class/evaluation.class.php b/htdocs/hrm/class/evaluation.class.php index 0125e7f882c..23ccc6c9fd2 100644 --- a/htdocs/hrm/class/evaluation.class.php +++ b/htdocs/hrm/class/evaluation.class.php @@ -923,8 +923,8 @@ class Evaluation extends CommonObject $result = $objectline->fetchAll('ASC', '', 0, 0, array('customsql'=>'fk_evaluation = '.$this->id)); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/hrm/class/evaluationdet.class.php b/htdocs/hrm/class/evaluationdet.class.php index f9bbde51912..5489065e52d 100644 --- a/htdocs/hrm/class/evaluationdet.class.php +++ b/htdocs/hrm/class/evaluationdet.class.php @@ -561,7 +561,8 @@ class Evaluationline extends CommonObject $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'evaluationline/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; $resql = $this->db->query($sql); if (!$resql) { - $error++; $this->error = $this->db->lasterror(); + $error++; + $this->error = $this->db->lasterror(); } // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments @@ -891,8 +892,8 @@ class Evaluationline extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_evaluationdet = '.$this->id)); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php index 117878c10c9..a08e8c713ae 100644 --- a/htdocs/hrm/class/job.class.php +++ b/htdocs/hrm/class/job.class.php @@ -925,8 +925,8 @@ class Job extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_job = '.$this->id)); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index 5d0c04a4f47..b72c11b36f6 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -971,8 +971,8 @@ class Position extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql' => 'fk_position = ' . $this->id)); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/hrm/class/skill.class.php b/htdocs/hrm/class/skill.class.php index 0cdc63ec24e..3f56294a7b2 100644 --- a/htdocs/hrm/class/skill.class.php +++ b/htdocs/hrm/class/skill.class.php @@ -965,8 +965,8 @@ class Skill extends CommonObject $result = $objectline->fetchAll('ASC', 'rankorder', 0, 0, array('customsql'=>'fk_skill = '.$this->id)); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/hrm/class/skillrank.class.php b/htdocs/hrm/class/skillrank.class.php index 6db80642bab..2d75425823e 100644 --- a/htdocs/hrm/class/skillrank.class.php +++ b/htdocs/hrm/class/skillrank.class.php @@ -919,8 +919,8 @@ class SkillRank extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_skillrank = '.((int) $this->id))); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/knowledgemanagement/class/knowledgerecord.class.php b/htdocs/knowledgemanagement/class/knowledgerecord.class.php index 1d8075c21ea..bf2bf38bbef 100644 --- a/htdocs/knowledgemanagement/class/knowledgerecord.class.php +++ b/htdocs/knowledgemanagement/class/knowledgerecord.class.php @@ -918,8 +918,8 @@ class KnowledgeRecord extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_knowledgerecord = '.((int) $this->id))); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 13f7cc5ae7b..30d6a3660a3 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -1275,8 +1275,8 @@ class Mo extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, $TFilters); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index 5908b964f2c..d7242f4e16c 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -1158,8 +1158,8 @@ class Partnership extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_partnership = '.((int) $this->id))); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php index 5ffb56ced44..60f13396b80 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php @@ -911,8 +911,8 @@ class StockTransfer extends CommonObject $result = $objectline->fetchAll('ASC', 'rang', 0, 0, array('customsql'=>'fk_stocktransfer = '.$this->id)); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php b/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php index 14febad09d4..4ee2f1db631 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php @@ -915,8 +915,8 @@ class StockTransferLine extends CommonObjectLine $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_stocktransferline = '.((int) $this->id))); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index 2ece5dbe217..1690f13da56 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -894,8 +894,8 @@ class RecruitmentCandidature extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_recruitmentcandidature = '.((int) $this->id))); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/webhook/class/target.class.php b/htdocs/webhook/class/target.class.php index ba33f2b8995..51a2a1beffa 100644 --- a/htdocs/webhook/class/target.class.php +++ b/htdocs/webhook/class/target.class.php @@ -911,8 +911,8 @@ class Target extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_target = '.((int) $this->id))); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } else { $this->lines = $result; diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php index 1213929fed9..d3b098784da 100644 --- a/htdocs/workstation/class/workstation.class.php +++ b/htdocs/workstation/class/workstation.class.php @@ -919,8 +919,8 @@ class Workstation extends CommonObject $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_workstation = '.((int) $this->id))); if (is_numeric($result)) { - $this->error = $this->error; - $this->errors = $this->errors; + $this->error = $objectline->error; + $this->errors = $objectline->errors; return $result; } From 169dcba95904584411bc86706c4da4b5241af091 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 14:54:06 +0100 Subject: [PATCH 218/816] Fix qodana --- htdocs/fourn/commande/list.php | 2 +- qodana.yaml | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index 3080a184abb..f02d2df24ca 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -1203,7 +1203,7 @@ if ($resql) { $topicmail = "SendOrderRef"; $modelmail = "order_supplier_send"; - $objecttmp = new CommandeFournisseur($db); + $objecttmp = new CommandeFournisseur($db); // in case $object is not the good object $trackid = 'sord'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; diff --git a/qodana.yaml b/qodana.yaml index 361afb8967f..36c35ece4c6 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -68,7 +68,10 @@ exclude: - name: PhpPropertyOnlyWrittenInspection - name: PhpCoveredCharacterInClassInspection - name: PhpSameParameterValueInspection + - name: PhpSillyAssignmentInspection - name: PhpConditionCheckedByNextConditionInspection - - name: RegExpSingleCharAlternation + - name: RegExpSingleCharAlternation - name: PhpSuspiciousNameCombinationInspection + - name: PhpWriteAccessToReferencedArrayValueWithoutUnsetInspection + \ No newline at end of file From cbda0e6197d1005ab02dc5506bb745507b830f0b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 15:17:37 +0100 Subject: [PATCH 219/816] Fix warnings --- htdocs/comm/action/card.php | 2 +- htdocs/core/boxes/box_activity.php | 32 ++++++++++++++----- htdocs/core/class/commonobject.class.php | 4 +-- .../modules/mrp/doc/pdf_vinci.modules.php | 8 ++--- htdocs/hrm/class/evaluation.class.php | 2 +- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index d1329e40454..91eb9f49516 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1353,7 +1353,7 @@ if ($action == 'create') { if (empty($donotclearsession)) { $assignedtouser = GETPOST("assignedtouser") ?GETPOST("assignedtouser") : (!empty($object->userownerid) && $object->userownerid > 0 ? $object->userownerid : $user->id); if ($assignedtouser) { - $listofuserid[$assignedtouser] = array('id'=>$assignedtouser, 'mandatory'=>0, 'transparency'=>$object->transparency); // Owner first + $listofuserid[$assignedtouser] = array('id'=>$assignedtouser, 'mandatory'=>0); // Owner first } //$listofuserid[$user->id] = array('id'=>$user->id, 'mandatory'=>0, 'transparency'=>(GETPOSTISSET('transparency') ? GETPOST('transparency', 'alpha') : 1)); // 1 by default at first init $listofuserid[$assignedtouser]['transparency'] = (GETPOSTISSET('transparency') ? GETPOST('transparency', 'alpha') : 1); // 1 by default at first init diff --git a/htdocs/core/boxes/box_activity.php b/htdocs/core/boxes/box_activity.php index 4829b32a72a..ea45580e163 100644 --- a/htdocs/core/boxes/box_activity.php +++ b/htdocs/core/boxes/box_activity.php @@ -155,7 +155,7 @@ class box_activity extends ModeleBoxes while ($j < count($data)) { $this->info_box_contents[$line][0] = array( 'td' => 'class="left" width="16"', - 'url' => DOL_URL_ROOT."/comm/propal/list.php?mainmenu=commercial&leftmenu=propals&search_status=".$data[$j]->fk_statut, + 'url' => DOL_URL_ROOT."/comm/propal/list.php?mainmenu=commercial&leftmenu=propals&search_status=".((int) $data[$j]->fk_statut), 'tooltip' => $langs->trans("Proposals")." ".$propalstatic->LibStatut($data[$j]->fk_statut, 0), 'logo' => 'object_propal' ); @@ -169,7 +169,7 @@ class box_activity extends ModeleBoxes 'td' => 'class="right"', 'text' => $data[$j]->nb, 'tooltip' => $langs->trans("Proposals")." ".$propalstatic->LibStatut($data[$j]->fk_statut, 0), - 'url' => DOL_URL_ROOT."/comm/propal/list.php?mainmenu=commercial&leftmenu=propals&search_status=".$data[$j]->fk_statut, + 'url' => DOL_URL_ROOT."/comm/propal/list.php?mainmenu=commercial&leftmenu=propals&search_status=".((int) $data[$j]->fk_statut), ); $totalnb += $data[$j]->nb; @@ -185,6 +185,13 @@ class box_activity extends ModeleBoxes $line++; $j++; } + if (count($data) == 0) { + $this->info_box_contents[$line][0] = array( + 'td' => 'class="center"', + 'text'=>$langs->trans("NoRecordedProposals"), + ); + $line++; + } } } @@ -273,6 +280,13 @@ class box_activity extends ModeleBoxes $line++; $j++; } + if (count($data) == 0) { + $this->info_box_contents[$line][0] = array( + 'td' => 'class="center"', + 'text'=>$langs->trans("NoRecordedOrders"), + ); + $line++; + } } } @@ -329,11 +343,11 @@ class box_activity extends ModeleBoxes if (!empty($data)) { $j = 0; while ($j < count($data)) { - $billurl = "search_status=2&paye=1"; + $billurl = "search_status=2&paye=1"; $this->info_box_contents[$line][0] = array( 'td' => 'class="left" width="16"', 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(1, $data[$j]->fk_statut, 0), - 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", + 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", 'logo' => 'bill', ); @@ -346,7 +360,7 @@ class box_activity extends ModeleBoxes 'td' => 'class="right"', 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(1, $data[$j]->fk_statut, 0), 'text' => $data[$j]->nb, - 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", + 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", ); $this->info_box_contents[$line][3] = array( @@ -369,6 +383,7 @@ class box_activity extends ModeleBoxes 'td' => 'class="center"', 'text'=>$langs->trans("NoRecordedInvoices"), ); + $line++; } } @@ -412,11 +427,11 @@ class box_activity extends ModeleBoxes $j = 0; while ($j < count($data)) { - $billurl = "search_status=".$data[$j]->fk_statut."&paye=0"; + $billurl = "search_status=".$data[$j]->fk_statut."&paye=0"; $this->info_box_contents[$line][0] = array( 'td' => 'class="left" width="16"', 'tooltip' => $langs->trans('Bills').' '.$facturestatic->LibStatut(0, $data[$j]->fk_statut, 0), - 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", + 'url' => DOL_URL_ROOT."/compta/facture/list.php?".$billurl."&mainmenu=accountancy&leftmenu=customers_bills", 'logo' => 'bill', ); @@ -446,8 +461,9 @@ class box_activity extends ModeleBoxes if (count($data) == 0) { $this->info_box_contents[$line][0] = array( 'td' => 'class="center"', - 'text'=>$langs->trans("NoRecordedInvoices"), + 'text'=>$langs->trans("NoRecordedUnpaidInvoices"), ); + $line++; } } } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index f8a48f49d40..aafed5900d8 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6457,9 +6457,9 @@ abstract class CommonObject return -1; } elseif ($value == '') { $new_array_languages[$key] = null; + } else { + $new_array_languages[$key] = $value; } - //dol_syslog("double value"." sur ".$attributeLabel."(".$value." is '".$attributeType."')", LOG_DEBUG); - $new_array_languages[$key] = $value; break; /*case 'select': // Not required, we chosed value='0' for undefined values if ($value=='-1') diff --git a/htdocs/core/modules/mrp/doc/pdf_vinci.modules.php b/htdocs/core/modules/mrp/doc/pdf_vinci.modules.php index 1416992e3c5..8e3eeeafa33 100644 --- a/htdocs/core/modules/mrp/doc/pdf_vinci.modules.php +++ b/htdocs/core/modules/mrp/doc/pdf_vinci.modules.php @@ -1405,14 +1405,13 @@ class pdf_vinci extends ModelePDFMo $rank = 0; $this->cols['code'] = array( 'rank' => $rank, - 'status' => false, + 'status' => true, 'width' => 35, // in mm 'title' => array( 'textkey' => 'Ref' ), 'border-left' => true, // add left line separator ); - $this->cols['code']['status'] = true; $rank = 1; // do not use negative rank $this->cols['desc'] = array( @@ -1455,14 +1454,13 @@ class pdf_vinci extends ModelePDFMo $rank = $rank + 10; $this->cols['dim'] = array( 'rank' => $rank, - 'status' => false, + 'status' => true, 'width' => 25, // in mm 'title' => array( 'textkey' => 'Size' ), 'border-left' => true, // add left line separator ); - $this->cols['dim']['status'] = true; $rank = $rank + 10; $this->cols['qty'] = array( @@ -1474,7 +1472,6 @@ class pdf_vinci extends ModelePDFMo ), 'border-left' => true, // add left line separator ); - $this->cols['qty']['status'] = true; $rank = $rank + 10; $this->cols['qtytot'] = array( @@ -1486,7 +1483,6 @@ class pdf_vinci extends ModelePDFMo ), 'border-left' => true, // add left line separator ); - $this->cols['qtytot']['status'] = true; // Add extrafields cols if (!empty($object->lines)) { diff --git a/htdocs/hrm/class/evaluation.class.php b/htdocs/hrm/class/evaluation.class.php index 23ccc6c9fd2..4a41f1c8e0e 100644 --- a/htdocs/hrm/class/evaluation.class.php +++ b/htdocs/hrm/class/evaluation.class.php @@ -853,7 +853,7 @@ class Evaluation extends CommonObject $this->labelStatus[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Closed'); $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated'); - $this->labelStatus[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Closed'); + $this->labelStatusShort[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Closed'); } $statusType = 'status'.$status; From f8451ffc568a7b7666658eb0e06e63c2c46b3857 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 15:52:03 +0100 Subject: [PATCH 220/816] Debug v17 --- htdocs/admin/multicurrency.php | 3 ++- htdocs/hrm/class/job.class.php | 21 ++++++++----------- htdocs/hrm/class/position.class.php | 4 +++- .../class/multicurrency.class.php | 18 ++++++++-------- htdocs/multicurrency/multicurrency_rate.php | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index 1cf838c08cb..5945ebfb5d5 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -134,7 +134,8 @@ if ($action == 'add_currency') { dolibarr_set_const($db, 'MULTICURRENCY_APP_SOURCE', GETPOST('MULTICURRENCY_APP_SOURCE', 'alpha')); //dolibarr_set_const($db, 'MULTICURRENCY_ALTERNATE_SOURCE', GETPOST('MULTICURRENCY_ALTERNATE_SOURCE', 'alpha')); } else { - $result = MultiCurrency::syncRates($conf->global->MULTICURRENCY_APP_ID); + $multiurrency = new MultiCurrency($db); + $result = $multiurrency->syncRates(getDolGlobalString('MULTICURRENCY_APP_ID')); if ($result > 0) { setEventMessages($langs->trans("CurrencyRateSyncSucceed"), null, "mesgs"); } diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php index a08e8c713ae..93950979a1a 100644 --- a/htdocs/hrm/class/job.class.php +++ b/htdocs/hrm/class/job.class.php @@ -600,30 +600,27 @@ class Job extends CommonObject } /** - * Get last job for user + * Get the last occupied position for a user * - * @param int $fk_user id of user we need to get last job - * @return mixed|string|null + * @param int $fk_user Id of user we need to get last job + * @return Position|string Last occupied position */ public function getLastJobForUser($fk_user) { - global $db; - - $j = new Job($db); - $Tab = $j->getForUser($fk_user); + $Tab = $this->getForUser($fk_user); if (empty($Tab)) return ''; - $job = array_shift($Tab); + $lastpos = array_shift($Tab); - return $job; + return $lastpos; } /** - * Get jobs for user + * Get array of occupied positions for a user * - * @param int $userid id of user we need to get job list - * @return array of jobs + * @param int $userid Id of user we need to get job list + * @return Position[] Array of occupied positions */ public function getForUser($userid) { diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index b72c11b36f6..98b5fd89be9 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -1036,6 +1036,8 @@ class Position extends CommonObject } /** + * getForUser + * * @param int $userid id of user we need to get position list * @return array|int of positions of user with for each of them the job fetched into that array */ @@ -1049,7 +1051,7 @@ class Position extends CommonObject } /** - * Create a document onto disk according to template module. + * Create a document onto disk according to template module. * * @param string $modele Force template to use ('' to not force) * @param Translate $outputlangs objet lang a utiliser pour traduction diff --git a/htdocs/multicurrency/class/multicurrency.class.php b/htdocs/multicurrency/class/multicurrency.class.php index 8b42f7cb25b..da1b9f653b3 100644 --- a/htdocs/multicurrency/class/multicurrency.class.php +++ b/htdocs/multicurrency/class/multicurrency.class.php @@ -428,7 +428,7 @@ class MultiCurrency extends CommonObject * * @param string $code currency code * @param double $rate new rate - * @return int -1 if KO, 1 if OK, 2 if label found and OK + * @return int -1 if KO, 1 if OK, 2 if label found and OK */ public function addRateFromDolibarr($code, $rate) { @@ -609,14 +609,14 @@ class MultiCurrency extends CommonObject * @param stdClass $TRate Object containing all currencies rates * @return int -1 if KO, 0 if nothing, 1 if OK */ - public static function recalculRates(&$TRate) + public function recalculRates(&$TRate) { global $conf; - if ($conf->currency != $conf->global->MULTICURRENCY_APP_SOURCE) { + if ($conf->currency != getDolGlobalString('MULTICURRENCY_APP_SOURCE')) { $alternate_source = 'USD'.$conf->currency; - if (!empty($TRate->{$alternate_source})) { - $coef = $TRate->USDUSD / $TRate->{$alternate_source}; + if (!empty($TRate->$alternate_source)) { + $coef = $TRate->USDUSD / $TRate->$alternate_source; foreach ($TRate as $attr => &$rate) { $rate *= $coef; } @@ -637,7 +637,7 @@ class MultiCurrency extends CommonObject * @param int $addifnotfound Add if not found * @return int <0 if KO, >0 if OK */ - public static function syncRates($key, $addifnotfound = 0) + public function syncRates($key, $addifnotfound = 0) { global $conf, $db, $langs; @@ -656,16 +656,16 @@ class MultiCurrency extends CommonObject if ($response->success) { $TRate = $response->quotes; - $timestamp = $response->timestamp; + //$timestamp = $response->timestamp; - if (self::recalculRates($TRate) >= 0) { + if ($this->recalculRates($TRate) >= 0) { foreach ($TRate as $currency_code => $rate) { $code = substr($currency_code, 3, 3); $obj = new MultiCurrency($db); if ($obj->fetch(null, $code) > 0) { $obj->updateRate($rate); } elseif ($addifnotfound) { - self::addRateFromDolibarr($code, $rate); + $this->addRateFromDolibarr($code, $rate); } } } diff --git a/htdocs/multicurrency/multicurrency_rate.php b/htdocs/multicurrency/multicurrency_rate.php index 03e5e09334a..8b9bbf4eef6 100644 --- a/htdocs/multicurrency/multicurrency_rate.php +++ b/htdocs/multicurrency/multicurrency_rate.php @@ -271,7 +271,7 @@ if (!in_array($action, array("updateRate", "deleteRate"))) { print ' '.$langs->trans('Date').''; print ' '; - print $form->selectDate($dateinput, 'dateinput', 0, 0, 1); + print $form->selectDate($dateinput, 'dateinput', 0, 0, 1, '', 1, 1); print ''; print ' '.$langs->trans('Currency').''; From 7d433e43fac407083b508e98b77ec6e7feaacb16 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 16:24:32 +0100 Subject: [PATCH 221/816] Add hooks on payment pages --- htdocs/core/class/hookmanager.class.php | 1 + htdocs/core/lib/payments.lib.php | 11 +++++++++-- htdocs/public/payment/newpayment.php | 8 +------- htdocs/public/payment/paymentok.php | 23 ++++++++++++++++++++--- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 191887e1725..71a92ebb6b1 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -197,6 +197,7 @@ class HookManager 'getFormatedSupplierRef', 'getIdProfUrl', 'getInputIdProf', + 'isPaymentOK', 'menuDropdownQuickaddItems', 'menuLeftMenuItems', 'moveUploadedFile', diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 44691f7c2c4..d5ddb158d6d 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -146,7 +146,7 @@ function payment_supplier_prepare_head(Paiement $object) */ function getValidOnlinePaymentMethods($paymentmethod = '') { - global $conf, $langs; + global $conf, $langs, $hookmanager, $action; $validpaymentmethod = array(); @@ -162,8 +162,15 @@ function getValidOnlinePaymentMethods($paymentmethod = '') $langs->load("stripe"); $validpaymentmethod['stripe'] = 'valid'; } - // TODO Add trigger + // This hook is used to complete the $validpaymentmethod array so an external payment modules + // can add its own key (ie 'payzen' for Payzen, ...) + $parameters = [ + 'paymentmethod' => $paymentmethod, + 'validpaymentmethod' => &$validpaymentmethod + ]; + $tmpobject = new stdClass(); + $hookmanager->executeHooks('doValidatePayment', $parameters, $tmpobject, $action); return $validpaymentmethod; } diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index e9823f2d0f7..c4b2d502d3d 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -281,15 +281,9 @@ if ((empty($paymentmethod) || $paymentmethod == 'stripe') && isModEnabled('strip } // Initialize $validpaymentmethod +// The list can be complete by the hook 'doValidatePayment' executed inside getValidOnlinePaymentMethods() $validpaymentmethod = getValidOnlinePaymentMethods($paymentmethod); -// This hook is used to push to $validpaymentmethod by external payment modules (ie Payzen, ...) -$parameters = [ - 'paymentmethod' => $paymentmethod, - 'validpaymentmethod' => &$validpaymentmethod -]; -$reshook = $hookmanager->executeHooks('doValidatePayment', $parameters, $object, $action); - // Check security token $tmpsource = $source; if ($tmpsource == 'membersubscription') { diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 6d50d1c8c76..3bfdfc5f089 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -54,13 +54,14 @@ if (is_numeric($entity)) { require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php'; -require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorbooth.class.php'; - if (isModEnabled('paypal')) { require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php'; require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php'; } +// Hook to be used by external payment modules (ie Payzen, ...) +include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; +$hookmanager = new HookManager($db); +$hookmanager->initHooks(array('newpayment')); $langs->loadLangs(array("main", "other", "dict", "bills", "companies", "paybox", "paypal")); @@ -337,6 +338,16 @@ if (isModEnabled('stripe')) { } } +// Check status of the object to verify if it is paid by external payment modules +$action = ''; +$parameters = [ + 'paymentmethod' => $paymentmethod, +]; +$reshook = $hookmanager->executeHooks('isPaymentOK', $parameters, $object, $action); +if ($reshook >= 0) { + $ispaymentok = $hookmanager->resArray['ispaymentok']; +} + // If data not provided from back url, search them into the session env if (empty($ipaddress)) { @@ -1142,6 +1153,8 @@ if ($ispaymentok) { // (we need first that the donation module is able to generate a pdf document for the cerfa with pre filled content) } elseif (array_key_exists('ATT', $tmptag) && $tmptag['ATT'] > 0) { // Record payment for registration to an event for an attendee + require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php'; + require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorbooth.class.php'; include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $object = new Facture($db); $result = $object->fetch($ref); @@ -1355,6 +1368,8 @@ if ($ispaymentok) { } } elseif (array_key_exists('BOO', $tmptag) && $tmptag['BOO'] > 0) { // Record payment for booth or conference + require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php'; + require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorbooth.class.php'; include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $object = new Facture($db); $result = $object->fetch($ref); @@ -1461,6 +1476,8 @@ if ($ispaymentok) { if (!$error) { // Putting the booth to "suggested" state + require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php'; + require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorbooth.class.php'; $booth = new ConferenceOrBooth($db); $resultbooth = $booth->fetch((int) $tmptag['BOO']); if ($resultbooth < 0) { From 65a2093cd13c945efe82ecd46df178bb1e998214 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 16:48:40 +0100 Subject: [PATCH 222/816] Fix regression --- htdocs/core/lib/functions.lib.php | 12 ++++++------ test/phpunit/FunctionsLibTest.php | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 6241eaaa8b1..977342b1457 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -340,13 +340,13 @@ function getBrowserInfo($user_agent) $reg = array(); if (preg_match('/firefox(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'firefox'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/edge(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'edge'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/chrome(\/|\s)([\d\.]+)/i', $user_agent, $reg)) { $name = 'chrome'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/chrome/i', $user_agent, $reg)) { // we can have 'chrome (Mozilla...) chrome x.y' in one string $name = 'chrome'; @@ -356,11 +356,11 @@ function getBrowserInfo($user_agent) $name = 'epiphany'; } elseif (preg_match('/safari(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'safari'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/opera(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { // Safari is often present in string for mobile but its not. $name = 'opera'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/(MSIE\s([0-9]+\.[0-9]))|.*(Trident\/[0-9]+.[0-9];.*rv:([0-9]+\.[0-9]+))/i', $user_agent, $reg)) { $name = 'ie'; $version = end($reg); @@ -371,7 +371,7 @@ function getBrowserInfo($user_agent) } elseif (preg_match('/l[iy]n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) { // MS products at end $name = 'lynxlinks'; - $version = $reg[4]; + $version = empty($reg[3]) ? '' : $reg[3]; } if ($tablet) { diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index ef5507d8601..370a498ad3a 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -443,10 +443,11 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase $this->assertEquals('tablet', $tmp['layout']); $this->assertEquals('iphone', $tmp['phone']); - //iPad + //Lynx $user_agent = 'Lynx/2.8.8dev.3 libwww‑FM/2.14 SSL‑MM/1.4.1'; $tmp=getBrowserInfo($user_agent); $this->assertEquals('lynxlinks', $tmp['browsername']); + $this->assertEquals('2.8.8', $tmp['browserversion']); $this->assertEquals('unknown', $tmp['browseros']); $this->assertEquals('classic', $tmp['layout']); } From 2970f039dd966b2c7d5e5105fd3ec3b38a1edec8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 16:52:23 +0100 Subject: [PATCH 223/816] Fix warning --- htdocs/core/lib/functions.lib.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 5b791594fea..4724bf85d50 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -340,13 +340,13 @@ function getBrowserInfo($user_agent) $reg = array(); if (preg_match('/firefox(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'firefox'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/edge(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'edge'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/chrome(\/|\s)([\d\.]+)/i', $user_agent, $reg)) { $name = 'chrome'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/chrome/i', $user_agent, $reg)) { // we can have 'chrome (Mozilla...) chrome x.y' in one string $name = 'chrome'; @@ -356,11 +356,11 @@ function getBrowserInfo($user_agent) $name = 'epiphany'; } elseif (preg_match('/safari(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'safari'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/opera(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { // Safari is often present in string for mobile but its not. $name = 'opera'; - $version = $reg[2]; + $version = empty($reg[2]) ? '' : $reg[2]; } elseif (preg_match('/(MSIE\s([0-9]+\.[0-9]))|.*(Trident\/[0-9]+.[0-9];.*rv:([0-9]+\.[0-9]+))/i', $user_agent, $reg)) { $name = 'ie'; $version = end($reg); @@ -368,10 +368,10 @@ function getBrowserInfo($user_agent) // MS products at end $name = 'ie'; $version = end($reg); - } elseif (preg_match('/l(i|y)n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) { + } elseif (preg_match('/l[iy]n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) { // MS products at end $name = 'lynxlinks'; - $version = $reg[4]; + $version = empty($reg[3]) ? '' : $reg[3]; } if ($tablet) { From 57358b618b8f46535ed7e434cfd9e105207434e8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 17:08:10 +0100 Subject: [PATCH 224/816] Clean code --- htdocs/core/modules/action/modules_action.php | 2 -- htdocs/core/modules/asset/modules_asset.php | 2 -- htdocs/core/modules/bank/modules_bank.php | 2 -- htdocs/core/modules/bom/modules_bom.php | 2 -- htdocs/core/modules/cheque/modules_chequereceipts.php | 2 -- htdocs/core/modules/commande/modules_commande.php | 2 -- htdocs/core/modules/contract/modules_contract.php | 2 -- htdocs/core/modules/delivery/modules_delivery.php | 2 -- htdocs/core/modules/dons/modules_don.php | 2 -- htdocs/core/modules/expedition/modules_expedition.php | 2 -- .../modules/expensereport/modules_expensereport.php | 2 -- htdocs/core/modules/export/modules_export.php | 8 +++----- htdocs/core/modules/facture/modules_facture.php | 2 -- htdocs/core/modules/fichinter/modules_fichinter.php | 2 -- htdocs/core/modules/holiday/modules_holiday.php | 2 -- htdocs/core/modules/hrm/modules_evaluation.php | 2 -- htdocs/core/modules/import/modules_import.php | 8 +++----- htdocs/core/modules/member/modules_cards.php | 2 -- htdocs/core/modules/member/modules_member.class.php | 1 - htdocs/core/modules/movement/modules_movement.php | 2 -- htdocs/core/modules/mrp/modules_mo.php | 2 -- htdocs/core/modules/printsheet/modules_labels.php | 2 -- .../product_batch/modules_product_batch.class.php | 2 -- htdocs/core/modules/project/modules_project.php | 2 -- htdocs/core/modules/project/task/modules_task.php | 2 -- .../propale/doc/doc_generic_proposal_odt.modules.php | 8 ++++---- htdocs/core/modules/propale/modules_propale.php | 2 -- htdocs/core/modules/reception/modules_reception.php | 2 -- htdocs/core/modules/societe/modules_societe.class.php | 1 - htdocs/core/modules/stock/doc/pdf_standard.modules.php | 2 +- htdocs/core/modules/stock/modules_stock.php | 2 -- .../modules/stocktransfer/modules_stocktransfer.php | 2 -- .../supplier_invoice/modules_facturefournisseur.php | 2 -- .../supplier_order/modules_commandefournisseur.php | 2 -- .../supplier_payment/modules_supplier_payment.php | 2 -- .../supplier_proposal/modules_supplier_proposal.php | 2 -- htdocs/core/modules/ticket/modules_ticket.php | 2 -- htdocs/core/modules/user/modules_user.class.php | 2 -- .../core/modules/usergroup/modules_usergroup.class.php | 2 -- .../core/modules/workstation/modules_workstation.php | 2 -- htdocs/exports/export.php | 2 +- htdocs/exports/index.php | 2 +- htdocs/imports/import.php | 10 +++++----- htdocs/imports/index.php | 2 +- qodana.yaml | 1 + 45 files changed, 20 insertions(+), 93 deletions(-) diff --git a/htdocs/core/modules/action/modules_action.php b/htdocs/core/modules/action/modules_action.php index b496e32f5e1..1681d1f5100 100644 --- a/htdocs/core/modules/action/modules_action.php +++ b/htdocs/core/modules/action/modules_action.php @@ -44,8 +44,6 @@ abstract class ModeleAction extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'action'; $list = array(); diff --git a/htdocs/core/modules/asset/modules_asset.php b/htdocs/core/modules/asset/modules_asset.php index 0b90eab00e3..c9b64e0180f 100644 --- a/htdocs/core/modules/asset/modules_asset.php +++ b/htdocs/core/modules/asset/modules_asset.php @@ -84,8 +84,6 @@ abstract class ModelePDFAsset extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'asset'; $list = array(); diff --git a/htdocs/core/modules/bank/modules_bank.php b/htdocs/core/modules/bank/modules_bank.php index 70f6717d0c7..cfe7d406248 100644 --- a/htdocs/core/modules/bank/modules_bank.php +++ b/htdocs/core/modules/bank/modules_bank.php @@ -48,8 +48,6 @@ abstract class ModeleBankAccountDoc extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'bankaccount'; $list = array(); diff --git a/htdocs/core/modules/bom/modules_bom.php b/htdocs/core/modules/bom/modules_bom.php index 4c58e57c546..64fc9502d26 100644 --- a/htdocs/core/modules/bom/modules_bom.php +++ b/htdocs/core/modules/bom/modules_bom.php @@ -50,8 +50,6 @@ abstract class ModelePDFBom extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'bom'; $list = array(); diff --git a/htdocs/core/modules/cheque/modules_chequereceipts.php b/htdocs/core/modules/cheque/modules_chequereceipts.php index 519b13db443..45e18a12734 100644 --- a/htdocs/core/modules/cheque/modules_chequereceipts.php +++ b/htdocs/core/modules/cheque/modules_chequereceipts.php @@ -146,8 +146,6 @@ abstract class ModeleChequeReceipts extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'chequereceipt'; $list = array(); diff --git a/htdocs/core/modules/commande/modules_commande.php b/htdocs/core/modules/commande/modules_commande.php index 055286ddf37..d6ecda2b2e7 100644 --- a/htdocs/core/modules/commande/modules_commande.php +++ b/htdocs/core/modules/commande/modules_commande.php @@ -51,8 +51,6 @@ abstract class ModelePDFCommandes extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'order'; $list = array(); diff --git a/htdocs/core/modules/contract/modules_contract.php b/htdocs/core/modules/contract/modules_contract.php index 8e296f626fb..577ec4be5d9 100644 --- a/htdocs/core/modules/contract/modules_contract.php +++ b/htdocs/core/modules/contract/modules_contract.php @@ -54,8 +54,6 @@ abstract class ModelePDFContract extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'contract'; $list = array(); diff --git a/htdocs/core/modules/delivery/modules_delivery.php b/htdocs/core/modules/delivery/modules_delivery.php index 66e9727bc7b..9f7b6805f73 100644 --- a/htdocs/core/modules/delivery/modules_delivery.php +++ b/htdocs/core/modules/delivery/modules_delivery.php @@ -52,8 +52,6 @@ abstract class ModelePDFDeliveryOrder extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'delivery'; $list = array(); diff --git a/htdocs/core/modules/dons/modules_don.php b/htdocs/core/modules/dons/modules_don.php index 6bb78ab98ac..ca982c61a53 100644 --- a/htdocs/core/modules/dons/modules_don.php +++ b/htdocs/core/modules/dons/modules_don.php @@ -50,8 +50,6 @@ abstract class ModeleDon extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'donation'; $list = array(); diff --git a/htdocs/core/modules/expedition/modules_expedition.php b/htdocs/core/modules/expedition/modules_expedition.php index ce210d6a958..2ca5613af48 100644 --- a/htdocs/core/modules/expedition/modules_expedition.php +++ b/htdocs/core/modules/expedition/modules_expedition.php @@ -53,8 +53,6 @@ abstract class ModelePdfExpedition extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'shipping'; $list = array(); diff --git a/htdocs/core/modules/expensereport/modules_expensereport.php b/htdocs/core/modules/expensereport/modules_expensereport.php index eee2190033e..8e7718ee0d5 100644 --- a/htdocs/core/modules/expensereport/modules_expensereport.php +++ b/htdocs/core/modules/expensereport/modules_expensereport.php @@ -75,8 +75,6 @@ abstract class ModeleExpenseReport extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'expensereport'; $list = array(); diff --git a/htdocs/core/modules/export/modules_export.php b/htdocs/core/modules/export/modules_export.php index 685a4bda430..31b137f6465 100644 --- a/htdocs/core/modules/export/modules_export.php +++ b/htdocs/core/modules/export/modules_export.php @@ -28,7 +28,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; /** * Parent class for export modules */ -class ModeleExports extends CommonDocGenerator // This class can't be abstract as there is instance propreties loaded by liste_modeles +class ModeleExports extends CommonDocGenerator // This class can't be abstract as there is instance propreties loaded by listOfAvailableExportFormat { /** * @var string Error code (or message) @@ -44,7 +44,6 @@ class ModeleExports extends CommonDocGenerator // This class can't be abstrac public $libversion = array(); - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Load into memory list of available export format * @@ -52,10 +51,9 @@ class ModeleExports extends CommonDocGenerator // This class can't be abstrac * @param integer $maxfilenamelength Max length of value to show * @return array List of templates (same content than array this->driverlabel) */ - public function liste_modeles($db, $maxfilenamelength = 0) + public function listOfAvailableExportFormat($db, $maxfilenamelength = 0) { - // phpcs:enable - dol_syslog(get_class($this)."::liste_modeles"); + dol_syslog(get_class($this)."::listOfAvailableExportFormat"); $dir = DOL_DOCUMENT_ROOT."/core/modules/export/"; $handle = opendir($dir); diff --git a/htdocs/core/modules/facture/modules_facture.php b/htdocs/core/modules/facture/modules_facture.php index b0d3c4682ba..ff541550d4e 100644 --- a/htdocs/core/modules/facture/modules_facture.php +++ b/htdocs/core/modules/facture/modules_facture.php @@ -61,8 +61,6 @@ abstract class ModelePDFFactures extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'invoice'; $list = array(); diff --git a/htdocs/core/modules/fichinter/modules_fichinter.php b/htdocs/core/modules/fichinter/modules_fichinter.php index 185ef4cf73b..28b3fd265ce 100644 --- a/htdocs/core/modules/fichinter/modules_fichinter.php +++ b/htdocs/core/modules/fichinter/modules_fichinter.php @@ -51,8 +51,6 @@ abstract class ModelePDFFicheinter extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'ficheinter'; $list = array(); diff --git a/htdocs/core/modules/holiday/modules_holiday.php b/htdocs/core/modules/holiday/modules_holiday.php index 7b6e13ea992..e38801a052e 100644 --- a/htdocs/core/modules/holiday/modules_holiday.php +++ b/htdocs/core/modules/holiday/modules_holiday.php @@ -55,8 +55,6 @@ abstract class ModelePDFHoliday extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'holiday'; $list = array(); diff --git a/htdocs/core/modules/hrm/modules_evaluation.php b/htdocs/core/modules/hrm/modules_evaluation.php index a28d3f2ef9d..06276ca8474 100644 --- a/htdocs/core/modules/hrm/modules_evaluation.php +++ b/htdocs/core/modules/hrm/modules_evaluation.php @@ -49,8 +49,6 @@ abstract class ModelePDFEvaluation extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'evaluation'; $list = array(); diff --git a/htdocs/core/modules/import/modules_import.php b/htdocs/core/modules/import/modules_import.php index d875afc5c4f..fa4a5ad3692 100644 --- a/htdocs/core/modules/import/modules_import.php +++ b/htdocs/core/modules/import/modules_import.php @@ -155,18 +155,16 @@ class ModeleImports } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Charge en memoire et renvoie la liste des modeles actifs + * Load into memory list of available import format * * @param DoliDB $db Database handler * @param integer $maxfilenamelength Max length of value to show * @return array List of templates */ - public function liste_modeles($db, $maxfilenamelength = 0) + public function listOfAvailableImportFormat($db, $maxfilenamelength = 0) { - // phpcs:enable - dol_syslog(get_class($this)."::liste_modeles"); + dol_syslog(get_class($this)."::listOfAvailableImportFormat"); $dir = DOL_DOCUMENT_ROOT."/core/modules/import/"; $handle = opendir($dir); diff --git a/htdocs/core/modules/member/modules_cards.php b/htdocs/core/modules/member/modules_cards.php index b37b9144d3e..0147f42f6c7 100644 --- a/htdocs/core/modules/member/modules_cards.php +++ b/htdocs/core/modules/member/modules_cards.php @@ -51,8 +51,6 @@ class ModelePDFCards public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'member'; $list = array(); diff --git a/htdocs/core/modules/member/modules_member.class.php b/htdocs/core/modules/member/modules_member.class.php index a356c76ee7c..77ab5621915 100644 --- a/htdocs/core/modules/member/modules_member.class.php +++ b/htdocs/core/modules/member/modules_member.class.php @@ -51,7 +51,6 @@ abstract class ModelePDFMember extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - $type = 'member'; $list = array(); diff --git a/htdocs/core/modules/movement/modules_movement.php b/htdocs/core/modules/movement/modules_movement.php index 1af966faf22..a058d685114 100644 --- a/htdocs/core/modules/movement/modules_movement.php +++ b/htdocs/core/modules/movement/modules_movement.php @@ -85,8 +85,6 @@ abstract class ModelePDFMovement extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'movement'; $list = array(); diff --git a/htdocs/core/modules/mrp/modules_mo.php b/htdocs/core/modules/mrp/modules_mo.php index 1b3af7f6b8c..c178a5d3eaf 100644 --- a/htdocs/core/modules/mrp/modules_mo.php +++ b/htdocs/core/modules/mrp/modules_mo.php @@ -50,8 +50,6 @@ abstract class ModelePDFMo extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'mrp'; $list = array(); diff --git a/htdocs/core/modules/printsheet/modules_labels.php b/htdocs/core/modules/printsheet/modules_labels.php index ae4c6888a6c..b80710dc1f6 100644 --- a/htdocs/core/modules/printsheet/modules_labels.php +++ b/htdocs/core/modules/printsheet/modules_labels.php @@ -51,8 +51,6 @@ class ModelePDFLabels public function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'members_labels'; $list = array(); diff --git a/htdocs/core/modules/product_batch/modules_product_batch.class.php b/htdocs/core/modules/product_batch/modules_product_batch.class.php index 1446d20aeda..d596ffeb111 100644 --- a/htdocs/core/modules/product_batch/modules_product_batch.class.php +++ b/htdocs/core/modules/product_batch/modules_product_batch.class.php @@ -55,8 +55,6 @@ abstract class ModelePDFProductBatch extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'product_batch'; $list = array(); diff --git a/htdocs/core/modules/project/modules_project.php b/htdocs/core/modules/project/modules_project.php index 6f55426e65f..9f8e0e977c7 100644 --- a/htdocs/core/modules/project/modules_project.php +++ b/htdocs/core/modules/project/modules_project.php @@ -103,8 +103,6 @@ abstract class ModelePDFProjects extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'project'; $list = array(); diff --git a/htdocs/core/modules/project/task/modules_task.php b/htdocs/core/modules/project/task/modules_task.php index 6614369aa43..97e31d5d24c 100644 --- a/htdocs/core/modules/project/task/modules_task.php +++ b/htdocs/core/modules/project/task/modules_task.php @@ -49,8 +49,6 @@ abstract class ModelePDFTask extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'project_task'; $list = array(); diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index de6554137df..ac95786cdd2 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -190,21 +190,21 @@ class doc_generic_proposal_odt extends ModelePDFPropales if (getDolGlobalInt("MAIN_PROPAL_CHOOSE_ODT_DOCUMENT") > 0) { // Model for creation $list = ModelePDFPropales::liste_modeles($this->db); - $texte .= ''; + $texte .= '
'; $texte .= ''; - $texte .= ''; + $texte .= ''; $texte .= '"; $texte .= ''; - $texte .= ''; + $texte .= ''; $texte .= '"; $texte .= ''; - $texte .= ''; + $texte .= ''; $texte .= '"; diff --git a/htdocs/core/modules/propale/modules_propale.php b/htdocs/core/modules/propale/modules_propale.php index b58ae681ef2..f69fd5e763e 100644 --- a/htdocs/core/modules/propale/modules_propale.php +++ b/htdocs/core/modules/propale/modules_propale.php @@ -53,8 +53,6 @@ abstract class ModelePDFPropales extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'propal'; $list = array(); diff --git a/htdocs/core/modules/reception/modules_reception.php b/htdocs/core/modules/reception/modules_reception.php index f519974382b..0dba62ee646 100644 --- a/htdocs/core/modules/reception/modules_reception.php +++ b/htdocs/core/modules/reception/modules_reception.php @@ -43,8 +43,6 @@ abstract class ModelePdfReception extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'reception'; $list = array(); diff --git a/htdocs/core/modules/societe/modules_societe.class.php b/htdocs/core/modules/societe/modules_societe.class.php index a1067c14d30..105333d815b 100644 --- a/htdocs/core/modules/societe/modules_societe.class.php +++ b/htdocs/core/modules/societe/modules_societe.class.php @@ -48,7 +48,6 @@ abstract class ModeleThirdPartyDoc extends CommonDocGenerator public static function liste_modeles($dbs, $maxfilenamelength = 0) { // phpcs:enable - $type = 'company'; $list = array(); diff --git a/htdocs/core/modules/stock/doc/pdf_standard.modules.php b/htdocs/core/modules/stock/doc/pdf_standard.modules.php index ed1877ec8f7..ac0bf98b0f3 100644 --- a/htdocs/core/modules/stock/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/stock/doc/pdf_standard.modules.php @@ -402,7 +402,7 @@ class pdf_standard extends ModelePDFStock // Label $pdf->SetXY($this->posxlabel + 0.8, $curY); - $pdf->MultiCell($this->posxqty - $this->posxlabel - 0.8, 3, dol_trunc($objp->produit, 24), 0, 'L'); + $pdf->MultiCell($this->posxqty - $this->posxlabel - 0.8, 3, dol_trunc($productstatic->label, 24), 0, 'L'); // Quantity $valtoshow = price2num($objp->value, 'MS'); diff --git a/htdocs/core/modules/stock/modules_stock.php b/htdocs/core/modules/stock/modules_stock.php index 73092bb0bf6..d1dc684d1d2 100644 --- a/htdocs/core/modules/stock/modules_stock.php +++ b/htdocs/core/modules/stock/modules_stock.php @@ -75,8 +75,6 @@ abstract class ModelePDFStock extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'stock'; $list = array(); diff --git a/htdocs/core/modules/stocktransfer/modules_stocktransfer.php b/htdocs/core/modules/stocktransfer/modules_stocktransfer.php index 6c0213afb0c..2a7218543e7 100644 --- a/htdocs/core/modules/stocktransfer/modules_stocktransfer.php +++ b/htdocs/core/modules/stocktransfer/modules_stocktransfer.php @@ -50,8 +50,6 @@ abstract class ModelePDFStockTransfer extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'stocktransfer'; $list = array(); diff --git a/htdocs/core/modules/supplier_invoice/modules_facturefournisseur.php b/htdocs/core/modules/supplier_invoice/modules_facturefournisseur.php index 546596ab640..de56773eae2 100644 --- a/htdocs/core/modules/supplier_invoice/modules_facturefournisseur.php +++ b/htdocs/core/modules/supplier_invoice/modules_facturefournisseur.php @@ -51,8 +51,6 @@ abstract class ModelePDFSuppliersInvoices extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'invoice_supplier'; $list = array(); diff --git a/htdocs/core/modules/supplier_order/modules_commandefournisseur.php b/htdocs/core/modules/supplier_order/modules_commandefournisseur.php index 51c4e5f07d3..e8b66bb84cf 100644 --- a/htdocs/core/modules/supplier_order/modules_commandefournisseur.php +++ b/htdocs/core/modules/supplier_order/modules_commandefournisseur.php @@ -54,8 +54,6 @@ abstract class ModelePDFSuppliersOrders extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'order_supplier'; $list = array(); diff --git a/htdocs/core/modules/supplier_payment/modules_supplier_payment.php b/htdocs/core/modules/supplier_payment/modules_supplier_payment.php index 9409c4c688b..881d123772c 100644 --- a/htdocs/core/modules/supplier_payment/modules_supplier_payment.php +++ b/htdocs/core/modules/supplier_payment/modules_supplier_payment.php @@ -74,8 +74,6 @@ abstract class ModelePDFSuppliersPayments extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'supplier_payment'; $list = array(); diff --git a/htdocs/core/modules/supplier_proposal/modules_supplier_proposal.php b/htdocs/core/modules/supplier_proposal/modules_supplier_proposal.php index 42c935ca13c..f1fbf2f9890 100644 --- a/htdocs/core/modules/supplier_proposal/modules_supplier_proposal.php +++ b/htdocs/core/modules/supplier_proposal/modules_supplier_proposal.php @@ -53,8 +53,6 @@ abstract class ModelePDFSupplierProposal extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'supplier_proposal'; $list = array(); diff --git a/htdocs/core/modules/ticket/modules_ticket.php b/htdocs/core/modules/ticket/modules_ticket.php index 263803162fd..aaf9fb2e11b 100644 --- a/htdocs/core/modules/ticket/modules_ticket.php +++ b/htdocs/core/modules/ticket/modules_ticket.php @@ -44,8 +44,6 @@ abstract class ModelePDFTicket extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'ticket'; $list = array(); diff --git a/htdocs/core/modules/user/modules_user.class.php b/htdocs/core/modules/user/modules_user.class.php index b0142687ce5..d20e5e95eb8 100644 --- a/htdocs/core/modules/user/modules_user.class.php +++ b/htdocs/core/modules/user/modules_user.class.php @@ -55,8 +55,6 @@ abstract class ModelePDFUser extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'user'; $list = array(); diff --git a/htdocs/core/modules/usergroup/modules_usergroup.class.php b/htdocs/core/modules/usergroup/modules_usergroup.class.php index 99ee232fdf2..2c4aebe1e6f 100644 --- a/htdocs/core/modules/usergroup/modules_usergroup.class.php +++ b/htdocs/core/modules/usergroup/modules_usergroup.class.php @@ -55,8 +55,6 @@ abstract class ModelePDFUserGroup extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'group'; $list = array(); diff --git a/htdocs/core/modules/workstation/modules_workstation.php b/htdocs/core/modules/workstation/modules_workstation.php index a99dab9b17a..b72d34f5812 100644 --- a/htdocs/core/modules/workstation/modules_workstation.php +++ b/htdocs/core/modules/workstation/modules_workstation.php @@ -50,8 +50,6 @@ abstract class ModelePDFWorkstation extends CommonDocGenerator public static function liste_modeles($db, $maxfilenamelength = 0) { // phpcs:enable - global $conf; - $type = 'workstation'; $list = array(); diff --git a/htdocs/exports/export.php b/htdocs/exports/export.php index 4591ccd0bf3..f35ae3a3121 100644 --- a/htdocs/exports/export.php +++ b/htdocs/exports/export.php @@ -1187,7 +1187,7 @@ if ($step == 5 && $datatoexport) { $htmltabloflibs .= ''; $htmltabloflibs .= ''."\n"; - $liste = $objmodelexport->liste_modeles($db); + $liste = $objmodelexport->listOfAvailableExportFormat($db); $listeall = $liste; foreach ($listeall as $key => $val) { if (preg_match('/__\(Disabled\)__/', $listeall[$key])) { diff --git a/htdocs/exports/index.php b/htdocs/exports/index.php index 41d6cd18ed0..6039a9c447a 100644 --- a/htdocs/exports/index.php +++ b/htdocs/exports/index.php @@ -72,7 +72,7 @@ print ''; include_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php'; $model = new ModeleExports($db); -$liste = $model->liste_modeles($db); // This is not a static method for exports because method load non static properties +$liste = $model->listOfAvailableExportFormat($db); // This is not a static method for exports because method load non static properties foreach ($liste as $key => $val) { if (preg_match('/__\(Disabled\)__/', $liste[$key])) { diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index 579fdb74c4a..d326470aa04 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -485,7 +485,7 @@ if ($step == 2 && $datatoimport) { print ''; - $list = $objmodelimport->liste_modeles($db); + $list = $objmodelimport->listOfAvailableImportFormat($db); foreach ($list as $key) { print ''; print ''; @@ -529,7 +529,7 @@ if ($step == 3 && $datatoimport) { $param .= '&enclosure='.urlencode($enclosure); } - $list = $objmodelimport->liste_modeles($db); + $list = $objmodelimport->listOfAvailableImportFormat($db); llxHeader('', $langs->trans("NewImport"), $help_url); @@ -763,7 +763,7 @@ if ($step == 4 && $datatoimport) { //var_dump($array_match_file_to_database); $model = $format; - $list = $objmodelimport->liste_modeles($db); + $list = $objmodelimport->listOfAvailableImportFormat($db); if (empty($separator)) { $separator = (empty($conf->global->IMPORT_CSV_SEPARATOR_TO_USE) ? ',' : $conf->global->IMPORT_CSV_SEPARATOR_TO_USE); @@ -1547,7 +1547,7 @@ if ($step == 5 && $datatoimport) { } $model = $format; - $list = $objmodelimport->liste_modeles($db); + $list = $objmodelimport->listOfAvailableImportFormat($db); // Create classe to use for import $dir = DOL_DOCUMENT_ROOT."/core/modules/import/"; @@ -2010,7 +2010,7 @@ if ($step == 6 && $datatoimport) { } $model = $format; - $list = $objmodelimport->liste_modeles($db); + $list = $objmodelimport->listOfAvailableImportFormat($db); $importid = GETPOST("importid", 'alphanohtml'); diff --git a/htdocs/imports/index.php b/htdocs/imports/index.php index ac3d2b23f69..e90f58aa8e1 100644 --- a/htdocs/imports/index.php +++ b/htdocs/imports/index.php @@ -68,7 +68,7 @@ print ''; include_once DOL_DOCUMENT_ROOT.'/core/modules/import/modules_import.php'; $model = new ModeleImports(); -$list = $model->liste_modeles($db); +$list = $model->listOfAvailableImportFormat($db); foreach ($list as $key) { print ''; diff --git a/qodana.yaml b/qodana.yaml index 36c35ece4c6..49fd189e734 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -72,6 +72,7 @@ exclude: - name: PhpConditionCheckedByNextConditionInspection - name: RegExpSingleCharAlternation - name: PhpSuspiciousNameCombinationInspection + - name: PhpObjectFieldsAreOnlyWrittenInspection - name: PhpWriteAccessToReferencedArrayValueWithoutUnsetInspection \ No newline at end of file From 97222603c10c97396c450a6cb933c081d5c8dc3e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 17:14:58 +0100 Subject: [PATCH 225/816] Debug v17 --- htdocs/modulebuilder/index.php | 6 +++--- htdocs/stripe/admin/stripe.php | 4 ++-- htdocs/takepos/admin/terminal.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 8b87d84c10e..a6f3431bd2e 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1731,9 +1731,9 @@ if ($dirins && $action == 'confirm_deleteobject' && $objectname) { ); $resultko = 0; - foreach ($filetodelete as $filetodelete) { - $resulttmp = dol_delete_file($dir.'/'.$filetodelete, 0, 0, 1); - $resulttmp = dol_delete_file($dir.'/'.$filetodelete.'.back', 0, 0, 1); + foreach ($filetodelete as $tmpfiletodelete) { + $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete, 0, 0, 1); + $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete.'.back', 0, 0, 1); if (!$resulttmp) { $resultko++; } diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 6cbefc14185..1c5a507b619 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -420,8 +420,8 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code $location = array(); $location[""] = $langs->trans("NotDefined"); - foreach ($locations as $locations) { - $location[$locations->id] = $locations->display_name; + foreach ($locations as $tmplocation) { + $location[$tmplocation->id] = $tmplocation->display_name; } print $form->selectarray("STRIPE_LOCATION", $location, getDolGlobalString('STRIPE_LOCATION')); print ''; diff --git a/htdocs/takepos/admin/terminal.php b/htdocs/takepos/admin/terminal.php index fe03139c8a3..7fc2d60544a 100644 --- a/htdocs/takepos/admin/terminal.php +++ b/htdocs/takepos/admin/terminal.php @@ -219,8 +219,8 @@ if (isModEnabled("banque")) { $reader = array(); $reader[""] = $langs->trans("NoReader"); - foreach ($readers as $readers) { - $reader[$reader->id] = $readers->label.' ('.$readers->status.')'; + foreach ($readers as $tmpreader) { + $reader[$tmpreader->id] = $tmpreader->label.' ('.$tmpreader->status.')'; } print $form->selectarray('CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse, $reader, $conf->global->{'CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse}); print ''; From 1b1e4e188e439ba2a6b417264182bcf379e03769 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 17:17:21 +0100 Subject: [PATCH 226/816] Debug v17 --- htdocs/core/class/fileupload.class.php | 2 +- qodana.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/fileupload.class.php b/htdocs/core/class/fileupload.class.php index b1e085fbff7..a3fb3505fba 100644 --- a/htdocs/core/class/fileupload.class.php +++ b/htdocs/core/class/fileupload.class.php @@ -259,7 +259,7 @@ class FileUpload /** * getFileObjects * - * @return void + * @return array Array of objects */ protected function getFileObjects() { diff --git a/qodana.yaml b/qodana.yaml index 49fd189e734..5b835ab446d 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -72,7 +72,7 @@ exclude: - name: PhpConditionCheckedByNextConditionInspection - name: RegExpSingleCharAlternation - name: PhpSuspiciousNameCombinationInspection - - name: PhpObjectFieldsAreOnlyWrittenInspection + - name: PhpObjectFieldsAreOnlyWrittenInspection - name: PhpWriteAccessToReferencedArrayValueWithoutUnsetInspection \ No newline at end of file From b70c6faef299c1418b984497ae2272d471131644 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 17:19:05 +0100 Subject: [PATCH 227/816] Clean code --- .../modules/supplier_payment/modules_supplier_payment.php | 7 +++++-- htdocs/ftp/index.php | 8 ++++---- htdocs/index.php | 2 +- qodana.yaml | 3 ++- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/htdocs/core/modules/supplier_payment/modules_supplier_payment.php b/htdocs/core/modules/supplier_payment/modules_supplier_payment.php index 881d123772c..93195edec24 100644 --- a/htdocs/core/modules/supplier_payment/modules_supplier_payment.php +++ b/htdocs/core/modules/supplier_payment/modules_supplier_payment.php @@ -17,6 +17,8 @@ */ require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; + + /** * Parent class for supplier invoices models */ @@ -85,8 +87,9 @@ abstract class ModelePDFSuppliersPayments extends CommonDocGenerator } /** - * \class ModeleNumRefSupplierPayments - * \brief Payment numbering references mother class + * ModeleNumRefSupplierPayments + * + * Payment numbering references mother class */ abstract class ModeleNumRefSupplierPayments diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index af48f0f8348..633cb6fa5ce 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -282,7 +282,7 @@ if ($action == 'download') { $newsection = $section; - $result = dol_ftp_get($connect_id, $localfile, $file, $newsection); + $result = dol_ftp_get($conn_id, $localfile, $file, $newsection); if ($result) { @@ -306,9 +306,9 @@ if ($action == 'download') { header('Content-Type: '.$type); } if ($attachment) { - header('Content-Disposition: attachment; filename="'.$filename.'"'); + header('Content-Disposition: attachment; filename="'.$file.'"'); } else { - header('Content-Disposition: inline; filename="'.$filename.'"'); + header('Content-Disposition: inline; filename="'.$file.'"'); } // Ajout directives pour resoudre bug IE @@ -319,7 +319,7 @@ if ($action == 'download') { exit; } else { - setEventMessages($langs->transnoentitiesnoconv('FailedToGetFile', $remotefile), null, 'errors'); + setEventMessages($langs->transnoentitiesnoconv('FailedToGetFile', $file), null, 'errors'); } } else { dol_print_error('', $mesg); diff --git a/htdocs/index.php b/htdocs/index.php index e0001adba5e..15c41e7ff50 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -119,7 +119,7 @@ if (empty($conf->global->MAIN_REMOVE_INSTALL_WARNING)) { } // Conf files must be in read only mode - if (is_writable($conffile)) { + if (is_writable($conffile)) { // $conffile is defined into filefunc.inc.php $langs->load("errors"); //$langs->load("other"); //if (!empty($message)) $message.='
'; diff --git a/qodana.yaml b/qodana.yaml index 5b835ab446d..75ab2315e9a 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -73,6 +73,7 @@ exclude: - name: RegExpSingleCharAlternation - name: PhpSuspiciousNameCombinationInspection - name: PhpObjectFieldsAreOnlyWrittenInspection + - name: PhpMissingParentConstructorInspection - name: PhpWriteAccessToReferencedArrayValueWithoutUnsetInspection - + \ No newline at end of file From d1934bfded6f1ef8ff7c75487746c72f19e86dc6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Dec 2022 17:29:57 +0100 Subject: [PATCH 228/816] Debug v17 --- htdocs/compta/localtax/index.php | 12 ++---------- htdocs/compta/tva/index.php | 10 ---------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/htdocs/compta/localtax/index.php b/htdocs/compta/localtax/index.php index ad0b86a161d..fb96e766945 100644 --- a/htdocs/compta/localtax/index.php +++ b/htdocs/compta/localtax/index.php @@ -18,11 +18,13 @@ * along with this program. If not, see . */ + /** * \file htdocs/compta/localtax/index.php * \ingroup tax * \brief Index page of IRPF reports */ + require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/report.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/tax.lib.php'; @@ -441,16 +443,6 @@ while ((($y < $yend) || ($y == $yend && $m <= $mend)) && $mcursor < 1000) { // $ $hookmanager->initHooks(array('externalbalance')); $reshook = $hookmanager->executeHooks('addVatLine', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks - if (!is_array($x_coll) && $coll_listbuy == -1) { - $langs->load("errors"); - print '
'; - break; - } - if (!is_array($x_paye) && $coll_listbuy == -2) { - print ''; - break; - } - print ''; print ''; diff --git a/htdocs/compta/tva/index.php b/htdocs/compta/tva/index.php index f0efe305d8c..5c0d6930475 100644 --- a/htdocs/compta/tva/index.php +++ b/htdocs/compta/tva/index.php @@ -389,16 +389,6 @@ if ($refresh === true) { $hookmanager->initHooks(array('externalbalance')); $reshook = $hookmanager->executeHooks('addVatLine', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks - if (!is_array($x_coll) && $coll_listbuy == -1) { - $langs->load("errors"); - print ''; - break; - } - if (!is_array($x_paye) && $coll_listbuy == -2) { - print ''; - break; - } - print ''; print ''; From da4567c87524c96337cfa89588dfe3a689ac7c2a Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sun, 1 Jan 2023 15:05:04 +0100 Subject: [PATCH 229/816] Set $remise_percent to 0, if GETPOST is empty. --- htdocs/commande/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 77a59c159ff..996beecab61 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1106,7 +1106,7 @@ if (empty($reshook)) { $special_code = 3; } - $remise_percent = price2num(GETPOST('remise_percent'), '', 2); + $remise_percent = GETPOST('remise_percent') != '' ? price2num(GETPOST('remise_percent'), '', 2) : 0; // Check minimum price $productid = GETPOST('productid', 'int'); From 0915374fa126efda9260bf898e714eb7f65bda22 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 1 Jan 2023 16:54:36 +0100 Subject: [PATCH 230/816] Fix php 8 errors --- htdocs/stripe/class/stripe.class.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 43f940acdee..53adfdbe85b 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -378,7 +378,7 @@ class Stripe extends CommonObject $paymentintent = null; - if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND) && empty($conf->global->STRIPE_CARD_PRESENT)) { + if (is_object($object) && getDolGlobalInt('STRIPE_REUSE_EXISTING_INTENT_IF_FOUND') && !getDolGlobalInt('STRIPE_CARD_PRESENT')) { // Warning. If a payment was tried and failed, a payment intent was created. // But if we change something on object to pay (amount or other that does not change the idempotency key), reusing same payment intent is not allowed by Stripe. // Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed by Stripe after a delay), Stripe will @@ -435,26 +435,26 @@ class Stripe extends CommonObject // list of payment method types $paymentmethodtypes = array("card"); $descriptor = dol_trunc($tag, 10, 'right', 'UTF-8', 1); - if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT)) { + if (getDolGlobalInt('STRIPE_SEPA_DIRECT_DEBIT')) { $paymentmethodtypes[] = "sepa_debit"; //&& ($object->thirdparty->isInEEC()) //$descriptor = preg_replace('/ref=[^:=]+/', '', $descriptor); // Clean ref } - if (!empty($conf->global->STRIPE_KLARNA)) { + if (getDolGlobalInt('STRIPE_KLARNA')) { $paymentmethodtypes[] = "klarna"; } - if (!empty($conf->global->STRIPE_BANCONTACT)) { + if (getDolGlobalInt('STRIPE_BANCONTACT')) { $paymentmethodtypes[] = "bancontact"; } - if (!empty($conf->global->STRIPE_IDEAL)) { + if (getDolGlobalInt('STRIPE_IDEAL')) { $paymentmethodtypes[] = "ideal"; } - if (!empty($conf->global->STRIPE_GIROPAY)) { + if (getDolGlobalInt('STRIPE_GIROPAY')) { $paymentmethodtypes[] = "giropay"; } - if (!empty($conf->global->STRIPE_SOFORT)) { + if (getDolGlobalInt('STRIPE_SOFORT')) { $paymentmethodtypes[] = "sofort"; } - if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') { + if (getDolGlobalInt('STRIPE_CARD_PRESENT') && $mode == 'terminal') { $paymentmethodtypes = array("card_present"); } @@ -484,13 +484,13 @@ class Stripe extends CommonObject //$dataforintent["setup_future_usage"] = "off_session"; $dataforintent["off_session"] = true; } - if (!empty($conf->global->STRIPE_GIROPAY)) { + if (getDolGlobalInt('STRIPE_GIROPAY')) { unset($dataforintent['setup_future_usage']); } - if (!empty($conf->global->STRIPE_KLARNA)) { + if (getDolGlobalInt('STRIPE_KLARNA')) { unset($dataforintent['setup_future_usage']); } - if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') { + if (getDolGlobalInt('STRIPE_CARD_PRESENT') && $mode == 'terminal') { unset($dataforintent['setup_future_usage']); $dataforintent["capture_method"] = "manual"; $dataforintent["confirmation_method"] = "manual"; @@ -500,7 +500,7 @@ class Stripe extends CommonObject $description .= ' - '.$payment_method; } - if ($conf->entity != $conf->global->STRIPECONNECT_PRINCIPAL && $stripefee > 0) { + if ($conf->entity != getDolGlobalInt('STRIPECONNECT_PRINCIPAL') && $stripefee > 0) { $dataforintent["application_fee_amount"] = $stripefee; } if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) { From 5c8dc4ed58e1a3231dc1572b24e188ef234485e5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 1 Jan 2023 23:50:37 +0100 Subject: [PATCH 231/816] Fix warning --- .../core/boxes/box_graph_invoices_peryear.php | 4 ++-- htdocs/core/modules/modLoan.class.php | 2 +- htdocs/don/class/don.class.php | 8 ++++---- htdocs/expedition/class/expedition.class.php | 19 +------------------ htdocs/reception/class/reception.class.php | 19 ------------------- qodana.yaml | 2 +- 6 files changed, 9 insertions(+), 45 deletions(-) diff --git a/htdocs/core/boxes/box_graph_invoices_peryear.php b/htdocs/core/boxes/box_graph_invoices_peryear.php index 5a9b84829f2..9ea2fe5a130 100644 --- a/htdocs/core/boxes/box_graph_invoices_peryear.php +++ b/htdocs/core/boxes/box_graph_invoices_peryear.php @@ -142,7 +142,7 @@ class box_graph_invoices_peryear extends ModeleBoxes $px2->SetData($data2); unset($data2); $i = $startyear; - $legend = array(); + /*$legend = array(); while ($i <= $endyear) { if ($startmonth != 1) { $legend[] = sprintf("%d/%d", $i - 2001, $i - 2000); @@ -150,7 +150,7 @@ class box_graph_invoices_peryear extends ModeleBoxes $legend[] = $i; } $i++; - } + }*/ $px2->SetLegend([$langs->trans("AmountOfBillsHT")]); $px2->SetMaxValue($px2->GetCeilMaxValue()); $px2->SetWidth($WIDTH); diff --git a/htdocs/core/modules/modLoan.class.php b/htdocs/core/modules/modLoan.class.php index 7f2850b075a..36919bc38af 100644 --- a/htdocs/core/modules/modLoan.class.php +++ b/htdocs/core/modules/modLoan.class.php @@ -82,7 +82,7 @@ class modLoan extends DolibarrModules "chaine", "6611" ); - $this->const[1] = array( + $this->const[2] = array( "LOAN_ACCOUNTING_ACCOUNT_INSURANCE", "chaine", "6162" diff --git a/htdocs/don/class/don.class.php b/htdocs/don/class/don.class.php index 333f9673175..158c96cb441 100644 --- a/htdocs/don/class/don.class.php +++ b/htdocs/don/class/don.class.php @@ -206,7 +206,7 @@ class Don extends CommonObject */ public function initAsSpecimen() { - global $conf, $user, $langs; + global $conf; $now = dol_now(); @@ -224,10 +224,10 @@ class Don extends CommonObject $num_socs = $this->db->num_rows($resql); $i = 0; while ($i < $num_socs) { - $i++; - $row = $this->db->fetch_row($resql); $socids[$i] = $row[0]; + + $i++; } } @@ -237,7 +237,7 @@ class Don extends CommonObject $this->specimen = 1; $this->lastname = 'Doe'; $this->firstname = 'John'; - $this->socid = 1; + $this->socid = empty($socids[0]) ? 0 : $socids[0]; $this->date = $now; $this->date_valid = $now; $this->amount = 100.90; diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index bb2954daa60..dd6dfee55b1 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -1911,23 +1911,6 @@ class Expedition extends CommonObject dol_syslog(get_class($this)."::initAsSpecimen"); - // Load array of products prodids - $num_prods = 0; - $prodids = array(); - $sql = "SELECT rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."product"; - $sql .= " WHERE entity IN (".getEntity('product').")"; - $resql = $this->db->query($sql); - if ($resql) { - $num_prods = $this->db->num_rows($resql); - $i = 0; - while ($i < $num_prods) { - $i++; - $row = $this->db->fetch_row($resql); - $prodids[$i] = $row[0]; - } - } - $order = new Commande($this->db); $order->initAsSpecimen(); @@ -1940,7 +1923,7 @@ class Expedition extends CommonObject $this->date = $now; $this->date_creation = $now; $this->date_valid = $now; - $this->date_delivery = $now; + $this->date_delivery = $now + 24 * 3600; $this->date_expedition = $now + 24 * 3600; $this->entrepot_id = 0; diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php index 96b275bfb26..03ed28a2200 100644 --- a/htdocs/reception/class/reception.class.php +++ b/htdocs/reception/class/reception.class.php @@ -1348,25 +1348,6 @@ class Reception extends CommonObject dol_syslog(get_class($this)."::initAsSpecimen"); - // Load array of products prodids - $num_prods = 0; - $prodids = array(); - $sql = "SELECT rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."product"; - $sql .= " WHERE entity IN (".getEntity('product').")"; - $sql .= $this->db->plimit(100); - - $resql = $this->db->query($sql); - if ($resql) { - $num_prods = $this->db->num_rows($resql); - $i = 0; - while ($i < $num_prods) { - $i++; - $row = $this->db->fetch_row($resql); - $prodids[$i] = $row[0]; - } - } - $order = new CommandeFournisseur($this->db); $order->initAsSpecimen(); diff --git a/qodana.yaml b/qodana.yaml index 75ab2315e9a..7347f4dd50b 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -75,5 +75,5 @@ exclude: - name: PhpObjectFieldsAreOnlyWrittenInspection - name: PhpMissingParentConstructorInspection - name: PhpWriteAccessToReferencedArrayValueWithoutUnsetInspection - + - name: PhpArrayUsedOnlyForWriteInspection \ No newline at end of file From ac75406e357ce5b4cddf590a26dd0936898d4faa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 1 Jan 2023 23:55:59 +0100 Subject: [PATCH 232/816] Clean code --- htdocs/fichinter/card-rec.php | 2 +- htdocs/fichinter/class/fichinterrec.class.php | 11 ++++------- qodana.yaml | 3 +++ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/fichinter/card-rec.php b/htdocs/fichinter/card-rec.php index f2bd0bac8a3..22f77546090 100644 --- a/htdocs/fichinter/card-rec.php +++ b/htdocs/fichinter/card-rec.php @@ -234,7 +234,7 @@ if ($action == 'add') { } elseif ($action == 'delete' && $user->rights->ficheinter->supprimer) { // delete modele $object->fetch($id); - $object->delete(); + $object->delete($user); $id = 0; header('Location: '.$_SERVER["PHP_SELF"]); exit; diff --git a/htdocs/fichinter/class/fichinterrec.class.php b/htdocs/fichinter/class/fichinterrec.class.php index fa3b700b1fd..2f4ca02d3c7 100644 --- a/htdocs/fichinter/class/fichinterrec.class.php +++ b/htdocs/fichinter/class/fichinterrec.class.php @@ -411,16 +411,13 @@ class FichinterRec extends Fichinter /** * Delete template fichinter rec * - * @param int $rowid Id of fichinter rec to delete. If empty, we delete current instance of fichinter rec - * @param int $notrigger 1=Does not execute triggers, 0= execute triggers - * @param int $idwarehouse Id warehouse to use for stock change. + * @param User $user Object user who delete + * @param int $notrigger Disable trigger * @return int <0 if KO, >0 if OK */ - public function delete($rowid = 0, $notrigger = 0, $idwarehouse = -1) + public function delete(User $user, $notrigger = 0) { - if (empty($rowid)) { - $rowid = $this->id; - } + $rowid = $this->id; dol_syslog(get_class($this)."::delete rowid=".$rowid, LOG_DEBUG); diff --git a/qodana.yaml b/qodana.yaml index 7347f4dd50b..872b043013b 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -76,4 +76,7 @@ exclude: - name: PhpMissingParentConstructorInspection - name: PhpWriteAccessToReferencedArrayValueWithoutUnsetInspection - name: PhpArrayUsedOnlyForWriteInspection + - name: PhpArrayIndexImmediatelyRewrittenInspection + - name: PhpParameterNameChangedDuringInheritanceInspection + - name: PhpDuplicateSwitchCaseBodyInspection \ No newline at end of file From 7e22e1e7b490f7c3862602b2afa2870359497206 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 00:02:34 +0100 Subject: [PATCH 233/816] Clean php --- .github/workflows/code_quality.yml | 1 + htdocs/mailmanspip/class/mailmanspip.class.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index 2b8ea0b3551..700d9fe64bf 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -16,6 +16,7 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 + php-version: '7.1' - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2022.3.0 env: diff --git a/htdocs/mailmanspip/class/mailmanspip.class.php b/htdocs/mailmanspip/class/mailmanspip.class.php index 46701a459a6..6bc34977e4e 100644 --- a/htdocs/mailmanspip/class/mailmanspip.class.php +++ b/htdocs/mailmanspip/class/mailmanspip.class.php @@ -105,13 +105,13 @@ class MailmanSpip */ public function connectSpip() { - $resource = getDoliDBInstance('mysql', ADHERENT_SPIP_SERVEUR, ADHERENT_SPIP_USER, ADHERENT_SPIP_PASS, ADHERENT_SPIP_DB, ADHERENT_SPIP_PORT); + $resource = getDoliDBInstance('mysql', getDolGlobalString('ADHERENT_SPIP_SERVEUR'), getDolGlobalString('ADHERENT_SPIP_USER'), getDolGlobalString('ADHERENT_SPIP_PASS'), getDolGlobalString('ADHERENT_SPIP_DB'), getDolGlobalString('ADHERENT_SPIP_PORT')); if ($resource->ok) { return $resource; } - dol_syslog('Error when connecting to SPIP '.ADHERENT_SPIP_SERVEUR.' '.ADHERENT_SPIP_USER.' '.ADHERENT_SPIP_PASS.' '.ADHERENT_SPIP_DB, LOG_ERR); + dol_syslog('Error when connecting to SPIP '.getDolGlobalString('ADHERENT_SPIP_SERVEUR').' '.getDolGlobalString('ADHERENT_SPIP_USER').' '.getDolGlobalString('ADHERENT_SPIP_PASS').' '.getDolGlobalString('ADHERENT_SPIP_DB'), LOG_ERR); return false; } From a6847e9edc81976fb98324ae04f586a21e8b3fbc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 00:06:15 +0100 Subject: [PATCH 234/816] doxygen --- htdocs/ticket/class/actions_ticket.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/ticket/class/actions_ticket.class.php b/htdocs/ticket/class/actions_ticket.class.php index 6ad204965bc..29a013f1eb9 100644 --- a/htdocs/ticket/class/actions_ticket.class.php +++ b/htdocs/ticket/class/actions_ticket.class.php @@ -111,7 +111,7 @@ class ActionsTicket * @param int $id ID of ticket * @param string $ref Reference of ticket * @param string $track_id Track ID of ticket (for public area) - * @return void + * @return int <0 if KO, >0 if OK */ public function fetch($id = 0, $ref = '', $track_id = '') { From cf1ff1e1f69688a7656c08051dc01fb3f6fb0ec7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 00:07:03 +0100 Subject: [PATCH 235/816] Fix warning --- htdocs/resource/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/resource/card.php b/htdocs/resource/card.php index 5c588b59c6b..3ee118d06c7 100644 --- a/htdocs/resource/card.php +++ b/htdocs/resource/card.php @@ -225,7 +225,7 @@ if ($action == 'create' || $object->fetch($id, $ref) > 0) { // Type print ''; print ''; // Description From 2aef5e94df346965073f9feddca8342037afc913 Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sun, 1 Jan 2023 15:05:04 +0100 Subject: [PATCH 236/816] Set $remise_percent to 0, if GETPOST is empty. --- htdocs/commande/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 66e673abf2d..e467a398dc7 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1106,7 +1106,7 @@ if (empty($reshook)) { $special_code = 3; } - $remise_percent = price2num(GETPOST('remise_percent'), '', 2); + $remise_percent = GETPOST('remise_percent') != '' ? price2num(GETPOST('remise_percent'), '', 2) : 0; // Check minimum price $productid = GETPOST('productid', 'int'); From b96c58ea6796232bd35562c2f711358b8812b054 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 00:07:03 +0100 Subject: [PATCH 237/816] Fix warning --- htdocs/resource/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/resource/card.php b/htdocs/resource/card.php index 5c588b59c6b..3ee118d06c7 100644 --- a/htdocs/resource/card.php +++ b/htdocs/resource/card.php @@ -225,7 +225,7 @@ if ($action == 'create' || $object->fetch($id, $ref) > 0) { // Type print ''; print ''; // Description From edfa7dddfcc4c78faa6f6130f418be6818488205 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 01:50:25 +0100 Subject: [PATCH 238/816] Update html.formpropal.class.php --- htdocs/core/class/html.formpropal.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formpropal.class.php b/htdocs/core/class/html.formpropal.class.php index fbbf2c97fb7..7cce3c839c5 100644 --- a/htdocs/core/class/html.formpropal.class.php +++ b/htdocs/core/class/html.formpropal.class.php @@ -139,7 +139,7 @@ class FormPropal } else { print ''; print ''; From 9aecf48ce33880623e3f5f0330cbbba76710bd7d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 01:53:05 +0100 Subject: [PATCH 239/816] Update main.inc.php --- htdocs/main.inc.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index e0ea7b1dbfc..dbb18aa61d3 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -3211,7 +3211,7 @@ if (!function_exists("llxFooter")) { global $contextpage, $page, $limit, $mode; global $dolibarr_distrib; - $ext = 'layout='.$conf->browser->layout.'&version='.urlencode(DOL_VERSION); + $ext = 'layout='.urlencode($conf->browser->layout).'&version='.urlencode(DOL_VERSION); // Hook to add more things on all pages within fiche DIV $llxfooter = ''; @@ -3222,7 +3222,9 @@ if (!function_exists("llxFooter")) { } elseif ($reshook > 0) { $llxfooter = $hookmanager->resPrint; } - print $llxfooter; + if ($llxfooter) { + print $llxfooter; + } // Global html output events ($mesgs, $errors, $warnings) dol_htmloutput_events($disabledoutputofmessages); From 73e5d6d2d2a7b86eee434a0db4fe100c195a4b31 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 02:08:20 +0100 Subject: [PATCH 240/816] Clean code --- htdocs/core/class/conf.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 56e9e88b1dc..74d8b089223 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -499,9 +499,9 @@ class Conf // Exception: Some dir are not the name of module. So we keep exception here for backward compatibility. // Sous module bons d'expedition - $this->expedition_bon->enabled = (!empty($this->global->MAIN_SUBMODULE_EXPEDITION) ? $this->global->MAIN_SUBMODULE_EXPEDITION : 0); + $this->expedition_bon->enabled = (empty($this->global->MAIN_SUBMODULE_EXPEDITION) ? 0 : $this->global->MAIN_SUBMODULE_EXPEDITION); // Sub module delivery note Sous module bons de livraison - $this->delivery_note->enabled = (!empty($this->global->MAIN_SUBMODULE_DELIVERY) ? $this->global->MAIN_SUBMODULE_DELIVERY : 0); + $this->delivery_note->enabled = (empty($this->global->MAIN_SUBMODULE_DELIVERY) ? 0 : $this->global->MAIN_SUBMODULE_DELIVERY); // Module fournisseur if (!empty($this->fournisseur)) { From f3bdecd111e8d30f92536be289f407271600bcf7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 02:23:28 +0100 Subject: [PATCH 241/816] Revert option ECM_AUTO_TREE_ENABLED into ECM_AUTO_TREE_HIDEN --- htdocs/admin/ecm.php | 24 ++++++++++++------------ htdocs/core/lib/ecm.lib.php | 2 +- htdocs/core/modules/modECM.class.php | 8 +------- htdocs/ecm/index_auto.php | 2 +- htdocs/install/upgrade2.php | 7 +++++++ 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/htdocs/admin/ecm.php b/htdocs/admin/ecm.php index 3e0c2378742..4b5ccbb133e 100644 --- a/htdocs/admin/ecm.php +++ b/htdocs/admin/ecm.php @@ -31,6 +31,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; // Load translation files required by the page $langs->load("admin"); +$action = GETPOST('action', 'aZ09'); + if (!$user->admin) { accessforbidden(); } @@ -41,6 +43,7 @@ if (!$user->admin) { */ // set +$reg = array(); if (preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) { $code = $reg[1]; if (dolibarr_set_const($db, $code, 1, 'chaine', 0, '', $conf->entity) > 0) { @@ -67,6 +70,8 @@ if (preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) { * View */ +$form = new Form($db); + $help_url = ''; llxHeader('', $langs->trans("ECMSetup"), $help_url); @@ -81,26 +86,21 @@ print dol_get_fiche_head($head, 'ecm', '', -1, ''); print '
'.$langs->trans("DefaultModelPropalCreate").''.$langs->trans("DefaultModelPropalCreate").''; $texte .= $form->selectarray('value2', $list, $conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT); $texte .= "
'.$langs->trans("DefaultModelPropalToBill").''.$langs->trans("DefaultModelPropalToBill").''; $texte .= $form->selectarray('value3', $list, $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL); $texte .= "
'.$langs->trans("DefaultModelPropalClosed").''.$langs->trans("DefaultModelPropalClosed").''; $texte .= $form->selectarray('value4', $list, $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED); $texte .= "
'.$langs->trans("LibraryVersion").'
'; print $langs->trans("FileMustHaveOneOfFollowingFormat"); print '
'.img_picto_common($key, $objmodelimport->getPictoForKey($key)).'
'.$langs->trans("ErrorNoAccountancyModuleLoaded").'
'.$langs->trans("FeatureNotYetAvailable").'
'.dol_print_date(dol_mktime(0, 0, 0, $m, 1, $y), "%b %Y").'
' . $langs->trans("ErrorNoAccountancyModuleLoaded") . '
' . $langs->trans("FeatureNotYetAvailable") . '
' . dol_print_date(dol_mktime(0, 0, 0, $m, 1, $y), "%b %Y") . '
'.$langs->trans("ResourceType").''; - $ret = $formresource->select_types_resource($object->fk_code_type_resource, 'fk_code_type_resource', '', 2); + $formresource->select_types_resource($object->fk_code_type_resource, 'fk_code_type_resource', '', 2); print '
'.$langs->trans("ResourceType").''; - $ret = $formresource->select_types_resource($object->fk_code_type_resource, 'fk_code_type_resource', '', 2); + $formresource->select_types_resource($object->fk_code_type_resource, 'fk_code_type_resource', '', 2); print '
'; print ''; print ''; -print ''; -print ''."\n"; +print ''."\n"; print ''; -$form = new Form($db); - // Mail required for members print ''; print ''; -print ''; - -print ''; diff --git a/htdocs/core/lib/ecm.lib.php b/htdocs/core/lib/ecm.lib.php index e7840505e8f..2a9b9a766a3 100644 --- a/htdocs/core/lib/ecm.lib.php +++ b/htdocs/core/lib/ecm.lib.php @@ -54,7 +54,7 @@ function ecm_prepare_dasboard_head($object) $head[$h][2] = 'index'; $h++; - if (!empty($conf->global->ECM_AUTO_TREE_ENABLED)) { + if (empty($conf->global->ECM_AUTO_TREE_HIDEN)) { $head[$h][0] = DOL_URL_ROOT.'/ecm/index_auto.php'; $head[$h][1] = $langs->trans("ECMSectionsAuto").$form->textwithpicto('', $helptext, 1, 'info', '', 0, 3); $head[$h][2] = 'index_auto'; diff --git a/htdocs/core/modules/modECM.class.php b/htdocs/core/modules/modECM.class.php index 1ea7530be53..09556b43cd8 100644 --- a/htdocs/core/modules/modECM.class.php +++ b/htdocs/core/modules/modECM.class.php @@ -74,12 +74,6 @@ class modECM extends DolibarrModules $this->const = array(); // List of parameters $r = 0; - $this->const[$r][0] = "ECM_AUTO_TREE_ENABLED"; - $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "1"; - $this->const[$r][3] = 'Auto tree is enabled by default'; - $this->const[$r][4] = 0; - // Boxes $this->boxes = array(); // List of boxes $r = 0; @@ -182,7 +176,7 @@ class modECM extends DolibarrModules 'langs'=>'ecm', 'position'=>103, 'perms'=>'$user->rights->ecm->read || $user->rights->ecm->upload', - 'enabled'=>'($user->rights->ecm->read || $user->rights->ecm->upload) && getDolGlobalInt("ECM_AUTO_TREE_ENABLED")', + 'enabled'=>'($user->rights->ecm->read || $user->rights->ecm->upload) && !getDolGlobalInt("ECM_AUTO_TREE_HIDEN")', 'target'=>'', 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both ); diff --git a/htdocs/ecm/index_auto.php b/htdocs/ecm/index_auto.php index 342d7d74129..9d9d30e8188 100644 --- a/htdocs/ecm/index_auto.php +++ b/htdocs/ecm/index_auto.php @@ -309,7 +309,7 @@ llxHeader($moreheadcss.$moreheadjs, $langs->trans("ECMArea"), '', '', '', '', $m // Add sections to manage $rowspan = 0; $sectionauto = array(); -if (!empty($conf->global->ECM_AUTO_TREE_ENABLED)) { +if (empty($conf->global->ECM_AUTO_TREE_HIDEN)) { if (isModEnabled("product") || isModEnabled("service")) { $langs->load("products"); $rowspan++; $sectionauto[] = array('position'=>10, 'level'=>1, 'module'=>'product', 'test'=>(isModEnabled("product") || isModEnabled("service")), 'label'=>$langs->trans("ProductsAndServices"), 'desc'=>$langs->trans("ECMDocsByProducts")); diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 51334eaae21..89e190f92c1 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -490,6 +490,13 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { migrate_contractdet_rank(); } + + // Scripts for 18.0 + $afterversionarray = explode('.', '170.9'); + $beforeversionarray = explode('.', '18.0.9'); + if (versioncompare($versiontoarray, $afterversionarray) >= 0 && versioncompare($versiontoarray, $beforeversionarray) <= 0) { + migrate_contractdet_rank(); + } } From 5148e6a1a2601e298188a87312ce22853fa74a9e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 03:08:57 +0100 Subject: [PATCH 242/816] Enhance doxygen conf --- .github/workflows/doxygen-action.yml.disabled | 17 +++++++ build/doxygen/dolibarr-doxygen.doxyfile | 50 ++++++++++++------- 2 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/doxygen-action.yml.disabled diff --git a/.github/workflows/doxygen-action.yml.disabled b/.github/workflows/doxygen-action.yml.disabled new file mode 100644 index 00000000000..bd923e6394f --- /dev/null +++ b/.github/workflows/doxygen-action.yml.disabled @@ -0,0 +1,17 @@ +# See syntax file on https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions +name: Doxygen +on: + schedule: + - cron: "0 15 * * *" + workflow_dispatch: + branches: + - develop + +jobs: + doxygen: + runs-on: ubuntu-latest + steps: + - name: 'Doxygen' + uses: mattnotmitt/doxygen-action@1.9.5 + with: + doxyfile-path: build/doxygen diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index 31400661ecc..b7ca04898e5 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -1,14 +1,17 @@ -# Doxyfile 1.7.3 +# Doxyfile 1.8.16 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options @@ -448,7 +451,7 @@ GENERATE_TODOLIST = NO # disable (NO) the test list. This list is created by putting \test # commands in the documentation. -GENERATE_TESTLIST = YES +GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug @@ -625,7 +628,7 @@ EXCLUDE_SYMLINKS = YES # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* -EXCLUDE_PATTERNS = */CVS/* *google* *pibarcode* +EXCLUDE_PATTERNS = */CVS/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -775,14 +778,16 @@ IGNORE_PREFIX = # configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html @@ -852,13 +857,24 @@ HTML_TIMESTAMP = YES HTML_ALIGN_MEMBERS = YES +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = NO + # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). -HTML_DYNAMIC_SECTIONS = YES +HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 @@ -1003,7 +1019,7 @@ QHG_LOCATION = # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. -GENERATE_ECLIPSEHELP = YES +GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have @@ -1072,7 +1088,7 @@ FORMULA_TRANSPARENT = YES # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client From f8f2e8ea9ea988c075153037feb58853506704d7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 03:52:29 +0100 Subject: [PATCH 243/816] Enhancement with doxygen --- .github/workflows/doxygen-action.yml.disabled | 17 --------- .github/workflows/doxygen-gh-pages.yml | 38 +++++++++++++++++++ build/doxygen/dolibarr-doxygen-build.pl | 10 ++--- build/doxygen/dolibarr-doxygen.doxyfile | 38 +++++++++---------- 4 files changed, 62 insertions(+), 41 deletions(-) delete mode 100644 .github/workflows/doxygen-action.yml.disabled create mode 100644 .github/workflows/doxygen-gh-pages.yml diff --git a/.github/workflows/doxygen-action.yml.disabled b/.github/workflows/doxygen-action.yml.disabled deleted file mode 100644 index bd923e6394f..00000000000 --- a/.github/workflows/doxygen-action.yml.disabled +++ /dev/null @@ -1,17 +0,0 @@ -# See syntax file on https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions -name: Doxygen -on: - schedule: - - cron: "0 15 * * *" - workflow_dispatch: - branches: - - develop - -jobs: - doxygen: - runs-on: ubuntu-latest - steps: - - name: 'Doxygen' - uses: mattnotmitt/doxygen-action@1.9.5 - with: - doxyfile-path: build/doxygen diff --git a/.github/workflows/doxygen-gh-pages.yml b/.github/workflows/doxygen-gh-pages.yml new file mode 100644 index 00000000000..066ede4dea3 --- /dev/null +++ b/.github/workflows/doxygen-gh-pages.yml @@ -0,0 +1,38 @@ +# See syntax file on https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions +name: Doxygen +on: + schedule: + - cron: "0 15 * * *" + workflow_dispatch: + branches: + - develop +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Build + uses: DenverCoder1/doxygen-github-pages-action@v1.2.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: gh-pages + folder: docs/html + config_file: build/doxygen/dolibarr-doxygen.doxyfile + + - name: Deploy + uses: JamesIves/github-pages-deploy-action@v4 + with: + branch: gh-pages + folder: docs/html # The folder the action should deploy. + target-folder: docs/html2 + +#jobs: +# doxygen: +# runs-on: ubuntu-latest +# steps: +# - name: 'Doxygen' +# uses: mattnotmitt/doxygen-action@1.9.5 +# with: +# doxyfile-path: build/doxygen diff --git a/build/doxygen/dolibarr-doxygen-build.pl b/build/doxygen/dolibarr-doxygen-build.pl index 75a5cceddbe..5a4849a3a5b 100755 --- a/build/doxygen/dolibarr-doxygen-build.pl +++ b/build/doxygen/dolibarr-doxygen-build.pl @@ -17,9 +17,9 @@ use Cwd; my $dir = getcwd; print "Current dir is: $dir\n"; -print "Running dir for doxygen must be: $DIR\n"; +#print "Running dir for doxygen must be: $DIR\n"; -if (! -s $CONFFILE) +if (! -s "build/doxygen/$CONFFILE") { print "Error: current directory for building Dolibarr doxygen documentation is not correct.\n"; print "\n"; @@ -30,7 +30,7 @@ if (! -s $CONFFILE) exit 1; } -$SOURCE="../.."; +$SOURCE="."; # Get version $MAJOR, $MINOR and $BUILD $result = open( IN, "< " . $SOURCE . "/htdocs/filefunc.inc.php" ); @@ -47,8 +47,8 @@ $version=$MAJOR.".".$MINOR.".".$BUILD; print "Running doxygen for version ".$version.", please wait...\n"; -print "cat $CONFFILE | sed -e 's/x\.y\.z/".$version."/' | doxygen $OPTIONS - 2>&1\n"; -$result=`cat $CONFFILE | sed -e 's/x\.y\.z/$version/' | doxygen $OPTIONS - 2>&1`; +print "cat build/doxygen/$CONFFILE | sed -e 's/x\.y\.z/".$version."/' | doxygen $OPTIONS - 2>&1\n"; +$result=`cat build/doxygen/$CONFFILE | sed -e 's/x\.y\.z/$version/' | doxygen $OPTIONS - 2>&1`; print $result; diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index b7ca04898e5..216ba517dc5 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -41,7 +41,7 @@ PROJECT_NUMBER = x.y.z # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = ../../build +OUTPUT_DIRECTORY = build # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output @@ -117,7 +117,7 @@ FULL_PATH_NAMES = YES # If left blank the directory from which doxygen is run is used as the # path to strip. -STRIP_FROM_PATH = "../.." +STRIP_FROM_PATH = "" # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells @@ -290,7 +290,7 @@ TYPEDEF_HIDES_STRUCT = NO # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols -SYMBOL_CACHE_SIZE = 0 +#SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options @@ -490,7 +490,7 @@ SHOW_USED_FILES = YES # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. -SHOW_DIRECTORIES = YES +#SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the @@ -574,7 +574,7 @@ WARN_FORMAT = "$file:$line: $text" # and error messages should be written. If left blank the output is written # to stderr. -WARN_LOGFILE = doxygen_warnings.log +WARN_LOGFILE = build/html/doxygen_warnings.log #--------------------------------------------------------------------------- # configuration options related to the input files @@ -585,7 +585,7 @@ WARN_LOGFILE = doxygen_warnings.log # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../../htdocs ../../scripts +INPUT = htdocs scripts # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -614,7 +614,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = ../../build ../../dev ../../doc ../../document ../../documents ../../htdocs/conf/conf.php ../../htdocs/custom ../../htdocs/document ../../htdocs/documents ../../htdocs/includes +EXCLUDE = build dev doc document documents htdocs/conf/conf.php htdocs/custom htdocs/document htdocs/documents htdocs/includes # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded @@ -642,7 +642,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = ../../htdocs/modulebuilder/template +EXAMPLE_PATH = htdocs/modulebuilder/template # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -662,7 +662,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = ../../doc/images +IMAGE_PATH = doc/images # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -765,7 +765,7 @@ ALPHABETICAL_INDEX = YES # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) -COLS_IN_ALPHA_INDEX = 5 +#COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. @@ -802,14 +802,14 @@ HTML_FILE_EXTENSION = .html # standard header. # Does not work with 1.7.3 -#HTML_HEADER = doxygen_header.html +#HTML_HEADER = build/doxygen/doxygen_header.html # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. # Does not work with 1.7.3 -HTML_FOOTER = doxygen_footer.html +HTML_FOOTER = build/doxygen/doxygen_footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to @@ -855,7 +855,7 @@ HTML_TIMESTAMP = YES # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. -HTML_ALIGN_MEMBERS = YES +#HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that @@ -1051,7 +1051,7 @@ GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. -USE_INLINE_TREES = NO +#USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree @@ -1098,7 +1098,7 @@ SEARCHENGINE = YES # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. -SERVER_BASED_SEARCH = NO +SERVER_BASED_SEARCH = YES #--------------------------------------------------------------------------- # configuration options related to the LaTeX output @@ -1276,13 +1276,13 @@ XML_OUTPUT = xml # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_SCHEMA = +#XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_DTD = +#XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting @@ -1447,7 +1447,7 @@ EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). -PERL_PATH = /usr/bin/perl +#PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool @@ -1469,7 +1469,7 @@ CLASS_DIAGRAMS = NO # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. -MSCGEN_PATH = +#MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented From 466239c256e1cf6371a29a4644cb600c45eb5db4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 04:08:09 +0100 Subject: [PATCH 244/816] Fix font --- build/doxygen/dolibarr-doxygen.doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index 216ba517dc5..b1302c7853d 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -1501,7 +1501,7 @@ DOT_NUM_THREADS = 0 # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. -DOT_FONTNAME = FreeSans.ttf +#DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. From 7dd39092279fe9bfe35623e4414a81e8b4991331 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 04:16:06 +0100 Subject: [PATCH 245/816] Fix doxygen --- .github/workflows/doxygen-gh-pages.yml | 4 ++-- build/doxygen/dolibarr-doxygen.doxyfile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/doxygen-gh-pages.yml b/.github/workflows/doxygen-gh-pages.yml index 066ede4dea3..dbeebfeb8d9 100644 --- a/.github/workflows/doxygen-gh-pages.yml +++ b/.github/workflows/doxygen-gh-pages.yml @@ -18,14 +18,14 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} branch: gh-pages - folder: docs/html + folder: build/html config_file: build/doxygen/dolibarr-doxygen.doxyfile - name: Deploy uses: JamesIves/github-pages-deploy-action@v4 with: branch: gh-pages - folder: docs/html # The folder the action should deploy. + folder: build/html # The folder the action should deploy. target-folder: docs/html2 #jobs: diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index b1302c7853d..2ba292f21ad 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -614,7 +614,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = build dev doc document documents htdocs/conf/conf.php htdocs/custom htdocs/document htdocs/documents htdocs/includes +EXCLUDE = build dev doc document documents htdocs/conf/conf.php htdocs/custom htdocs/document htdocs/documents htdocs/includes htdocs/install/doctemplates # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded From 47d26974e6a4d2ece4a59b0c14c106c251b6dbdd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 04:31:27 +0100 Subject: [PATCH 246/816] Fix doxygen --- build/doxygen/dolibarr-doxygen.doxyfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index 2ba292f21ad..51f697e1945 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -642,21 +642,21 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = htdocs/modulebuilder/template +#EXAMPLE_PATH = htdocs/modulebuilder/template # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. -EXAMPLE_PATTERNS = *.php +#EXAMPLE_PATTERNS = *.php # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. -EXAMPLE_RECURSIVE = NO +#EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see From c973b7d59c0b20c3b4625b63eccead5bd2d743cb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 04:33:42 +0100 Subject: [PATCH 247/816] Try removing the copy --- .github/workflows/doxygen-gh-pages.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/doxygen-gh-pages.yml b/.github/workflows/doxygen-gh-pages.yml index dbeebfeb8d9..33dd47aa6e6 100644 --- a/.github/workflows/doxygen-gh-pages.yml +++ b/.github/workflows/doxygen-gh-pages.yml @@ -21,12 +21,12 @@ jobs: folder: build/html config_file: build/doxygen/dolibarr-doxygen.doxyfile - - name: Deploy - uses: JamesIves/github-pages-deploy-action@v4 - with: - branch: gh-pages - folder: build/html # The folder the action should deploy. - target-folder: docs/html2 +# - name: Deploy +# uses: JamesIves/github-pages-deploy-action@v4 +# with: +# branch: gh-pages +# folder: build/html # The folder the action should deploy. +# target-folder: docs/html2 #jobs: # doxygen: From 6dbffb53989f8f75f7d5b1d863c7c72328f1a3b6 Mon Sep 17 00:00:00 2001 From: atm-lena Date: Mon, 2 Jan 2023 09:48:34 +0100 Subject: [PATCH 248/816] Add price() to pricetonum() on bomline view --- htdocs/bom/tpl/objectline_view.tpl.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 85bd4d6b02a..fc6b7709d14 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -247,13 +247,13 @@ if ($resql) { // Cost if (!empty($sub_bom->id)) { $sub_bom->calculateCosts(); - print ''; + print ''; $total_cost+= $sub_bom->total_cost * $sub_bom_line->qty * $line->qty; } elseif ($sub_bom_product->cost_price > 0) { - print ''; + print ''; $total_cost+= $sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty; } elseif ($sub_bom_product->pmp > 0) { // PMP if cost price isn't defined - print ''; + print ''; $total_cost.= $sub_bom_product->pmp * $sub_bom_line->qty * $line->qty; } else { // Minimum purchase price if cost price and PMP aren't defined $sql_supplier_price = 'SELECT MIN(price) AS min_price, quantity AS qty FROM '.MAIN_DB_PREFIX.'product_fournisseur_price'; From 70e1e8cbb9d52c814c54cc3943853e89fa62c0cf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 12:48:17 +0100 Subject: [PATCH 249/816] Clean code for doxygen --- build/doxygen/dolibarr-doxygen.doxyfile | 6 +- build/doxygen/doxygen-awesome.css | 2413 +++++++++++++++++ .../stock/class/api_stockmovements.class.php | 4 +- 3 files changed, 2420 insertions(+), 3 deletions(-) create mode 100644 build/doxygen/doxygen-awesome.css diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index 51f697e1945..20ff102f0a2 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -1098,7 +1098,7 @@ SEARCHENGINE = YES # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. -SERVER_BASED_SEARCH = YES +SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output @@ -1650,3 +1650,7 @@ GENERATE_LEGEND = YES # the various graphs. DOT_CLEANUP = YES + + +FULL_SIDEBAR = NO +HTML_EXTRA_STYLESHEET = build/doxygen/doxygen-awesome.css diff --git a/build/doxygen/doxygen-awesome.css b/build/doxygen/doxygen-awesome.css new file mode 100644 index 00000000000..0b1c8c20892 --- /dev/null +++ b/build/doxygen/doxygen-awesome.css @@ -0,0 +1,2413 @@ +/** + +Doxygen Awesome +https://github.com/jothepro/doxygen-awesome-css + +MIT License + +Copyright (c) 2021 - 2022 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +html { + /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ + --primary-color: #1779c4; + --primary-dark-color: #335c80; + --primary-light-color: #70b1e9; + + /* page base colors */ + --page-background-color: #ffffff; + --page-foreground-color: #2f4153; + --page-secondary-foreground-color: #6f7e8e; + + /* color for all separators on the website: hr, borders, ... */ + --separator-color: #dedede; + + /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */ + --border-radius-large: 8px; + --border-radius-small: 4px; + --border-radius-medium: 6px; + + /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */ + --spacing-small: 5px; + --spacing-medium: 10px; + --spacing-large: 16px; + + /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */ + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); + + --odd-color: rgba(0,0,0,.028); + + /* font-families. will affect all text on the website + * font-family: the normal font for text, headlines, menus + * font-family-monospace: used for preformatted text in memtitle, code, fragments + */ + --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif; + --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; + + /* font sizes */ + --page-font-size: 15.6px; + --navigation-font-size: 14.4px; + --toc-font-size: 13.4px; + --code-font-size: 14px; /* affects code, fragment */ + --title-font-size: 22px; + + /* content text properties. These only affect the page content, not the navigation or any other ui elements */ + --content-line-height: 27px; + /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ + --content-maxwidth: 1050px; + --table-line-height: 24px; + --toc-sticky-top: var(--spacing-medium); + --toc-width: 200px; + --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px); + + /* colors for various content boxes: @warning, @note, @deprecated @bug */ + --warning-color: #f8d1cc; + --warning-color-dark: #b61825; + --warning-color-darker: #75070f; + --note-color: #faf3d8; + --note-color-dark: #f3a600; + --note-color-darker: #5f4204; + --todo-color: #e4f3ff; + --todo-color-dark: #1879C4; + --todo-color-darker: #274a5c; + --deprecated-color: #ecf0f3; + --deprecated-color-dark: #5b6269; + --deprecated-color-darker: #43454a; + --bug-color: #e4dafd; + --bug-color-dark: #5b2bdd; + --bug-color-darker: #2a0d72; + --invariant-color: #d8f1e3; + --invariant-color-dark: #44b86f; + --invariant-color-darker: #265532; + + /* blockquote colors */ + --blockquote-background: #f8f9fa; + --blockquote-foreground: #636568; + + /* table colors */ + --tablehead-background: #f1f1f1; + --tablehead-foreground: var(--page-foreground-color); + + /* menu-display: block | none + * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible. + * `GENERATE_TREEVIEW` MUST be enabled! + */ + --menu-display: block; + + --menu-focus-foreground: var(--page-background-color); + --menu-focus-background: var(--primary-color); + --menu-selected-background: rgba(0,0,0,.05); + + + --header-background: var(--page-background-color); + --header-foreground: var(--page-foreground-color); + + /* searchbar colors */ + --searchbar-background: var(--side-nav-background); + --searchbar-foreground: var(--page-foreground-color); + + /* searchbar size + * (`searchbar-width` is only applied on screens >= 768px. + * on smaller screens the searchbar will always fill the entire screen width) */ + --searchbar-height: 33px; + --searchbar-width: 210px; + --searchbar-border-radius: var(--searchbar-height); + + /* code block colors */ + --code-background: #f5f5f5; + --code-foreground: var(--page-foreground-color); + + /* fragment colors */ + --fragment-background: #F8F9FA; + --fragment-foreground: #37474F; + --fragment-keyword: #bb6bb2; + --fragment-keywordtype: #8258b3; + --fragment-keywordflow: #d67c3b; + --fragment-token: #438a59; + --fragment-comment: #969696; + --fragment-link: #5383d6; + --fragment-preprocessor: #46aaa5; + --fragment-linenumber-color: #797979; + --fragment-linenumber-background: #f4f4f5; + --fragment-linenumber-border: #e3e5e7; + --fragment-lineheight: 20px; + + /* sidebar navigation (treeview) colors */ + --side-nav-background: #fbfbfb; + --side-nav-foreground: var(--page-foreground-color); + --side-nav-arrow-opacity: 0; + --side-nav-arrow-hover-opacity: 0.9; + + --toc-background: var(--side-nav-background); + --toc-foreground: var(--side-nav-foreground); + + /* height of an item in any tree / collapsable table */ + --tree-item-height: 30px; + + --memname-font-size: var(--code-font-size); + --memtitle-font-size: 18px; + + --webkit-scrollbar-size: 7px; + --webkit-scrollbar-padding: 4px; + --webkit-scrollbar-color: var(--separator-color); +} + +@media screen and (max-width: 767px) { + html { + --page-font-size: 16px; + --navigation-font-size: 16px; + --toc-font-size: 15px; + --code-font-size: 15px; /* affects code, fragment */ + --title-font-size: 22px; + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: #1C1D1F; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #2e1917; + --warning-color-dark: #ad2617; + --warning-color-darker: #f5b1aa; + --note-color: #3b2e04; + --note-color-dark: #f1b602; + --note-color-darker: #ceb670; + --todo-color: #163750; + --todo-color-dark: #1982D2; + --todo-color-darker: #dcf0fa; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2a2536; + --bug-color-dark: #7661b3; + --bug-color-darker: #ae9ed6; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; + } +} + +/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */ +html.dark-mode { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: #1C1D1F; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #2e1917; + --warning-color-dark: #ad2617; + --warning-color-darker: #f5b1aa; + --note-color: #3b2e04; + --note-color-dark: #f1b602; + --note-color-darker: #ceb670; + --todo-color: #163750; + --todo-color-dark: #1982D2; + --todo-color-darker: #dcf0fa; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2a2536; + --bug-color-dark: #7661b3; + --bug-color-darker: #ae9ed6; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; +} + +body { + color: var(--page-foreground-color); + background-color: var(--page-background-color); + font-size: var(--page-font-size); +} + +body, table, div, p, dl, #nav-tree .label, .title, +.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, +.SelectItem, #MSearchField, .navpath li.navelem a, +.navpath li.navelem a:hover, p.reference, p.definition { + font-family: var(--font-family); +} + +h1, h2, h3, h4, h5 { + margin-top: .9em; + font-weight: 600; + line-height: initial; +} + +p, div, table, dl, p.reference, p.definition { + font-size: var(--page-font-size); +} + +p.reference, p.definition { + color: var(--page-secondary-foreground-color); +} + +a:link, a:visited, a:hover, a:focus, a:active { + color: var(--primary-color) !important; + font-weight: 500; +} + +a.anchor { + scroll-margin-top: var(--spacing-large); + display: block; +} + +/* + Title and top navigation + */ + +#top { + background: var(--header-background); + border-bottom: 1px solid var(--separator-color); +} + +@media screen and (min-width: 768px) { + #top { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + } +} + +#main-nav { + flex-grow: 5; + padding: var(--spacing-small) var(--spacing-medium); +} + +#titlearea { + width: auto; + padding: var(--spacing-medium) var(--spacing-large); + background: none; + color: var(--header-foreground); + border-bottom: none; +} + +@media screen and (max-width: 767px) { + #titlearea { + padding-bottom: var(--spacing-small); + } +} + +#titlearea table tbody tr { + height: auto !important; +} + +#projectname { + font-size: var(--title-font-size); + font-weight: 600; +} + +#projectnumber { + font-family: inherit; + font-size: 60%; +} + +#projectbrief { + font-family: inherit; + font-size: 80%; +} + +#projectlogo { + vertical-align: middle; +} + +#projectlogo img { + max-height: calc(var(--title-font-size) * 2); + margin-right: var(--spacing-small); +} + +.sm-dox, .tabs, .tabs2, .tabs3 { + background: none; + padding: 0; +} + +.tabs, .tabs2, .tabs3 { + border-bottom: 1px solid var(--separator-color); + margin-bottom: -1px; +} + +.main-menu-btn-icon, .main-menu-btn-icon:before, .main-menu-btn-icon:after { + background: var(--page-secondary-foreground-color); +} + +@media screen and (max-width: 767px) { + .sm-dox a span.sub-arrow { + background: var(--code-background); + } + + #main-menu a.has-submenu span.sub-arrow { + color: var(--page-secondary-foreground-color); + border-radius: var(--border-radius-medium); + } + + #main-menu a.has-submenu:hover span.sub-arrow { + color: var(--page-foreground-color); + } +} + +@media screen and (min-width: 768px) { + .sm-dox li, .tablist li { + display: var(--menu-display); + } + + .sm-dox a span.sub-arrow { + border-color: var(--header-foreground) transparent transparent transparent; + } + + .sm-dox a:hover span.sub-arrow { + border-color: var(--menu-focus-foreground) transparent transparent transparent; + } + + .sm-dox ul a span.sub-arrow { + border-color: transparent transparent transparent var(--page-foreground-color); + } + + .sm-dox ul a:hover span.sub-arrow { + border-color: transparent transparent transparent var(--menu-focus-foreground); + } +} + +.sm-dox ul { + background: var(--page-background-color); + box-shadow: var(--box-shadow); + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium) !important; + padding: var(--spacing-small); + animation: ease-out 150ms slideInMenu; +} + +@keyframes slideInMenu { + from { + opacity: 0; + transform: translate(0px, -2px); + } + + to { + opacity: 1; + transform: translate(0px, 0px); + } +} + +.sm-dox ul a { + color: var(--page-foreground-color) !important; + background: var(--page-background-color); + font-size: var(--navigation-font-size); +} + +.sm-dox>li>ul:after { + border-bottom-color: var(--page-background-color) !important; +} + +.sm-dox>li>ul:before { + border-bottom-color: var(--separator-color) !important; +} + +.sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus { + font-size: var(--navigation-font-size) !important; + color: var(--menu-focus-foreground) !important; + text-shadow: none; + background-color: var(--menu-focus-background); + border-radius: var(--border-radius-small) !important; +} + +.sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a { + text-shadow: none; + background: transparent; + background-image: none !important; + color: var(--header-foreground) !important; + font-weight: normal; + font-size: var(--navigation-font-size); + border-radius: var(--border-radius-small) !important; +} + +.sm-dox a:focus { + outline: auto; +} + +.sm-dox a:hover, .sm-dox a:active, .tablist li a:hover { + text-shadow: none; + font-weight: normal; + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; + border-radius: var(--border-radius-small) !important; + font-size: var(--navigation-font-size); +} + +.tablist li.current { + border-radius: var(--border-radius-small); + background: var(--menu-selected-background); +} + +.tablist li { + margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small); +} + +.tablist a { + padding: 0 var(--spacing-large); +} + + +/* + Search box + */ + +#MSearchBox { + height: var(--searchbar-height); + background: var(--searchbar-background); + border-radius: var(--searchbar-border-radius); + border: 1px solid var(--separator-color); + overflow: hidden; + width: var(--searchbar-width); + position: relative; + box-shadow: none; + display: block; + margin-top: 0; +} + +/* until Doxygen 1.9.4 */ +.left img#MSearchSelect { + left: 0; + user-select: none; + padding-left: 8px; +} + +/* Doxygen 1.9.5 */ +.left span#MSearchSelect { + left: 0; + user-select: none; + margin-left: 8px; + padding: 0; +} + +.left #MSearchSelect[src$=".png"] { + padding-left: 0 +} + +.SelectionMark { + user-select: none; +} + +.tabs .left #MSearchSelect { + padding-left: 0; +} + +.tabs #MSearchBox { + position: absolute; + right: var(--spacing-medium); +} + +@media screen and (max-width: 767px) { + .tabs #MSearchBox { + position: relative; + right: 0; + margin-left: var(--spacing-medium); + margin-top: 0; + } +} + +#MSearchSelectWindow, #MSearchResultsWindow { + z-index: 9999; +} + +#MSearchBox.MSearchBoxActive { + border-color: var(--primary-color); + box-shadow: inset 0 0 0 1px var(--primary-color); +} + +#main-menu > li:last-child { + margin-right: 0; +} + +@media screen and (max-width: 767px) { + #main-menu > li:last-child { + height: 50px; + } +} + +#MSearchField { + font-size: var(--navigation-font-size); + height: calc(var(--searchbar-height) - 2px); + background: transparent; + width: calc(var(--searchbar-width) - 64px); +} + +.MSearchBoxActive #MSearchField { + color: var(--searchbar-foreground); +} + +#MSearchSelect { + top: calc(calc(var(--searchbar-height) / 2) - 11px); +} + +#MSearchBox span.left, #MSearchBox span.right { + background: none; + background-image: none; +} + +#MSearchBox span.right { + padding-top: calc(calc(var(--searchbar-height) / 2) - 12px); + position: absolute; + right: var(--spacing-small); +} + +.tabs #MSearchBox span.right { + top: calc(calc(var(--searchbar-height) / 2) - 12px); +} + +@keyframes slideInSearchResults { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } +} + +#MSearchResultsWindow { + left: auto !important; + right: var(--spacing-medium); + border-radius: var(--border-radius-large); + border: 1px solid var(--separator-color); + transform: translate(0, 20px); + box-shadow: var(--box-shadow); + animation: ease-out 280ms slideInSearchResults; + background: var(--page-background-color); +} + +iframe#MSearchResults { + margin: 4px; +} + +iframe { + color-scheme: normal; +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) iframe#MSearchResults { + filter: invert() hue-rotate(180deg); + } +} + +html.dark-mode iframe#MSearchResults { + filter: invert() hue-rotate(180deg); +} + +#MSearchResults .SRPage { + background-color: transparent; +} + +#MSearchResults .SRPage .SREntry { + font-size: 10pt; + padding: var(--spacing-small) var(--spacing-medium); +} + +#MSearchSelectWindow { + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + box-shadow: var(--box-shadow); + background: var(--page-background-color); + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); +} + +#MSearchSelectWindow a.SelectItem { + font-size: var(--navigation-font-size); + line-height: var(--content-line-height); + margin: 0 var(--spacing-small); + border-radius: var(--border-radius-small); + color: var(--page-foreground-color) !important; + font-weight: normal; +} + +#MSearchSelectWindow a.SelectItem:hover { + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; +} + +@media screen and (max-width: 767px) { + #MSearchBox { + margin-top: var(--spacing-medium); + margin-bottom: var(--spacing-medium); + width: calc(100vw - 30px); + } + + #main-menu > li:last-child { + float: none !important; + } + + #MSearchField { + width: calc(100vw - 110px); + } + + @keyframes slideInSearchResultsMobile { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } + } + + #MSearchResultsWindow { + left: var(--spacing-medium) !important; + right: var(--spacing-medium); + overflow: auto; + transform: translate(0, 20px); + animation: ease-out 280ms slideInSearchResultsMobile; + width: auto !important; + } + + /* + * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2 + */ + label.main-menu-btn ~ #searchBoxPos1 { + top: 3px !important; + right: 6px !important; + left: 45px; + display: flex; + } + + label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox { + margin-top: 0; + margin-bottom: 0; + flex-grow: 2; + float: left; + } +} + +/* + Tree view + */ + +#side-nav { + padding: 0 !important; + background: var(--side-nav-background); +} + +@media screen and (max-width: 767px) { + #side-nav { + display: none; + } + + #doc-content { + margin-left: 0 !important; + } +} + +#nav-tree { + background: transparent; +} + +#nav-tree .label { + font-size: var(--navigation-font-size); +} + +#nav-tree .item { + height: var(--tree-item-height); + line-height: var(--tree-item-height); +} + +#nav-sync { + bottom: 12px; + right: 12px; + top: auto !important; + user-select: none; +} + +#nav-tree .selected { + text-shadow: none; + background-image: none; + background-color: transparent; + position: relative; +} + +#nav-tree .selected::after { + content: ""; + position: absolute; + top: 1px; + bottom: 1px; + left: 0; + width: 4px; + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + background: var(--primary-color); +} + + +#nav-tree a { + color: var(--side-nav-foreground) !important; + font-weight: normal; +} + +#nav-tree a:focus { + outline-style: auto; +} + +#nav-tree .arrow { + opacity: var(--side-nav-arrow-opacity); +} + +.arrow { + color: inherit; + cursor: pointer; + font-size: 45%; + vertical-align: middle; + margin-right: 2px; + font-family: serif; + height: auto; + text-align: right; +} + +#nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow { + opacity: var(--side-nav-arrow-hover-opacity); +} + +#nav-tree .selected a { + color: var(--primary-color) !important; + font-weight: bolder; + font-weight: 600; +} + +.ui-resizable-e { + background: var(--separator-color); + width: 1px; +} + +/* + Contents + */ + +div.header { + border-bottom: 1px solid var(--separator-color); + background-color: var(--page-background-color); + background-image: none; +} + +@media screen and (min-width: 1000px) { + #doc-content > div > div.contents, + .PageDoc > div.contents { + display: flex; + flex-direction: row-reverse; + flex-wrap: nowrap; + align-items: flex-start; + } + + div.contents .textblock { + min-width: 200px; + flex-grow: 1; + } +} + +div.contents, div.header .title, div.header .summary { + max-width: var(--content-maxwidth); +} + +div.contents, div.header .title { + line-height: initial; + margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto; +} + +div.header .summary { + margin: var(--spacing-medium) auto 0 auto; +} + +div.headertitle { + padding: 0; +} + +div.header .title { + font-weight: 600; + font-size: 225%; + padding: var(--spacing-medium) var(--spacing-large); + word-break: break-word; +} + +div.header .summary { + width: auto; + display: block; + float: none; + padding: 0 var(--spacing-large); +} + +td.memSeparator { + border-color: var(--separator-color); +} + +span.mlabel { + background: var(--primary-color); + border: none; + padding: 4px 9px; + border-radius: 12px; + margin-right: var(--spacing-medium); +} + +span.mlabel:last-of-type { + margin-right: 2px; +} + +div.contents { + padding: 0 var(--spacing-large); +} + +div.contents p, div.contents li { + line-height: var(--content-line-height); +} + +div.contents div.dyncontent { + margin: var(--spacing-medium) 0; +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) div.contents div.dyncontent img, + html:not(.light-mode) div.contents center img, + html:not(.light-mode) div.contents > table img, + html:not(.light-mode) div.contents div.dyncontent iframe, + html:not(.light-mode) div.contents center iframe, + html:not(.light-mode) div.contents table iframe { + filter: hue-rotate(180deg) invert(); + } +} + +html.dark-mode div.contents div.dyncontent img, +html.dark-mode div.contents center img, +html.dark-mode div.contents > table img, +html.dark-mode div.contents div.dyncontent iframe, +html.dark-mode div.contents center iframe, +html.dark-mode div.contents table iframe { + filter: hue-rotate(180deg) invert(); +} + +h2.groupheader { + border-bottom: 0px; + color: var(--page-foreground-color); + box-shadow: + 100px 0 var(--page-background-color), + -100px 0 var(--page-background-color), + 100px 0.75px var(--separator-color), + -100px 0.75px var(--separator-color), + 500px 0 var(--page-background-color), + -500px 0 var(--page-background-color), + 500px 0.75px var(--separator-color), + -500px 0.75px var(--separator-color), + 900px 0 var(--page-background-color), + -900px 0 var(--page-background-color), + 900px 0.75px var(--separator-color), + -900px 0.75px var(--separator-color), + 1400px 0 var(--page-background-color), + -1400px 0 var(--page-background-color), + 1400px 0.75px var(--separator-color), + -1400px 0.75px var(--separator-color), + 1900px 0 var(--page-background-color), + -1900px 0 var(--page-background-color), + 1900px 0.75px var(--separator-color), + -1900px 0.75px var(--separator-color); +} + +blockquote { + margin: 0 var(--spacing-medium) 0 var(--spacing-medium); + padding: var(--spacing-small) var(--spacing-large); + background: var(--blockquote-background); + color: var(--blockquote-foreground); + border-left: 0; + overflow: visible; + border-radius: var(--border-radius-medium); + overflow: visible; + position: relative; +} + +blockquote::before, blockquote::after { + font-weight: bold; + font-family: serif; + font-size: 360%; + opacity: .15; + position: absolute; +} + +blockquote::before { + content: "“"; + left: -10px; + top: 4px; +} + +blockquote::after { + content: "”"; + right: -8px; + bottom: -25px; +} + +blockquote p { + margin: var(--spacing-small) 0 var(--spacing-medium) 0; +} +.paramname { + font-weight: 600; + color: var(--primary-dark-color); +} + +.paramname > code { + border: 0; +} + +table.params .paramname { + font-weight: 600; + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + padding-right: var(--spacing-small); + line-height: var(--table-line-height); +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px var(--primary-light-color); +} + +.alphachar a { + color: var(--page-foreground-color); +} + +/* + Table of Contents + */ + +div.contents .toc { + max-height: var(--toc-max-height); + min-width: var(--toc-width); + border: 0; + border-left: 1px solid var(--separator-color); + border-radius: 0; + background-color: transparent; + box-shadow: none; + position: sticky; + top: var(--toc-sticky-top); + padding: 0 var(--spacing-large); + margin: var(--spacing-small) 0 var(--spacing-large) var(--spacing-large); +} + +div.toc h3 { + color: var(--toc-foreground); + font-size: var(--navigation-font-size); + margin: var(--spacing-large) 0 var(--spacing-medium) 0; +} + +div.toc li { + padding: 0; + background: none; + line-height: var(--toc-font-size); + margin: var(--toc-font-size) 0 0 0; +} + +div.toc li::before { + display: none; +} + +div.toc ul { + margin-top: 0 +} + +div.toc li a { + font-size: var(--toc-font-size); + color: var(--page-foreground-color) !important; + text-decoration: none; +} + +div.toc li a:hover, div.toc li a.active { + color: var(--primary-color) !important; +} + +div.toc li a.aboveActive { + color: var(--page-secondary-foreground-color) !important; +} + + +@media screen and (max-width: 999px) { + div.contents .toc { + max-height: 45vh; + float: none; + width: auto; + margin: 0 0 var(--spacing-medium) 0; + position: relative; + top: 0; + position: relative; + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + background-color: var(--toc-background); + box-shadow: var(--box-shadow); + } + + div.contents .toc.interactive { + max-height: calc(var(--navigation-font-size) + 2 * var(--spacing-large)); + overflow: hidden; + } + + div.contents .toc > h3 { + -webkit-tap-highlight-color: transparent; + cursor: pointer; + position: sticky; + top: 0; + background-color: var(--toc-background); + margin: 0; + padding: var(--spacing-large) 0; + display: block; + } + + div.contents .toc.interactive > h3::before { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + display: inline-block; + margin-right: var(--spacing-small); + margin-bottom: calc(var(--navigation-font-size) / 4); + transform: rotate(-90deg); + transition: transform 0.25s ease-out; + } + + div.contents .toc.interactive.open > h3::before { + transform: rotate(0deg); + } + + div.contents .toc.interactive.open { + max-height: 45vh; + overflow: auto; + transition: max-height 0.2s ease-in-out; + } + + div.contents .toc a, div.contents .toc a.active { + color: var(--primary-color) !important; + } + + div.contents .toc a:hover { + text-decoration: underline; + } +} + +/* + Code & Fragments + */ + +code, div.fragment, pre.fragment { + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + overflow: hidden; +} + +code { + display: inline; + background: var(--code-background); + color: var(--code-foreground); + padding: 2px 6px; +} + +div.fragment, pre.fragment { + margin: var(--spacing-medium) 0; + padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large); + background: var(--fragment-background); + color: var(--fragment-foreground); + overflow-x: auto; +} + +@media screen and (max-width: 767px) { + div.fragment, pre.fragment { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right: 0; + } + + .contents > div.fragment, + .textblock > div.fragment, + .textblock > pre.fragment, + .contents > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + border-radius: 0; + border-left: 0; + } + + .textblock li > .fragment, + .textblock li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + } + + .memdoc li > .fragment, + .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + } + + .textblock ul, .memdoc ul { + overflow: initial; + } + + .memdoc > div.fragment, + .memdoc > pre.fragment, + dl dd > div.fragment, + dl dd pre.fragment, + .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment, + .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment, + dl dd > .doxygen-awesome-fragment-wrapper > div.fragment, + dl dd .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + border-radius: 0; + border-left: 0; + } +} + +code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size) !important; +} + +div.line:after { + margin-right: var(--spacing-medium); +} + +div.fragment .line, pre.fragment { + white-space: pre; + word-wrap: initial; + line-height: var(--fragment-lineheight); +} + +div.fragment span.keyword { + color: var(--fragment-keyword); +} + +div.fragment span.keywordtype { + color: var(--fragment-keywordtype); +} + +div.fragment span.keywordflow { + color: var(--fragment-keywordflow); +} + +div.fragment span.stringliteral { + color: var(--fragment-token) +} + +div.fragment span.comment { + color: var(--fragment-comment); +} + +div.fragment a.code { + color: var(--fragment-link) !important; +} + +div.fragment span.preprocessor { + color: var(--fragment-preprocessor); +} + +div.fragment span.lineno { + display: inline-block; + width: 27px; + border-right: none; + background: var(--fragment-linenumber-background); + color: var(--fragment-linenumber-color); +} + +div.fragment span.lineno a { + background: none; + color: var(--fragment-link) !important; +} + +div.fragment .line:first-child .lineno { + box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border); +} + +div.line { + border-radius: var(--border-radius-small); +} + +div.line.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +/* + dl warning, attention, note, deprecated, bug, ... + */ + +dl.bug dt a, dl.deprecated dt a, dl.todo dt a { + font-weight: bold !important; +} + +dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.todo, dl.remark { + padding: var(--spacing-medium); + margin: var(--spacing-medium) 0; + color: var(--page-background-color); + overflow: hidden; + margin-left: 0; + border-radius: var(--border-radius-small); +} + +dl.section dd { + margin-bottom: 2px; +} + +dl.warning, dl.attention { + background: var(--warning-color); + border-left: 8px solid var(--warning-color-dark); + color: var(--warning-color-darker); +} + +dl.warning dt, dl.attention dt { + color: var(--warning-color-dark); +} + +dl.note, dl.remark { + background: var(--note-color); + border-left: 8px solid var(--note-color-dark); + color: var(--note-color-darker); +} + +dl.note dt, dl.remark dt { + color: var(--note-color-dark); +} + +dl.todo { + background: var(--todo-color); + border-left: 8px solid var(--todo-color-dark); + color: var(--todo-color-darker); +} + +dl.todo dt { + color: var(--todo-color-dark); +} + +dl.bug dt a { + color: var(--todo-color-dark) !important; +} + +dl.bug { + background: var(--bug-color); + border-left: 8px solid var(--bug-color-dark); + color: var(--bug-color-darker); +} + +dl.bug dt a { + color: var(--bug-color-dark) !important; +} + +dl.deprecated { + background: var(--deprecated-color); + border-left: 8px solid var(--deprecated-color-dark); + color: var(--deprecated-color-darker); +} + +dl.deprecated dt a { + color: var(--deprecated-color-dark) !important; +} + +dl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd { + margin-inline-start: 0px; +} + +dl.invariant, dl.pre { + background: var(--invariant-color); + border-left: 8px solid var(--invariant-color-dark); + color: var(--invariant-color-darker); +} + +dl.invariant dt, dl.pre dt { + color: var(--invariant-color-dark); +} + +/* + memitem + */ + +div.memdoc, div.memproto, h2.memtitle { + box-shadow: none; + background-image: none; + border: none; +} + +div.memdoc { + padding: 0 var(--spacing-medium); + background: var(--page-background-color); +} + +h2.memtitle, div.memitem { + border: 1px solid var(--separator-color); + box-shadow: var(--box-shadow); +} + +h2.memtitle { + box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow); +} + +div.memitem { + transition: none; +} + +div.memproto, h2.memtitle { + background: var(--fragment-background); +} + +h2.memtitle { + font-weight: 500; + font-size: var(--memtitle-font-size); + font-family: var(--font-family-monospace); + border-bottom: none; + border-top-left-radius: var(--border-radius-medium); + border-top-right-radius: var(--border-radius-medium); + word-break: break-all; + position: relative; +} + +h2.memtitle:after { + content: ""; + display: block; + background: var(--fragment-background); + height: var(--spacing-medium); + bottom: calc(0px - var(--spacing-medium)); + left: 0; + right: -14px; + position: absolute; + border-top-right-radius: var(--border-radius-medium); +} + +h2.memtitle > span.permalink { + font-size: inherit; +} + +h2.memtitle > span.permalink > a { + text-decoration: none; + padding-left: 3px; + margin-right: -4px; + user-select: none; + display: inline-block; + margin-top: -6px; +} + +h2.memtitle > span.permalink > a:hover { + color: var(--primary-dark-color) !important; +} + +a:target + h2.memtitle, a:target + h2.memtitle + div.memitem { + border-color: var(--primary-light-color); +} + +div.memitem { + border-top-right-radius: var(--border-radius-medium); + border-bottom-right-radius: var(--border-radius-medium); + border-bottom-left-radius: var(--border-radius-medium); + overflow: hidden; + display: block !important; +} + +div.memdoc { + border-radius: 0; +} + +div.memproto { + border-radius: 0 var(--border-radius-small) 0 0; + overflow: auto; + border-bottom: 1px solid var(--separator-color); + padding: var(--spacing-medium); + margin-bottom: -1px; +} + +div.memtitle { + border-top-right-radius: var(--border-radius-medium); + border-top-left-radius: var(--border-radius-medium); +} + +div.memproto table.memname { + font-family: var(--font-family-monospace); + color: var(--page-foreground-color); + font-size: var(--memname-font-size); + text-shadow: none; +} + +div.memproto div.memtemplate { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--memname-font-size); + margin-left: 2px; + text-shadow: none; +} + +table.mlabels, table.mlabels > tbody { + display: block; +} + +td.mlabels-left { + width: auto; +} + +td.mlabels-right { + margin-top: 3px; + position: sticky; + left: 0; +} + +table.mlabels > tbody > tr:first-child { + display: flex; + justify-content: space-between; + flex-wrap: wrap; +} + +.memname, .memitem span.mlabels { + margin: 0 +} + +/* + reflist + */ + +dl.reflist { + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-medium); + border: 1px solid var(--separator-color); + overflow: hidden; + padding: 0; +} + + +dl.reflist dt, dl.reflist dd { + box-shadow: none; + text-shadow: none; + background-image: none; + border: none; + padding: 12px; +} + + +dl.reflist dt { + font-weight: 500; + border-radius: 0; + background: var(--code-background); + border-bottom: 1px solid var(--separator-color); + color: var(--page-foreground-color) +} + + +dl.reflist dd { + background: none; +} + +/* + Table + */ + +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname), +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: inline-block; + max-width: 100%; +} + +.contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); +} + +table.fieldtable, +table.markdownTable tbody, +table.doxtable tbody { + border: none; + margin: var(--spacing-medium) 0; + box-shadow: 0 0 0 1px var(--separator-color); + border-radius: var(--border-radius-small); +} + +table.doxtable caption { + display: block; +} + +table.fieldtable { + border-collapse: collapse; + width: 100%; +} + +th.markdownTableHeadLeft, +th.markdownTableHeadRight, +th.markdownTableHeadCenter, +th.markdownTableHeadNone, +table.doxtable th { + background: var(--tablehead-background); + color: var(--tablehead-foreground); + font-weight: 600; + font-size: var(--page-font-size); +} + +th.markdownTableHeadLeft:first-child, +th.markdownTableHeadRight:first-child, +th.markdownTableHeadCenter:first-child, +th.markdownTableHeadNone:first-child, +table.doxtable tr th:first-child { + border-top-left-radius: var(--border-radius-small); +} + +th.markdownTableHeadLeft:last-child, +th.markdownTableHeadRight:last-child, +th.markdownTableHeadCenter:last-child, +th.markdownTableHeadNone:last-child, +table.doxtable tr th:last-child { + border-top-right-radius: var(--border-radius-small); +} + +table.markdownTable td, +table.markdownTable th, +table.fieldtable td, +table.fieldtable th, +table.doxtable td, +table.doxtable th { + border: 1px solid var(--separator-color); + padding: var(--spacing-small) var(--spacing-medium); +} + +table.markdownTable td:last-child, +table.markdownTable th:last-child, +table.fieldtable td:last-child, +table.fieldtable th:last-child, +table.doxtable td:last-child, +table.doxtable th:last-child { + border-right: none; +} + +table.markdownTable td:first-child, +table.markdownTable th:first-child, +table.fieldtable td:first-child, +table.fieldtable th:first-child, +table.doxtable td:first-child, +table.doxtable th:first-child { + border-left: none; +} + +table.markdownTable tr:first-child td, +table.markdownTable tr:first-child th, +table.fieldtable tr:first-child td, +table.fieldtable tr:first-child th, +table.doxtable tr:first-child td, +table.doxtable tr:first-child th { + border-top: none; +} + +table.markdownTable tr:last-child td, +table.markdownTable tr:last-child th, +table.fieldtable tr:last-child td, +table.fieldtable tr:last-child th, +table.doxtable tr:last-child td, +table.doxtable tr:last-child th { + border-bottom: none; +} + +table.markdownTable tr, table.doxtable tr { + border-bottom: 1px solid var(--separator-color); +} + +table.markdownTable tr:last-child, table.doxtable tr:last-child { + border-bottom: none; +} + +table.fieldtable th { + font-size: var(--page-font-size); + font-weight: 600; + background-image: none; + background-color: var(--tablehead-background); + color: var(--tablehead-foreground); +} + +table.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fielddoc, .fieldtable th { + border-bottom: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); +} + +table.fieldtable tr:last-child td:first-child { + border-bottom-left-radius: var(--border-radius-small); +} + +table.fieldtable tr:last-child td:last-child { + border-bottom-right-radius: var(--border-radius-small); +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +table.memberdecls { + display: block; + -webkit-tap-highlight-color: transparent; +} + +table.memberdecls tr[class^='memitem'] { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); +} + +table.memberdecls tr[class^='memitem'] .memTemplParams { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + color: var(--primary-dark-color); + white-space: normal; +} + +table.memberdecls .memItemLeft, +table.memberdecls .memItemRight, +table.memberdecls .memTemplItemLeft, +table.memberdecls .memTemplItemRight, +table.memberdecls .memTemplParams { + transition: none; + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + background-color: var(--fragment-background); +} + +table.memberdecls .memTemplItemLeft, +table.memberdecls .memTemplItemRight { + padding-top: 2px; +} + +table.memberdecls .memTemplParams { + border-bottom: 0; + border-left: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + padding-bottom: var(--spacing-small); +} + +table.memberdecls .memTemplItemLeft { + border-radius: 0 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + border-top: 0; +} + +table.memberdecls .memTemplItemRight { + border-radius: 0 0 var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-left: 0; + border-top: 0; +} + +table.memberdecls .memItemLeft { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + padding-left: var(--spacing-medium); + padding-right: 0; +} + +table.memberdecls .memItemRight { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-right: var(--spacing-medium); + padding-left: 0; + +} + +table.memberdecls .mdescLeft, table.memberdecls .mdescRight { + background: none; + color: var(--page-foreground-color); + padding: var(--spacing-small) 0; +} + +table.memberdecls .memItemLeft, +table.memberdecls .memTemplItemLeft { + padding-right: var(--spacing-medium); +} + +table.memberdecls .memSeparator { + background: var(--page-background-color); + height: var(--spacing-large); + border: 0; + transition: none; +} + +table.memberdecls .groupheader { + margin-bottom: var(--spacing-large); +} + +table.memberdecls .inherit_header td { + padding: 0 0 var(--spacing-medium) 0; + text-indent: -12px; + color: var(--page-secondary-foreground-color); +} + +table.memberdecls img[src="closed.png"], +table.memberdecls img[src="open.png"], +div.dynheader img[src="open.png"], +div.dynheader img[src="closed.png"] { + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + margin-top: 8px; + display: block; + float: left; + margin-left: -10px; + transition: transform 0.25s ease-out; +} + +table.memberdecls img { + margin-right: 10px; +} + +table.memberdecls img[src="closed.png"], +div.dynheader img[src="closed.png"] { + transform: rotate(-90deg); + +} + +.compoundTemplParams { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--code-font-size); +} + +@media screen and (max-width: 767px) { + + table.memberdecls .memItemLeft, + table.memberdecls .memItemRight, + table.memberdecls .mdescLeft, + table.memberdecls .mdescRight, + table.memberdecls .memTemplItemLeft, + table.memberdecls .memTemplItemRight, + table.memberdecls .memTemplParams { + display: block; + text-align: left; + padding-left: var(--spacing-large); + margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large)); + border-right: none; + border-left: none; + border-radius: 0; + white-space: normal; + } + + table.memberdecls .memItemLeft, + table.memberdecls .mdescLeft, + table.memberdecls .memTemplItemLeft { + border-bottom: 0; + padding-bottom: 0; + } + + table.memberdecls .memTemplItemLeft { + padding-top: 0; + } + + table.memberdecls .mdescLeft { + margin-bottom: calc(0px - var(--page-font-size)); + } + + table.memberdecls .memItemRight, + table.memberdecls .mdescRight, + table.memberdecls .memTemplItemRight { + border-top: 0; + padding-top: 0; + padding-right: var(--spacing-large); + overflow-x: auto; + } + + table.memberdecls tr[class^='memitem']:not(.inherit) { + display: block; + width: calc(100vw - 2 * var(--spacing-large)); + } + + table.memberdecls .mdescRight { + color: var(--page-foreground-color); + } + + table.memberdecls tr.inherit { + visibility: hidden; + } + + table.memberdecls tr[style="display: table-row;"] { + display: block !important; + visibility: visible; + width: calc(100vw - 2 * var(--spacing-large)); + animation: fade .5s; + } + + @keyframes fade { + 0% { + opacity: 0; + max-height: 0; + } + + 100% { + opacity: 1; + max-height: 200px; + } + } +} + + +/* + Horizontal Rule + */ + +hr { + margin-top: var(--spacing-large); + margin-bottom: var(--spacing-large); + height: 1px; + background-color: var(--separator-color); + border: 0; +} + +.contents hr { + box-shadow: 100px 0 0 var(--separator-color), + -100px 0 0 var(--separator-color), + 500px 0 0 var(--separator-color), + -500px 0 0 var(--separator-color), + 1500px 0 0 var(--separator-color), + -1500px 0 0 var(--separator-color), + 2000px 0 0 var(--separator-color), + -2000px 0 0 var(--separator-color); +} + +.contents img, .contents .center, .contents center, .contents div.image object { + max-width: 100%; + overflow: auto; +} + +@media screen and (max-width: 767px) { + .contents .dyncontent > .center, .contents > center { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); + } +} + +/* + Directories + */ +div.directory { + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + width: auto; +} + +table.directory { + font-family: var(--font-family); + font-size: var(--page-font-size); + font-weight: normal; + width: 100%; +} + +table.directory td.entry, table.directory td.desc { + padding: calc(var(--spacing-small) / 2) var(--spacing-small); + line-height: var(--table-line-height); +} + +table.directory tr.even td:last-child { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; +} + +table.directory tr.even td:first-child { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); +} + +table.directory tr.even:last-child td:last-child { + border-radius: 0 var(--border-radius-small) 0 0; +} + +table.directory tr.even:last-child td:first-child { + border-radius: var(--border-radius-small) 0 0 0; +} + +table.directory td.desc { + min-width: 250px; +} + +table.directory tr.even { + background-color: var(--odd-color); +} + +table.directory tr.odd { + background-color: transparent; +} + +.icona { + width: auto; + height: auto; + margin: 0 var(--spacing-small); +} + +.icon { + background: var(--primary-color); + border-radius: var(--border-radius-small); + font-size: var(--page-font-size); + padding: calc(var(--page-font-size) / 5); + line-height: var(--page-font-size); + transform: scale(0.8); + height: auto; + width: var(--page-font-size); + user-select: none; +} + +.iconfopen, .icondoc, .iconfclosed { + background-position: center; + margin-bottom: 0; + height: var(--table-line-height); +} + +.icondoc { + filter: saturate(0.2); +} + +@media screen and (max-width: 767px) { + div.directory { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed { + filter: hue-rotate(180deg) invert(); + } +} + +html.dark-mode .iconfopen, html.dark-mode .iconfclosed { + filter: hue-rotate(180deg) invert(); +} + +/* + Class list + */ + +.classindex dl.odd { + background: var(--odd-color); + border-radius: var(--border-radius-small); +} + +.classindex dl.even { + background-color: transparent; +} + +/* + Class Index Doxygen 1.8 +*/ + +table.classindex { + margin-left: 0; + margin-right: 0; + width: 100%; +} + +table.classindex table div.ah { + background-image: none; + background-color: initial; + border-color: var(--separator-color); + color: var(--page-foreground-color); + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-large); + padding: var(--spacing-small); +} + +div.qindex { + background-color: var(--odd-color); + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + padding: var(--spacing-small) 0; +} + +/* + Footer and nav-path + */ + +#nav-path { + width: 100%; +} + +#nav-path ul { + background-image: none; + background: var(--page-background-color); + border: none; + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + border-bottom: 0; + box-shadow: 0 0.75px 0 var(--separator-color); + font-size: var(--navigation-font-size); +} + +img.footer { + width: 60px; +} + +.navpath li.footer { + color: var(--page-secondary-foreground-color); +} + +address.footer { + color: var(--page-secondary-foreground-color); + margin-bottom: var(--spacing-large); +} + +#nav-path li.navelem { + background-image: none; + display: flex; + align-items: center; +} + +.navpath li.navelem a { + text-shadow: none; + display: inline-block; + color: var(--primary-color) !important; +} + +.navpath li.navelem b { + color: var(--primary-dark-color); + font-weight: 500; +} + +li.navelem { + padding: 0; + margin-left: -8px; +} + +li.navelem:first-child { + margin-left: var(--spacing-large); +} + +li.navelem:first-child:before { + display: none; +} + +#nav-path li.navelem:after { + content: ''; + border: 5px solid var(--page-background-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(4.2); + z-index: 10; + margin-left: 6px; +} + +#nav-path li.navelem:before { + content: ''; + border: 5px solid var(--separator-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(3.2); + margin-right: var(--spacing-small); +} + +.navpath li.navelem a:hover { + color: var(--primary-color); +} + +/* + Scrollbars for Webkit +*/ + +#nav-tree::-webkit-scrollbar, +div.fragment::-webkit-scrollbar, +pre.fragment::-webkit-scrollbar, +div.memproto::-webkit-scrollbar, +.contents center::-webkit-scrollbar, +.contents .center::-webkit-scrollbar, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar, +div.contents .toc::-webkit-scrollbar { + background: transparent; + width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); +} + +#nav-tree::-webkit-scrollbar-thumb, +div.fragment::-webkit-scrollbar-thumb, +pre.fragment::-webkit-scrollbar-thumb, +div.memproto::-webkit-scrollbar-thumb, +.contents center::-webkit-scrollbar-thumb, +.contents .center::-webkit-scrollbar-thumb, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb, +div.contents .toc::-webkit-scrollbar-thumb { + background-color: transparent; + border: var(--webkit-scrollbar-padding) solid transparent; + border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + background-clip: padding-box; +} + +#nav-tree:hover::-webkit-scrollbar-thumb, +div.fragment:hover::-webkit-scrollbar-thumb, +pre.fragment:hover::-webkit-scrollbar-thumb, +div.memproto:hover::-webkit-scrollbar-thumb, +.contents center:hover::-webkit-scrollbar-thumb, +.contents .center:hover::-webkit-scrollbar-thumb, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb, +div.contents .toc:hover::-webkit-scrollbar-thumb { + background-color: var(--webkit-scrollbar-color); +} + +#nav-tree::-webkit-scrollbar-track, +div.fragment::-webkit-scrollbar-track, +pre.fragment::-webkit-scrollbar-track, +div.memproto::-webkit-scrollbar-track, +.contents center::-webkit-scrollbar-track, +.contents .center::-webkit-scrollbar-track, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track, +div.contents .toc::-webkit-scrollbar-track { + background: transparent; +} + +#nav-tree::-webkit-scrollbar-corner { + background-color: var(--side-nav-background); +} + +#nav-tree, +div.fragment, +pre.fragment, +div.memproto, +.contents center, +.contents .center, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +div.contents .toc { + overflow-x: auto; + overflow-x: overlay; +} + +#nav-tree { + overflow-x: auto; + overflow-y: auto; + overflow-y: overlay; +} + +/* + Scrollbars for Firefox +*/ + +#nav-tree, +div.fragment, +pre.fragment, +div.memproto, +.contents center, +.contents .center, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +div.contents .toc { + scrollbar-width: thin; +} + +/* + Optional Dark mode toggle button +*/ + +doxygen-awesome-dark-mode-toggle { + display: inline-block; + margin: 0 0 0 var(--spacing-small); + padding: 0; + width: var(--searchbar-height); + height: var(--searchbar-height); + background: none; + border: none; + border-radius: var(--searchbar-height); + vertical-align: middle; + text-align: center; + line-height: var(--searchbar-height); + font-size: 22px; + display: flex; + align-items: center; + justify-content: center; + user-select: none; + cursor: pointer; +} + +doxygen-awesome-dark-mode-toggle > svg { + transition: transform .1s ease-in-out; +} + +doxygen-awesome-dark-mode-toggle:active > svg { + transform: scale(.5); +} + +doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.03); +} + +html.dark-mode doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.18); +} + +/* + Optional fragment copy button +*/ +.doxygen-awesome-fragment-wrapper { + position: relative; +} + +doxygen-awesome-fragment-copy-button { + opacity: 0; + background: var(--fragment-background); + width: 28px; + height: 28px; + position: absolute; + right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + border: 1px solid var(--fragment-foreground); + cursor: pointer; + border-radius: var(--border-radius-small); + display: flex; + justify-content: center; + align-items: center; +} + +.doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, doxygen-awesome-fragment-copy-button.success { + opacity: .28; +} + +doxygen-awesome-fragment-copy-button:hover, doxygen-awesome-fragment-copy-button.success { + opacity: 1 !important; +} + +doxygen-awesome-fragment-copy-button:active:not([class~=success]) svg { + transform: scale(.91); +} + +doxygen-awesome-fragment-copy-button svg { + fill: var(--fragment-foreground); + width: 18px; + height: 18px; +} + +doxygen-awesome-fragment-copy-button.success svg { + fill: rgb(14, 168, 14); +} + +doxygen-awesome-fragment-copy-button.success { + border-color: rgb(14, 168, 14); +} + +@media screen and (max-width: 767px) { + .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button { + right: 0; + } +} + +/* + Optional paragraph link button +*/ + +a.anchorlink { + font-size: 90%; + margin-left: var(--spacing-small); + color: var(--page-foreground-color) !important; + text-decoration: none; + opacity: .15; + display: none; + transition: opacity .1s ease-in-out, color .1s ease-in-out; +} + +a.anchorlink svg { + fill: var(--page-foreground-color); +} + +h3 a.anchorlink svg, h4 a.anchorlink svg { + margin-bottom: -3px; + margin-top: -4px; +} + +a.anchorlink:hover { + opacity: .45; +} + +h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink { + display: inline-block; +} + + +#MSearchBox .left { + background: none !important; +} +#MSearchBox .right { + background: none !important; +} diff --git a/htdocs/product/stock/class/api_stockmovements.class.php b/htdocs/product/stock/class/api_stockmovements.class.php index 544485060af..472d38ea245 100644 --- a/htdocs/product/stock/class/api_stockmovements.class.php +++ b/htdocs/product/stock/class/api_stockmovements.class.php @@ -162,8 +162,8 @@ class StockMovements extends DolibarrApi * @param float $qty Qty to add (Use negative value for a stock decrease) {@from body} {@required true} * @param int $type Optionally specify the type of movement. 0=input (stock increase by a stock transfer), 1=output (stock decrease by a stock transfer), 2=output (stock decrease), 3=input (stock increase). {@from body} {@type int} * @param string $lot Lot {@from body} - * @param string $movementcode Movement code {@example INV123} {@from body} - * @param string $movementlabel Movement label {@example Inventory number 123} {@from body} + * @param string $movementcode Movement code {@from body} + * @param string $movementlabel Movement label {@from body} * @param string $price To update AWP (Average Weighted Price) when you make a stock increase (qty must be higher then 0). {@from body} * @param string $datem Date of movement {@from body} {@type date} * @param string $dlc Eat-by date. {@from body} {@type date} From 59ed7b9f96f8b6ad5bf42ac4fc04e56f587ec9c1 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 2 Jan 2023 11:52:34 +0000 Subject: [PATCH 250/816] Fixing style errors. --- htdocs/comm/propal/card.php | 26 ++++++++++----------- htdocs/commande/card.php | 45 ++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 73a94a2a503..7953691f11b 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1235,7 +1235,7 @@ if (empty($reshook)) { // Prepare a price equivalent for minimum price check $pu_equivalent = $pu_ht; - $pu_equivalent_ttc = $pu_ttc; + $pu_equivalent_ttc = $pu_ttc; $currency_tx = $object->multicurrency_tx; // Check if we have a foreing currency @@ -1243,7 +1243,7 @@ if (empty($reshook)) { if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { $pu_equivalent = $pu_ht_devise * $currency_tx; } - if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') { + if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') { $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx; } @@ -1364,18 +1364,18 @@ if (empty($reshook)) { $remise_percent = price2num(GETPOST('remise_percent'), '', 2); // Prepare a price equivalent for minimum price check - $pu_equivalent = $pu_ht; - $pu_equivalent_ttc = $pu_ttc; - $currency_tx = $object->multicurrency_tx; + $pu_equivalent = $pu_ht; + $pu_equivalent_ttc = $pu_ttc; + $currency_tx = $object->multicurrency_tx; - // Check if we have a foreing currency - // If so, we update the pu_equiv as the equivalent price in base currency - if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { - $pu_equivalent = $pu_ht_devise * $currency_tx; - } - if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') { - $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx; - } + // Check if we have a foreing currency + // If so, we update the pu_equiv as the equivalent price in base currency + if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { + $pu_equivalent = $pu_ht_devise * $currency_tx; + } + if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') { + $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx; + } // Extrafields $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line); diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index f5b204c6889..135c6fc9ab9 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -684,18 +684,18 @@ if (empty($reshook)) { // Prepare a price equivalent for minimum price check - $pu_equivalent = $pu_ht; - $pu_equivalent_ttc = $pu_ttc; - $currency_tx = $object->multicurrency_tx; + $pu_equivalent = $pu_ht; + $pu_equivalent_ttc = $pu_ttc; + $currency_tx = $object->multicurrency_tx; - // Check if we have a foreing currency - // If so, we update the pu_equiv as the equivalent price in base currency - if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { - $pu_equivalent = $pu_ht_devise * $currency_tx; - } - if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') { - $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx; - } + // Check if we have a foreing currency + // If so, we update the pu_equiv as the equivalent price in base currency + if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { + $pu_equivalent = $pu_ht_devise * $currency_tx; + } + if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') { + $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx; + } $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2); @@ -1013,7 +1013,6 @@ if (empty($reshook)) { } if (!$error) { - // Insert line $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $info_bits, 0, $price_base_type, $pu_ttc, $date_start, $date_end, $type, min($rank, count($object->lines) + 1), 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, $fk_unit, '', 0, $pu_ht_devise); @@ -1093,18 +1092,18 @@ if (empty($reshook)) { $qty = price2num(GETPOST('qty', 'alpha'), 'MS'); // Prepare a price equivalent for minimum price check - $pu_equivalent = $pu_ht; - $pu_equivalent_ttc = $pu_ttc; - $currency_tx = $object->multicurrency_tx; + $pu_equivalent = $pu_ht; + $pu_equivalent_ttc = $pu_ttc; + $currency_tx = $object->multicurrency_tx; - // Check if we have a foreing currency - // If so, we update the pu_equiv as the equivalent price in base currency - if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { - $pu_equivalent = $pu_ht_devise * $currency_tx; - } - if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') { - $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx; - } + // Check if we have a foreing currency + // If so, we update the pu_equiv as the equivalent price in base currency + if ($pu_ht == '' && $pu_ht_devise != '' && $currency_tx != '') { + $pu_equivalent = $pu_ht_devise * $currency_tx; + } + if ($pu_ttc == '' && $pu_ttc_devise != '' && $currency_tx != '') { + $pu_equivalent_ttc = $pu_ttc_devise * $currency_tx; + } // Define info_bits $info_bits = 0; From 66ee541f771664fa3437d96748528ae914452809 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 15:18:25 +0100 Subject: [PATCH 251/816] Fix class name collision --- htdocs/includes/OAuth/Common/Storage/DoliStorage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php index a769efdf8b9..0ca8dee700b 100644 --- a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php +++ b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php @@ -67,10 +67,10 @@ class DoliStorage implements TokenStorageInterface /** * @param DoliDB $db Database handler - * @param Conf $conf Conf object + * @param \Conf $conf Conf object * @param string $keyforprovider Key to manage several providers of the same type. For example 'abc' will be added to 'Google' to defined storage key. */ - public function __construct(DoliDB $db, Conf $conf, $keyforprovider = '') + public function __construct(DoliDB $db, \Conf $conf, $keyforprovider = '') { $this->db = $db; $this->conf = $conf; From 5dcee6b7d76548ae404be0861746e3226c0c460b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 15:24:20 +0100 Subject: [PATCH 252/816] Fix doxygen --- htdocs/core/boxes/box_dolibarr_state_board.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/boxes/box_dolibarr_state_board.php b/htdocs/core/boxes/box_dolibarr_state_board.php index 9a2e94b8a1d..6152b167863 100644 --- a/htdocs/core/boxes/box_dolibarr_state_board.php +++ b/htdocs/core/boxes/box_dolibarr_state_board.php @@ -20,7 +20,7 @@ /** * \file htdocs/core/boxes/box_dolibarr_state_board.php - * \ingroup + * \ingroup core * \brief Module Dolibarr state base */ From 1484237c1e7588ebe5ac9f0d5654c95b634a198c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 16:13:35 +0100 Subject: [PATCH 253/816] Doc --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3d9b0b04e5a..bbb01cfd3cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,7 +21,7 @@ For users: NEW: Minimal PHP version is now PHP 7.0 instead of PHP 5.6 NEW: #21780 Add pid field to Cronjob class and store PID on job execution NEW: #19680 Add option PRODUCT_ALLOW_EXTERNAL_DOWNLOAD to automatically have uploaded files shared publicly by a link -NEW: #20650 can move the checkbox column on left (experimental option) +NEW: #20650 can move the checkbox column on left (experimental option MAIN_CHECKBOX_LEFT_COLUMN) NEW: #21000 Added columns 'alias_name' on project, supplier invoice, supplier order, supplier proposals and task list NEW: #21395 Added option for dark theme mode in display - color and theme NEW: #21397 added option to auto define barcode numbers for third-parties in barcode module setup From 3ed5edc0032ff0f1ace6958e11e628cf52eeecb0 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Mon, 2 Jan 2023 16:21:14 +0100 Subject: [PATCH 254/816] NEW : search on time spent duration range --- htdocs/projet/tasks/time.php | 53 +++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 94ed0edaffd..8c98e6387b1 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -88,6 +88,10 @@ $search_company = GETPOST('$search_company', 'alpha'); $search_company_alias = GETPOST('$search_company_alias', 'alpha'); $search_project_ref = GETPOST('$search_project_ref', 'alpha'); $search_project_label = GETPOST('$search_project_label', 'alpha'); +$search_timespent_starthour = GETPOSTINT("search_timespent_duration_starthour"); +$search_timespent_startmin = GETPOSTINT("search_timespent_duration_startmin"); +$search_timespent_endhour = GETPOSTINT("search_timespent_duration_endhour"); +$search_timespent_endmin = GETPOSTINT("search_timespent_duration_endmin"); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); @@ -196,6 +200,10 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_product_ref = ''; $toselect = array(); $search_array_options = array(); + $search_timespent_starthour = ''; + $search_timespent_startmin = ''; + $search_timespent_endhour = ''; + $search_timespent_endmin = ''; $action = ''; } @@ -1337,6 +1345,18 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser if ($search_date_endyear) { $param .= '&search_date_endyear='.urlencode($search_date_endyear); } + if ($search_timespent_starthour) { + $param .= '&search_timespent_duration_starthour='.urlencode($search_timespent_starthour); + } + if ($search_timespent_startmin) { + $param .= '&search_timespent_duration_startmin='.urlencode($search_timespent_startmin); + } + if ($search_timespent_endhour) { + $param .= '&search_timespent_duration_endhour='.urlencode($search_timespent_endhour); + } + if ($search_timespent_endmin) { + $param .= '&search_timespent_duration_endmin='.urlencode($search_timespent_endmin); + } /* // Add $param from extra fields @@ -1609,6 +1629,18 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $sql .= " AND t.task_date <= '".$db->idate($search_date_end)."'"; } + if($search_timespent_starthour || $search_timespent_startmin) { + $timespent_duration_start = $search_timespent_starthour * 60 * 60; // We store duration in seconds + $timespent_duration_start += ($search_timespent_startmin ? $search_timespent_startmin : 0) * 60; // We store duration in seconds + $sql .= " AND t.task_duration >= ".$timespent_duration_start; + } + + if($search_timespent_endhour || $search_timespent_endmin) { + $timespent_duration_end = $search_timespent_endhour * 60 * 60; // We store duration in seconds + $timespent_duration_end += ($search_timespent_endmin ? $search_timespent_endmin : 0) * 60; // We store duration in seconds + $sql .= " AND t.task_duration <= ".$timespent_duration_end; + } + $sql .= dolSqlDateFilter('t.task_datehour', $search_day, $search_month, $search_year); // Add where from hooks @@ -1877,7 +1909,26 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser } // Duration if (!empty($arrayfields['t.task_duration']['checked'])) { - print ''; + // Duration - Time spent + print ''; } // Product if (!empty($arrayfields['t.fk_product']['checked'])) { From 1bd0099d9f1e3c85ecdf3aefefe4830212a3bbcd Mon Sep 17 00:00:00 2001 From: atm-lena Date: Mon, 2 Jan 2023 16:29:16 +0100 Subject: [PATCH 255/816] Add column "Alias Name" in contact list --- htdocs/contact/list.php | 44 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index e8c4174af71..3e5103d319a 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -72,6 +72,7 @@ $search_firstlast_only = GETPOST("search_firstlast_only", 'alpha'); $search_lastname = GETPOST("search_lastname", 'alpha'); $search_firstname = GETPOST("search_firstname", 'alpha'); $search_societe = GETPOST("search_societe", 'alpha'); +$search_societe_alias = GETPOST("search_societe_alias", 'alpha'); $search_poste = GETPOST("search_poste", 'alpha'); $search_phone_perso = GETPOST("search_phone_perso", 'alpha'); $search_phone_pro = GETPOST("search_phone_pro", 'alpha'); @@ -192,6 +193,7 @@ foreach ($object->fields as $key => $val) { // Add none object fields for "search in all" if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) { $fieldstosearchall['s.nom'] = "ThirdParty"; + $fieldstosearchall['s.name_alias'] = "AliasNames"; } // Definition of fields for list @@ -213,6 +215,7 @@ foreach ($object->fields as $key => $val) { $arrayfields['country.code_iso'] = array('label'=>"Country", 'position'=>66, 'checked'=>0); if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) { $arrayfields['s.nom'] = array('label'=>"ThirdParty", 'position'=>113, 'checked'=> 1); + $arrayfields['s.name_alias'] = array('label'=>"AliasNameShort", 'position'=>114, 'checked'=> 1); } $arrayfields['unsubscribed'] = array( @@ -277,6 +280,7 @@ if (empty($reshook)) { $search_lastname = ""; $search_firstname = ""; $search_societe = ""; + $search_societe_alias = ""; $search_town = ""; $search_address = ""; $search_zip = ""; @@ -372,7 +376,7 @@ if ($resql) { dol_print_error($db); } -$sql = "SELECT s.rowid as socid, s.nom as name,"; +$sql = "SELECT s.rowid as socid, s.nom as name, s.name_alias as alias,"; $sql .= " p.rowid, p.lastname as lastname, p.statut, p.firstname, p.address, p.zip, p.town, p.poste, p.email,"; $sql .= " p.socialnetworks, p.photo,"; $sql .= " p.phone as phone_pro, p.phone_mobile, p.phone_perso, p.fax, p.fk_pays, p.priv, p.datec as date_creation, p.tms as date_update,"; @@ -544,8 +548,15 @@ if ($search_lastname) { if ($search_firstname) { $sql .= natural_search('p.firstname', $search_firstname); } -if ($search_societe) { - $sql .= natural_search(empty($conf->global->SOCIETE_DISABLE_CONTACTS) ? 's.nom' : 'p.fk_soc', $search_societe); +if (empty($arrayfields['s.name_alias']['checked']) && $search_societe) { + $sql .= natural_search(array("s.nom", "s.name_alias"), $search_societe); +} else { + if ($search_societe) { + $sql .= natural_search('s.nom', $search_societe); + } + if ($search_societe_alias) { + $sql .= natural_search('s.name_alias', $search_societe_alias); + } } if ($search_country) { $sql .= " AND p.fk_pays IN (".$db->sanitize($search_country).')'; @@ -676,6 +687,9 @@ if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && ( exit; } +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Módulo_Empresas'; llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist'); @@ -712,6 +726,9 @@ if ($search_firstname != '') { if ($search_societe != '') { $param .= '&search_societe='.urlencode($search_societe); } +if ($search_societe_alias != '') { + $param .= '&search_societe_alias='.urlencode($search_societe_alias); +} if ($search_address != '') { $param .= '&search_address='.urlencode($search_address); } @@ -984,6 +1001,12 @@ if (!empty($arrayfields['p.fk_soc']['checked']) || !empty($arrayfields['s.nom'][ print ''; print ''; } +// Alias +if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; +} if (!empty($arrayfields['p.priv']['checked'])) { print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Private/Public if (!empty($arrayfields['p.priv']['checked'])) { print ''; From 07ba47dff8a89f9e37d2cbdda66ce67838f8ed82 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 16:31:38 +0100 Subject: [PATCH 256/816] css --- htdocs/theme/eldy/global.inc.php | 5 +++++ htdocs/theme/md/style.css.php | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index daeb574a9dd..fe18193910d 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -171,6 +171,11 @@ table.liste th.wrapcolumntitle.liste_titre_sel:not(.maxwidthsearch), table.liste max-width: 100px; text-overflow: ellipsis; } +th.wrapcolumntitle dl dt a span.fas.fa-list { + padding-bottom: 0; + vertical-align: bottom; +} + /*.liste_titre input[name=month_date_when], .liste_titre input[name=monthvalid], .liste_titre input[name=search_ordermonth], .liste_titre input[name=search_deliverymonth], .liste_titre input[name=search_smonth], .liste_titre input[name=search_month], .liste_titre input[name=search_emonth], .liste_titre input[name=smonth], .liste_titre input[name=month], .liste_titre select[name=month], .liste_titre select[name=year], diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index b4ff8bb18b6..b59eb7ebd10 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -485,6 +485,11 @@ th.wrapcolumntitle.liste_titre_sel:not(.maxwidthsearch), td.wrapcolumntitle.list max-width: 120px; text-overflow: ellipsis; } +th.wrapcolumntitle dl dt a span.fas.fa-list { + padding-bottom: 0; + vertical-align: bottom; +} + .liste_titre input[name=month_date_when], .liste_titre input[name=monthvalid], .liste_titre input[name=search_ordermonth], .liste_titre input[name=search_deliverymonth], .liste_titre input[name=search_smonth], .liste_titre input[name=search_month], .liste_titre input[name=search_emonth], .liste_titre input[name=smonth], .liste_titre input[name=month], .liste_titre input[name=month_lim], .liste_titre input[name=month_start], .liste_titre input[name=month_end], .liste_titre input[name=month_create], From c84d17eced5d2a922b89b85a30ba61f6b680dbcf Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Mon, 2 Jan 2023 16:58:33 +0100 Subject: [PATCH 257/816] FIX : filter only if t.task_duration checked --- htdocs/projet/tasks/time.php | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 8c98e6387b1..6652b57304a 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -1629,16 +1629,20 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser $sql .= " AND t.task_date <= '".$db->idate($search_date_end)."'"; } - if($search_timespent_starthour || $search_timespent_startmin) { - $timespent_duration_start = $search_timespent_starthour * 60 * 60; // We store duration in seconds - $timespent_duration_start += ($search_timespent_startmin ? $search_timespent_startmin : 0) * 60; // We store duration in seconds - $sql .= " AND t.task_duration >= ".$timespent_duration_start; - } + if (!empty($arrayfields['t.task_duration']['checked'])) { - if($search_timespent_endhour || $search_timespent_endmin) { - $timespent_duration_end = $search_timespent_endhour * 60 * 60; // We store duration in seconds - $timespent_duration_end += ($search_timespent_endmin ? $search_timespent_endmin : 0) * 60; // We store duration in seconds - $sql .= " AND t.task_duration <= ".$timespent_duration_end; + if ($search_timespent_starthour || $search_timespent_startmin) { + $timespent_duration_start = $search_timespent_starthour * 60 * 60; // We store duration in seconds + $timespent_duration_start += ($search_timespent_startmin ? $search_timespent_startmin : 0) * 60; // We store duration in seconds + $sql .= " AND t.task_duration >= " . $timespent_duration_start; + } + + if ($search_timespent_endhour || $search_timespent_endmin) { + $timespent_duration_end = $search_timespent_endhour * 60 * 60; // We store duration in seconds + $timespent_duration_end += ($search_timespent_endmin ? $search_timespent_endmin : 0) * 60; // We store duration in seconds + $sql .= " AND t.task_duration <= " . $timespent_duration_end; + } + } $sql .= dolSqlDateFilter('t.task_datehour', $search_day, $search_month, $search_year); From c3f44859ae61968e1db1d6846f53777201eed225 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 17:33:11 +0100 Subject: [PATCH 258/816] Debug v17 --- htdocs/admin/oauth.php | 7 ++++--- htdocs/admin/oauthlogintokens.php | 8 +++++++- htdocs/core/modules/oauth/google_oauthcallback.php | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/oauth.php b/htdocs/admin/oauth.php index 64968b1a516..217dfd63cc9 100644 --- a/htdocs/admin/oauth.php +++ b/htdocs/admin/oauth.php @@ -285,7 +285,7 @@ if (count($listinsetup) > 0) { // Delete print ''; print ''; - print ''; print ''; print ''; @@ -306,7 +307,7 @@ if (count($listinsetup) > 0) { if ($keyforsupportedoauth2array == 'OAUTH_OTHER_NAME') { print ''; print ''; - print ''; print ''; print ''; diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php index f798995d525..9a0532880cd 100644 --- a/htdocs/admin/oauthlogintokens.php +++ b/htdocs/admin/oauthlogintokens.php @@ -213,7 +213,13 @@ if ($mode == 'setup' && $user->admin) { $urltocheckperms = ''; } - $urltorenew .= '&keyforprovider='.urlencode($keyforprovider); + if ($urltorenew) { + $urltorenew .= '&keyforprovider='.urlencode($keyforprovider); + } + if ($urltodelete) { + $urltodelete .= '&keyforprovider='.urlencode($keyforprovider); + } + // Show value of token $tokenobj = null; diff --git a/htdocs/core/modules/oauth/google_oauthcallback.php b/htdocs/core/modules/oauth/google_oauthcallback.php index b993cbdd81e..80c39d85158 100644 --- a/htdocs/core/modules/oauth/google_oauthcallback.php +++ b/htdocs/core/modules/oauth/google_oauthcallback.php @@ -42,7 +42,7 @@ $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domai $action = GETPOST('action', 'aZ09'); $backtourl = GETPOST('backtourl', 'alpha'); $keyforprovider = GETPOST('keyforprovider', 'aZ09'); -if (empty($keyforprovider) && !empty($_SESSION["oauthkeyforproviderbeforeoauthjump"]) && (GETPOST('code') || $action == 'delete')) { +if (!GETPOSTISSET('keyforprovider', 'aZ09') && !empty($_SESSION["oauthkeyforproviderbeforeoauthjump"]) && (GETPOST('code') || $action == 'delete')) { // If we are coming from the Oauth page $keyforprovider = $_SESSION["oauthkeyforproviderbeforeoauthjump"]; } From 4ddf0b27dc10268344c35e5db9c998af794270d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20N=C3=BA=C3=B1ez?= Date: Mon, 2 Jan 2023 18:15:33 +0100 Subject: [PATCH 259/816] NEW create email substitution variable for intervention signature URL --- htdocs/core/lib/functions.lib.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 977342b1457..d5c3652ebdb 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7659,6 +7659,9 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, if (isModEnabled("propal") && (!is_object($object) || $object->element == 'propal')) { $substitutionarray['__ONLINE_SIGN_URL__'] = 'ToOfferALinkForOnlineSignature'; } + if (isModEnabled("ficheinter") && (!is_object($object) || $object->element == 'fichinter')) { + $substitutionarray['__ONLINE_SIGN_FICHINTER_URL__'] = 'ToOfferALinkForOnlineSignature'; + } $substitutionarray['__ONLINE_PAYMENT_URL__'] = 'UrlToPayOnlineIfApplicable'; $substitutionarray['__ONLINE_PAYMENT_TEXT_AND_URL__'] = 'TextAndUrlToPayOnlineIfApplicable'; $substitutionarray['__SECUREKEYPAYMENT__'] = 'Security key (if key is not unique per record)'; @@ -7929,6 +7932,10 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, require_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php'; $substitutionarray['__ONLINE_SIGN_URL__'] = getOnlineSignatureUrl(0, 'proposal', $object->ref); } + if (is_object($object) && $object->element == 'fichinter') { + require_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php'; + $substitutionarray['__ONLINE_SIGN_FICHINTER_URL__'] = getOnlineSignatureUrl(0, 'fichinter', $object->ref); + } if (!empty($conf->global->PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD) && is_object($object) && $object->element == 'propal') { $substitutionarray['__DIRECTDOWNLOAD_URL_PROPOSAL__'] = $object->getLastMainDocLink($object->element); } else { From 6a085ad60246dd4d73b8943959ef61d2bd2d3127 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 19:01:15 +0100 Subject: [PATCH 260/816] css --- htdocs/theme/eldy/global.inc.php | 2 +- htdocs/theme/md/style.css.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index b4ff1774054..46e34549731 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -172,7 +172,7 @@ table.liste th.wrapcolumntitle.liste_titre_sel:not(.maxwidthsearch), table.liste text-overflow: ellipsis; } th.wrapcolumntitle dl dt a span.fas.fa-list { - padding-bottom: 0; + padding-bottom: 1px; vertical-align: bottom; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 59cadcb3763..9a341e56b3b 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -486,7 +486,7 @@ th.wrapcolumntitle.liste_titre_sel:not(.maxwidthsearch), td.wrapcolumntitle.list text-overflow: ellipsis; } th.wrapcolumntitle dl dt a span.fas.fa-list { - padding-bottom: 0; + padding-bottom: 1px; vertical-align: bottom; } From 9478cd6ad320a43c67006c9d354f84c2fbae1359 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 19:09:27 +0100 Subject: [PATCH 261/816] Doc --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index bbb01cfd3cf..68b22cc4f8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -166,7 +166,7 @@ NEW: show product label on inventory NEW: show sell-by and eat-by dates only if not empty NEW: show SellBy/EatBy dates for each batch product in shipment card NEW: skip accept/refuse process for proposals (option PROPAL_SKIP_ACCEPT_REFUSE) -NEW: SMTP using oauth2 authentication +NEW: experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP) NEW: can substitue project title in mail template NEW: Supplier order list - Add column private and public note NEW: Support IP type in extrafields From 3147c3a8d2548060db1fed4d4700b11ac0ecf845 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 19:01:15 +0100 Subject: [PATCH 262/816] css --- htdocs/theme/eldy/global.inc.php | 2 +- htdocs/theme/md/style.css.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index fe18193910d..de4b84b5975 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -172,7 +172,7 @@ table.liste th.wrapcolumntitle.liste_titre_sel:not(.maxwidthsearch), table.liste text-overflow: ellipsis; } th.wrapcolumntitle dl dt a span.fas.fa-list { - padding-bottom: 0; + padding-bottom: 1px; vertical-align: bottom; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index b59eb7ebd10..78b962aa87d 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -486,7 +486,7 @@ th.wrapcolumntitle.liste_titre_sel:not(.maxwidthsearch), td.wrapcolumntitle.list text-overflow: ellipsis; } th.wrapcolumntitle dl dt a span.fas.fa-list { - padding-bottom: 0; + padding-bottom: 1px; vertical-align: bottom; } From d62fb2af64eea3dab5bd1c20826f43f4f4f9edfe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 20:15:34 +0100 Subject: [PATCH 263/816] css --- htdocs/core/lib/functions.lib.php | 2 +- htdocs/societe/list.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 4724bf85d50..a600761d9b9 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2198,7 +2198,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi // If the preview file is found if (file_exists($fileimage)) { $phototoshow = '
'; - $phototoshow .= ''; + $phototoshow .= ''; $phototoshow .= '
'; } } diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 84a8d355c1a..f0ef18e4dfd 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -113,6 +113,7 @@ $place = GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : '0'; // $place is $diroutputmassaction = $conf->societe->dir_output.'/temp/massgeneration/'.$user->id; +// Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); @@ -770,6 +771,7 @@ $num = $db->num_rows($resql); $arrayofselected = is_array($toselect) ? $toselect : array(); +// Direct jump if only one record found if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && ($search_all != '' || $search_cti != '') && $action != 'list') { $obj = $db->fetch_object($resql); $id = $obj->rowid; @@ -1011,6 +1013,7 @@ foreach (array(1, 2, 3, 4, 5, 6) as $key) { } } +// Add code for pre mass action (confirmation or email presend form) $topicmail = "Information"; $modelmail = "thirdparty"; $objecttmp = new Societe($db); From 2dfb8c049683153e257610600d730801e053ef59 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 2 Jan 2023 20:26:46 +0100 Subject: [PATCH 264/816] Clean code --- htdocs/core/lib/files.lib.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 82831424ccd..47b3955e617 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1991,7 +1991,6 @@ function deleteFilesIntoDatabaseIndex($dir, $file, $mode = 'uploaded') */ function dol_convert_file($fileinput, $ext = 'png', $fileoutput = '', $page = '') { - global $langs; if (class_exists('Imagick')) { $image = new Imagick(); try { From 94fb344bd67c5910b8e681d74e7677e864270ea7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 02:02:34 +0100 Subject: [PATCH 265/816] FIX #22271 --- htdocs/imports/import.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index dfe2d0b9d49..a6982bd0a4e 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -815,18 +815,22 @@ if ($step == 4 && $datatoimport) { $array_match_file_to_database = array(); } - // Load source fields in input file + // Load the source fields from input file into variable $arrayrecord $fieldssource = array(); $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport, $langs); if ($result >= 0) { // Read first line $arrayrecord = $obj->import_read_record(); - // Put into array fieldssource starting with 1. + + // Create array $fieldssource starting with 1 with values found of first line. $i = 1; foreach ($arrayrecord as $key => $val) { if ($val["type"] != -1) { $fieldssource[$i]['example1'] = dol_trunc($val['val'], 128); $i++; + } else { + $fieldssource[$i]['example1'] = $langs->trans('Empty'); + $i++; } } $obj->import_close_file(); From 496cff016713848127b458ef027d9dc64ea05eb0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 02:29:49 +0100 Subject: [PATCH 266/816] Debug v17 --- htdocs/accountancy/admin/account.php | 77 ++++++++++++++----- htdocs/accountancy/bookkeeping/list.php | 10 +++ .../accountancy/bookkeeping/listbyaccount.php | 10 +++ htdocs/langs/en_US/accountancy.lang | 2 + 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/htdocs/accountancy/admin/account.php b/htdocs/accountancy/admin/account.php index 21d60103135..91b7673ab81 100644 --- a/htdocs/accountancy/admin/account.php +++ b/htdocs/accountancy/admin/account.php @@ -47,6 +47,7 @@ $search_label = GETPOST('search_label', 'alpha'); $search_labelshort = GETPOST('search_labelshort', 'alpha'); $search_accountparent = GETPOST('search_accountparent', 'alpha'); $search_pcgtype = GETPOST('search_pcgtype', 'alpha'); +$search_import_key = GETPOST('search_import_key', 'alpha'); $toselect = GETPOST('toselect', 'array'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $confirm = GETPOST('confirm', 'alpha'); @@ -83,16 +84,19 @@ if (!$sortorder) { } $arrayfields = array( - 'aa.account_number'=>array('label'=>$langs->trans("AccountNumber"), 'checked'=>1), - 'aa.label'=>array('label'=>$langs->trans("Label"), 'checked'=>1), - 'aa.labelshort'=>array('label'=>$langs->trans("LabelToShow"), 'checked'=>1), - 'aa.account_parent'=>array('label'=>$langs->trans("Accountparent"), 'checked'=>1), - 'aa.pcg_type'=>array('label'=>$langs->trans("Pcgtype"), 'checked'=>1, 'help'=>'PcgtypeDesc'), - 'aa.reconcilable'=>array('label'=>$langs->trans("Reconcilable"), 'checked'=>1), - 'aa.active'=>array('label'=>$langs->trans("Activated"), 'checked'=>1) + 'aa.account_number'=>array('label'=>"AccountNumber", 'checked'=>1), + 'aa.label'=>array('label'=>"Label", 'checked'=>1), + 'aa.labelshort'=>array('label'=>"LabelToShow", 'checked'=>1), + 'aa.account_parent'=>array('label'=>"Accountparent", 'checked'=>1), + 'aa.pcg_type'=>array('label'=>"Pcgtype", 'checked'=>1, 'help'=>'PcgtypeDesc'), + 'categories'=>array('label'=>"AccountingCategories", 'checked'=>-1, 'help'=>'AccountingCategoriesDesc'), + 'aa.reconcilable'=>array('label'=>"Reconcilable", 'checked'=>1), + 'aa.active'=>array('label'=>"Activated", 'checked'=>1), + 'aa.import_key'=>array('label'=>"ImportId", 'checked'=>-1) ); if ($conf->global->MAIN_FEATURES_LEVEL < 2) { + unset($arrayfields['categories']); unset($arrayfields['aa.reconcilable']); } @@ -226,15 +230,12 @@ if ($action == 'delete') { $pcgver = $conf->global->CHARTOFACCOUNTS; -$sql = "SELECT aa.rowid, aa.fk_pcg_version, aa.pcg_type, aa.account_number, aa.account_parent , aa.label, aa.labelshort, aa.reconcilable, aa.active, "; +$sql = "SELECT aa.rowid, aa.fk_pcg_version, aa.pcg_type, aa.account_number, aa.account_parent, aa.label, aa.labelshort, aa.fk_accounting_category,"; +$sql .= " aa.reconcilable, aa.active, aa.import_key,"; $sql .= " a2.rowid as rowid2, a2.label as label2, a2.account_number as account_number2"; $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa"; -$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version AND aa.entity = ".$conf->entity; -if ($db->type == 'pgsql') { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as a2 ON a2.rowid = aa.account_parent AND a2.entity = ".$conf->entity; -} else { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as a2 ON a2.rowid = aa.account_parent AND a2.entity = ".$conf->entity; -} +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version AND aa.entity = ".((int) $conf->entity); +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as a2 ON a2.rowid = aa.account_parent AND a2.entity = ".((int) $conf->entity); $sql .= " WHERE asy.rowid = ".((int) $pcgver); //print $sql; if (strlen(trim($search_account))) { @@ -337,6 +338,9 @@ if ($resql) { if ($search_pcgtype) { $param .= '&search_pcgtype='.urlencode($search_pcgtype); } + if ($optioncss != '') { + $param .= '&search_import_key='.urlencode($search_import_key); + } if ($optioncss != '') { $param .= '&optioncss='.urlencode($optioncss); } @@ -439,8 +443,17 @@ if ($resql) { print $formaccounting->select_account($search_accountparent, 'search_accountparent', 2, array(), 0, 0, 'maxwidth150'); print ''; } + // Predefined group if (!empty($arrayfields['aa.pcg_type']['checked'])) { - print '
'; + print ''; + } + // Custom groups + if (!empty($arrayfields['categories']['checked'])) { + print ''; + } + // Import key + if (!empty($arrayfields['aa.import_key']['checked'])) { + print ''; } if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { if (!empty($arrayfields['aa.reconcilable']['checked'])) { @@ -471,6 +484,12 @@ if ($resql) { if (!empty($arrayfields['aa.pcg_type']['checked'])) { print_liste_field_titre($arrayfields['aa.pcg_type']['label'], $_SERVER["PHP_SELF"], 'aa.pcg_type,aa.account_number', '', $param, '', $sortfield, $sortorder, '', $arrayfields['aa.pcg_type']['help'], 1); } + if (!empty($arrayfields['categories']['checked'])) { + print_liste_field_titre($arrayfields['categories']['label'], $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, '', $arrayfields['categories']['help'], 1); + } + if (!empty($arrayfields['aa.import_key']['checked'])) { + print_liste_field_titre($arrayfields['aa.import_key']['label'], $_SERVER["PHP_SELF"], 'aa.import_key', '', $param, '', $sortfield, $sortorder, '', $arrayfields['aa.import_key']['help'], 1); + } if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { if (!empty($arrayfields['aa.reconcilable']['checked'])) { print_liste_field_titre($arrayfields['aa.reconcilable']['label'], $_SERVER["PHP_SELF"], 'aa.reconcilable', '', $param, '', $sortfield, $sortorder); @@ -505,7 +524,7 @@ if ($resql) { // Account label if (!empty($arrayfields['aa.label']['checked'])) { print "\n"; if (!$i) { $totalarray['nbfield']++; @@ -515,7 +534,7 @@ if ($resql) { // Account label to show (label short) if (!empty($arrayfields['aa.labelshort']['checked'])) { print "\n"; if (!$i) { $totalarray['nbfield']++; @@ -549,10 +568,30 @@ if ($resql) { } } - // Chart of accounts type + // Predefined group (deprecated) if (!empty($arrayfields['aa.pcg_type']['checked'])) { print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Custom accounts + if (!empty($arrayfields['categories']['checked'])) { + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Import id + if (!empty($arrayfields['aa.import_key']['checked'])) { + print "\n"; if (!$i) { $totalarray['nbfield']++; diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 2b2df70d647..fa42b5bd6fd 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -1511,6 +1511,16 @@ while ($i < min($num, $limit)) { // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 4a6e37ceb29..29596f0a124 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -1232,6 +1232,16 @@ if ($num > 0 && $colspan > 0) { // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index b6bf1b90aef..9822a52e8f0 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -218,6 +218,7 @@ JournalLabel=Journal label NumPiece=Piece number TransactionNumShort=Num. transaction AccountingCategory=Custom group +AccountingCategories=Custom groups GroupByAccountAccounting=Group by general ledger account GroupBySubAccountAccounting=Group by subledger account AccountingAccountGroupsDesc=You can define here some groups of accounting account. They will be used for personalized accounting reports. @@ -265,6 +266,7 @@ ShowSubtotalByGroup=Show subtotal by level Pcgtype=Group of account PcgtypeDesc=Group of account are used as predefined 'filter' and 'grouping' criteria for some accounting reports. For example, 'INCOME' or 'EXPENSE' are used as groups for accounting accounts of products to build the expense/income report. +AccountingCategoriesDesc=Custom group of accounts can be used to group accounting accounts into one name to ease filter use or building of custom reports. Reconcilable=Reconcilable From 61ec6f5226f0d7d1d0c92e8e0cceb4452cd3a004 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 02:44:38 +0100 Subject: [PATCH 267/816] Doc --- htdocs/core/doxygen.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/doxygen.php b/htdocs/core/doxygen.php index ac66362a89f..06a2510dfef 100644 --- a/htdocs/core/doxygen.php +++ b/htdocs/core/doxygen.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2008-2022 Laurent Destailleur * Copyright (C) 2009 Regis Houssin * * This program is free software; you can redistribute it and/or modify @@ -23,7 +23,7 @@ * \mainpage Dolibarr project * * This is source documentation for Dolibarr ERP/CRM.
- * This documentation can be built or updated running the script dolibarr-doxygen-build.pl or from Eclipse with Doxygen plugin.
+ * This documentation can be built or updated running the script build/doxygen/dolibarr-doxygen-build.pl or from Eclipse with Doxygen plugin.
*
* Dolibarr official web site: www.dolibarr.org
*
From a0a6ab72415e85431b51d982e6f16b2afad84d2d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 02:46:05 +0100 Subject: [PATCH 268/816] Doc --- htdocs/core/doxygen.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/doxygen.php b/htdocs/core/doxygen.php index 06a2510dfef..1e66b348ef8 100644 --- a/htdocs/core/doxygen.php +++ b/htdocs/core/doxygen.php @@ -20,7 +20,7 @@ /** * \file htdocs/core/doxygen.php * \ingroup core - * \mainpage Dolibarr project + * \mainpage Dolibarr documentation of source code * * This is source documentation for Dolibarr ERP/CRM.
* This documentation can be built or updated running the script build/doxygen/dolibarr-doxygen-build.pl or from Eclipse with Doxygen plugin.
From 5978f404614fc31fe35f9d904152636fcd2d1fde Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 10:27:54 +0100 Subject: [PATCH 269/816] Fix user status --- htdocs/societe/list.php | 2 +- htdocs/user/class/user.class.php | 12 +++++++++--- htdocs/user/list.php | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 129e6ed63d4..3e69b1ff76e 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -1314,7 +1314,7 @@ if (!empty($arrayfields['s.tms']['checked'])) { // Status if (!empty($arrayfields['s.status']['checked'])) { print '
'; } if (!empty($arrayfields['s.import_key']['checked'])) { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index ebc49db57d3..a3445e3939f 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -436,7 +436,7 @@ class User extends CommonObject $sql .= " u.admin, u.login, u.note_private, u.note_public,"; $sql .= " u.pass, u.pass_crypted, u.pass_temp, u.api_key,"; $sql .= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid, u.fk_user_expense_validator, u.fk_user_holiday_validator,"; - $sql .= " u.statut, u.lang, u.entity,"; + $sql .= " u.statut as status, u.lang, u.entity,"; $sql .= " u.datec as datec,"; $sql .= " u.tms as datem,"; $sql .= " u.datelastlogin as datel,"; @@ -553,7 +553,10 @@ class User extends CommonObject $this->note_public = $obj->note_public; $this->note_private = $obj->note_private; $this->note = $obj->note_private; // deprecated - $this->statut = $obj->statut; + + $this->statut = $obj->status; // deprecated + $this->status = $obj->status; + $this->photo = $obj->photo; $this->openid = $obj->openid; $this->lang = $obj->lang; @@ -1349,7 +1352,10 @@ class User extends CommonObject $error = 0; // Check parameters - if ($this->statut == $status) { + if (isset($this->statut) && $this->statut == $status) { + return 0; + } + if (isset($this->status) && $this->status == $status) { return 0; } diff --git a/htdocs/user/list.php b/htdocs/user/list.php index 8610113f0da..d3139b438e2 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -800,7 +800,7 @@ if (!empty($arrayfields['u.tms']['checked'])) { if (!empty($arrayfields['u.statut']['checked'])) { // Status print ''; } // Action column From 37ce175d538a2382334b914dbf071976a41a7896 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 10:27:54 +0100 Subject: [PATCH 270/816] Fix user status --- htdocs/societe/list.php | 2 +- htdocs/user/class/user.class.php | 12 +++++++++--- htdocs/user/list.php | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index f0ef18e4dfd..96666b28d8c 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -1311,7 +1311,7 @@ if (!empty($arrayfields['s.tms']['checked'])) { // Status if (!empty($arrayfields['s.status']['checked'])) { print ''; } if (!empty($arrayfields['s.import_key']['checked'])) { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index dddcaa0ca6a..744e24fe15a 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -436,7 +436,7 @@ class User extends CommonObject $sql .= " u.admin, u.login, u.note_private, u.note_public,"; $sql .= " u.pass, u.pass_crypted, u.pass_temp, u.api_key,"; $sql .= " u.fk_soc, u.fk_socpeople, u.fk_member, u.fk_user, u.ldap_sid, u.fk_user_expense_validator, u.fk_user_holiday_validator,"; - $sql .= " u.statut, u.lang, u.entity,"; + $sql .= " u.statut as status, u.lang, u.entity,"; $sql .= " u.datec as datec,"; $sql .= " u.tms as datem,"; $sql .= " u.datelastlogin as datel,"; @@ -553,7 +553,10 @@ class User extends CommonObject $this->note_public = $obj->note_public; $this->note_private = $obj->note_private; $this->note = $obj->note_private; // deprecated - $this->statut = $obj->statut; + + $this->statut = $obj->status; // deprecated + $this->status = $obj->status; + $this->photo = $obj->photo; $this->openid = $obj->openid; $this->lang = $obj->lang; @@ -1350,7 +1353,10 @@ class User extends CommonObject $error = 0; // Check parameters - if ($this->statut == $status) { + if (isset($this->statut) && $this->statut == $status) { + return 0; + } + if (isset($this->status) && $this->status == $status) { return 0; } diff --git a/htdocs/user/list.php b/htdocs/user/list.php index 8610113f0da..d3139b438e2 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -800,7 +800,7 @@ if (!empty($arrayfields['u.tms']['checked'])) { if (!empty($arrayfields['u.statut']['checked'])) { // Status print ''; } // Action column From 9f02bd2350ed9b256c7f2d978cb9514e521df3e7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 11:32:33 +0100 Subject: [PATCH 271/816] Debug v17 --- htdocs/user/class/user.class.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 744e24fe15a..e90252877d1 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1353,10 +1353,11 @@ class User extends CommonObject $error = 0; // Check parameters - if (isset($this->statut) && $this->statut == $status) { - return 0; - } - if (isset($this->status) && $this->status == $status) { + if (isset($this->statut)) { + if ($this->statut == $status) { + return 0; + } + } elseif (isset($this->status) && $this->status == $status) { return 0; } @@ -3259,7 +3260,8 @@ class User extends CommonObject $this->iplastlogin = '127.0.0.1'; $this->datepreviouslogin = $now; $this->ippreviouslogin = '127.0.0.1'; - $this->statut = 1; + $this->statut = 1; // deprecated + $this->status = 1; $this->entity = 1; return 1; From 797b9c90548f27755cb5c68c9acb7cd9f780eeb8 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 3 Jan 2023 11:42:39 +0100 Subject: [PATCH 272/816] dfelete cem data on product deletion --- htdocs/product/class/product.class.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 0900f11ed29..e133e1a42f4 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1408,6 +1408,14 @@ class Product extends CommonObject } } + // Delete record into ECM index and physically + if (!$error) { + $res = $this->deleteEcmFiles(0); // Deleting files physically is done later with the dol_delete_dir_recursive + if (!$res) { + $error++; + } + } + if (!$error) { // We remove directory $ref = dol_sanitizeFileName($this->ref); From ea1ad5243f7b3e4f96b99c6a6edcc1c3072a04f7 Mon Sep 17 00:00:00 2001 From: Florent Poinsaut Date: Thu, 22 Dec 2022 16:31:55 +0000 Subject: [PATCH 273/816] fix supplier invoice import --- htdocs/core/modules/modFournisseur.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php index 7bd10fcaf9b..b6286c35162 100644 --- a/htdocs/core/modules/modFournisseur.class.php +++ b/htdocs/core/modules/modFournisseur.class.php @@ -587,6 +587,9 @@ class modFournisseur extends DolibarrModules } // End add extra fields $this->import_fieldshidden_array[$r] = array('extra.fk_object' => 'lastrowid-'.MAIN_DB_PREFIX.'facture_fourn'); + if (empty($conf->multicurrency->enabled)) { + $this->import_fieldshidden_array[$r]['f.multicurrency_code'] = 'const-'.$conf->currency; + } $this->import_regex_array[$r] = array('f.ref' => '(SI\d{4}-\d{4}|PROV.{1,32}$)', 'f.multicurrency_code' => 'code@'.MAIN_DB_PREFIX.'multicurrency'); $import_sample = array( 'f.ref' => '(PROV001)', From 7fd82ccc45d59409c40bc3c29feb4b13b4553fd1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 12:08:04 +0100 Subject: [PATCH 274/816] NEW formconfirm can support field with format datetime --- htdocs/core/class/html.form.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 6655215a4f7..71df1296fc7 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5010,7 +5010,7 @@ class Form * @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', 'select', 'multiselect', 'morecss', + * '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 @@ -5141,11 +5141,11 @@ class Form $more .= ''."\n"; $i++; } - } elseif ($input['type'] == 'date') { + } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') { $more .= '
'.$input['label'].'
'; $more .= '
'; $addnowlink = (empty($input['datenow']) ? 0 : 1); - $more .= $this->selectDate($input['value'], $input['name'], 0, 0, 0, '', 1, $addnowlink); + $more .= $this->selectDate($input['value'], $input['name'], ($input['type'] == 'datetime' ? 1 : 0), ($input['type'] == 'datetime' ? 1 : 0), 0, '', 1, $addnowlink); $more .= '
'."\n"; $formquestion[] = array('name'=>$input['name'].'day'); $formquestion[] = array('name'=>$input['name'].'month'); From b8b1eb603559cb33e8df617e2b0dae9204c36a73 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 12:08:04 +0100 Subject: [PATCH 275/816] NEW formconfirm can support field with format datetime --- htdocs/core/class/html.form.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index c33ffe28551..5a2efa07f40 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5001,7 +5001,7 @@ class Form * @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', 'select', 'multiselect', 'morecss', + * '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 @@ -5132,11 +5132,11 @@ class Form $more .= ''."\n"; $i++; } - } elseif ($input['type'] == 'date') { + } elseif ($input['type'] == 'date' || $input['type'] == 'datetime') { $more .= '
'.$input['label'].'
'; $more .= '
'; $addnowlink = (empty($input['datenow']) ? 0 : 1); - $more .= $this->selectDate($input['value'], $input['name'], 0, 0, 0, '', 1, $addnowlink); + $more .= $this->selectDate($input['value'], $input['name'], ($input['type'] == 'datetime' ? 1 : 0), ($input['type'] == 'datetime' ? 1 : 0), 0, '', 1, $addnowlink); $more .= '
'."\n"; $formquestion[] = array('name'=>$input['name'].'day'); $formquestion[] = array('name'=>$input['name'].'month'); From 3e36e9831e137d427777055829f18e4ed1032ea9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 13:03:27 +0100 Subject: [PATCH 276/816] Fix warnings --- htdocs/admin/syslog.php | 3 -- htdocs/core/class/ctyperesource.class.php | 4 -- .../class/stocktransfer.class.php | 52 +++++-------------- .../class/stocktransferline.class.php | 36 ------------- .../class/companypaymentmode.class.php | 26 ---------- htdocs/website/class/websitepage.class.php | 39 ++++---------- .../workstation/class/workstation.class.php | 36 ------------- 7 files changed, 22 insertions(+), 174 deletions(-) diff --git a/htdocs/admin/syslog.php b/htdocs/admin/syslog.php index 71f7fd7f875..cf07dd49539 100644 --- a/htdocs/admin/syslog.php +++ b/htdocs/admin/syslog.php @@ -115,9 +115,6 @@ if ($action == 'set') { // Check configuration foreach ($activeModules as $modulename) { - /** - * @var LogHandler - */ $module = new $modulename; $error = $module->checkConfiguration(); } diff --git a/htdocs/core/class/ctyperesource.class.php b/htdocs/core/class/ctyperesource.class.php index be83877098c..88f6960a9f9 100644 --- a/htdocs/core/class/ctyperesource.class.php +++ b/htdocs/core/class/ctyperesource.class.php @@ -468,8 +468,4 @@ class CtyperesourceLine public $label; public $active; - - /** - * @var mixed Sample line property 2 - */ } diff --git a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php index 60f13396b80..84182736a0a 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php @@ -57,11 +57,19 @@ class StockTransfer extends CommonObject */ public $isextrafieldmanaged = 1; + /** - * @var string Customer ref - * @deprecated - * @see $ref_customer - */ + * @var array List of child tables. To know object to delete on cascade. + * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + */ + protected $childtablesoncascade = array('stocktransfer_stocktransferline'); + + /** + * @var string Customer ref + * @deprecated + * @see $ref_customer + */ public $ref_client; /** @@ -162,42 +170,6 @@ class StockTransfer extends CommonObject // END MODULEBUILDER PROPERTIES - // If this object has a subtable with lines - - /** - * @var int Name of subtable line - */ - public $table_element_line = 'stocktransfer_stocktransferline'; - - /** - * @var int Field with ID of parent key if this object has a parent - */ - public $fk_element = 'fk_stocktransfer'; - - /** - * @var int Name of subtable class that manage subtable lines - */ - //public $class_element_line = 'StockTransferline'; - - /** - * @var array List of child tables. To test if we can delete object. - */ - //protected $childtables = array(); - - /** - * @var array List of child tables. To know object to delete on cascade. - * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will - * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object - */ - protected $childtablesoncascade = array('stocktransfer_stocktransferline'); - - /** - * @var StockTransferLine[] Array of subtable lines - */ - //public $lines = array(); - - - /** * Constructor * diff --git a/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php b/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php index 4ee2f1db631..65252efa106 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php @@ -117,42 +117,6 @@ class StockTransferLine extends CommonObjectLine // END MODULEBUILDER PROPERTIES - // If this object has a subtable with lines - - /** - * @var int Name of subtable line - */ - //public $table_element_line = 'stocktransfer_stocktransferlineline'; - - /** - * @var int Field with ID of parent key if this object has a parent - */ - //public $fk_element = 'fk_stocktransferline'; - - /** - * @var int Name of subtable class that manage subtable lines - */ - //public $class_element_line = 'StockTransferLineline'; - - /** - * @var array List of child tables. To test if we can delete object. - */ - //protected $childtables = array(); - - /** - * @var array List of child tables. To know object to delete on cascade. - * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will - * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object - */ - //protected $childtablesoncascade = array('stocktransfer_stocktransferlinedet'); - - /** - * @var StockTransferLineLine[] Array of subtable lines - */ - //public $lines = array(); - - - /** * Constructor * diff --git a/htdocs/societe/class/companypaymentmode.class.php b/htdocs/societe/class/companypaymentmode.class.php index 17889026e89..eb77a928f14 100644 --- a/htdocs/societe/class/companypaymentmode.class.php +++ b/htdocs/societe/class/companypaymentmode.class.php @@ -195,32 +195,6 @@ class CompanyPaymentMode extends CommonObject // END MODULEBUILDER PROPERTIES - - // If this object has a subtable with lines - - /** - * @var string Name of subtable line - */ - //public $table_element_line = 'companypaymentmodedet'; - /** - * @var string Field with ID of parent key if this field has a parent - */ - //public $fk_element = 'fk_companypaymentmode'; - /** - * @var string Name of subtable class that manage subtable lines - */ - //public $class_element_line = 'CompanyPaymentModeline'; - /** - * @var array List of child tables. To test if we can delete object. - */ - //protected $childtables=array(); - /** - * @var CompanyPaymentModeLine[] Array of subtable lines - */ - //public $lines = array(); - - - /** * Constructor * diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 55916fc4fe2..c4efd987d0b 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -50,6 +50,16 @@ class WebsitePage extends CommonObject */ public $picto = 'file-code'; + /** + * @var string Field with ID of parent key if this field has a parent or for child tables + */ + public $fk_element = 'fk_website_page'; + + /** + * @var array List of child tables. To know object to delete on cascade. + */ + protected $childtablesoncascade = array('categorie_website_page'); + /** * @var int ID @@ -181,35 +191,6 @@ class WebsitePage extends CommonObject // END MODULEBUILDER PROPERTIES - // If this object has a subtable with lines - - // /** - // * @var string Name of subtable line - // */ - //public $table_element_line = 'mymodule_myobjectline'; - - /** - * @var string Field with ID of parent key if this field has a parent or for child tables - */ - public $fk_element = 'fk_website_page'; - - // /** - // * @var string Name of subtable class that manage subtable lines - // */ - //public $class_element_line = 'MyObjectline'; - - /** - * @var array List of child tables. To test if we can delete object. - */ - //protected $childtables=array(); - - /** - * @var array List of child tables. To know object to delete on cascade. - */ - protected $childtablesoncascade = array('categorie_website_page'); - - - /** * Constructor * diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php index d3b098784da..6f81c4a28eb 100644 --- a/htdocs/workstation/class/workstation.class.php +++ b/htdocs/workstation/class/workstation.class.php @@ -132,42 +132,6 @@ class Workstation extends CommonObject // END MODULEBUILDER PROPERTIES - // If this object has a subtable with lines - - /** - * @var int Name of subtable line - */ - //public $table_element_line = 'workstation_workstationline'; - - /** - * @var int Field with ID of parent key if this object has a parent - */ - //public $fk_element = 'fk_workstation'; - - /** - * @var int Name of subtable class that manage subtable lines - */ - //public $class_element_line = 'Workstationline'; - - /** - * @var array List of child tables. To test if we can delete object. - */ - //protected $childtables = array(); - - /** - * @var array List of child tables. To know object to delete on cascade. - * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will - * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object - */ - //protected $childtablesoncascade = array('workstation_workstationdet'); - - /** - * @var WorkstationLine[] Array of subtable lines - */ - //public $lines = array(); - - - /** * Constructor * From f5792d692af4199d4d28fe637ad3d1a4013518dc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 13:32:43 +0100 Subject: [PATCH 277/816] Fix migration --- htdocs/install/mysql/migration/16.0.0-17.0.0.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 228fde598bb..31cbebab726 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -207,6 +207,8 @@ ALTER TABLE llx_societe_remise_except ADD COLUMN multicurrency_tx double(24,8) N -- VMYSQL4.3 ALTER TABLE llx_hrm_evaluationdet CHANGE COLUMN `rank` rankorder integer; -- VPGSQL8.2 ALTER TABLE llx_hrm_evaluationdet CHANGE COLUMN rank rankorder integer; +-- VMYSQL4.3 ALTER TABLE llx_hrm_skillrank CHANGE COLUMN `rank` rankorder integer; +-- VPGSQL8.2 ALTER TABLE llx_hrm_skillrank CHANGE COLUMN rank rankorder integer; -- Rename const to hide public and private notes (fix allow notes const was used to hide) @@ -388,4 +390,3 @@ ALTER TABLE llx_opensurvey_user_studs ADD COLUMN date_creation datetime NULL; ALTER TABLE llx_opensurvey_comments ADD COLUMN date_creation datetime NULL; ALTER TABLE llx_c_tva ADD COLUMN use_default tinyint DEFAULT 0; - From ed11164b74e92fbd7214cbbbfbee3b71635902ad Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Jan 2023 13:33:04 +0100 Subject: [PATCH 278/816] Debug --- htdocs/hrm/compare.php | 66 +++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/htdocs/hrm/compare.php b/htdocs/hrm/compare.php index d1dde23a63c..6365dd51d25 100644 --- a/htdocs/hrm/compare.php +++ b/htdocs/hrm/compare.php @@ -28,9 +28,6 @@ * 2- the central part displays the skills. display of the maximum score for this group and the number of occurrences. * * 3- the right part displays the members of group 2 or the job to be compared - * - * - * */ @@ -48,6 +45,7 @@ require_once DOL_DOCUMENT_ROOT . '/hrm/lib/hrm.lib.php'; // Load translation files required by the page $langs->load('hrm'); +$job = new Job($db); // Permissions $permissiontoread = $user->rights->hrm->evaluation->read || $user->rights->hrm->compare_advance->read; @@ -61,8 +59,8 @@ if (!$permissiontoread || ($action === 'create' && !$permissiontoadd)) accessfor * View */ -$css = array(); -$css[] = '/hrm/css/style.css'; +$css = array('/hrm/css/style.css'); + llxHeader('', $langs->trans('SkillComparison'), '', '', 0, 0, '', $css); $head = array(); @@ -74,8 +72,6 @@ $head[$h][2] = 'compare'; print dol_get_fiche_head($head, 'compare', '', 1); -//$PDOdb = new TPDOdb; -$form = new Form($db); ?> '."\n"; llxHeader($moreheadcss.$moreheadjs, $langs->trans("ECMArea"), '', '', '', '', $morejs, '', 0, 0); -$head = ecm_prepare_dasboard_head(''); +$head = ecm_prepare_dasboard_head(null); print dol_get_fiche_head($head, 'index', '', -1, ''); diff --git a/htdocs/ecm/index_auto.php b/htdocs/ecm/index_auto.php index 9d9d30e8188..3944e869da0 100644 --- a/htdocs/ecm/index_auto.php +++ b/htdocs/ecm/index_auto.php @@ -387,7 +387,7 @@ if (empty($conf->global->ECM_AUTO_TREE_HIDEN)) { } } -$head = ecm_prepare_dasboard_head(''); +$head = ecm_prepare_dasboard_head(null); print dol_get_fiche_head($head, 'index_auto', '', -1, ''); diff --git a/htdocs/ecm/index_medias.php b/htdocs/ecm/index_medias.php index 2e1edcdc269..39118774430 100644 --- a/htdocs/ecm/index_medias.php +++ b/htdocs/ecm/index_medias.php @@ -295,7 +295,7 @@ $moreheadjs .= ''."\n"; llxHeader($moreheadcss.$moreheadjs, $langs->trans("ECMArea"), '', '', '', '', $morejs, '', 0, 0); -$head = ecm_prepare_dasboard_head(''); +$head = ecm_prepare_dasboard_head(null); print dol_get_fiche_head($head, 'index_medias', '', -1, ''); diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index 633cb6fa5ce..e6c1aac1372 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -154,6 +154,7 @@ if ($action == 'addfolder') { // Action ajout d'un rep if ($action == 'add' && $user->rights->ftp->setup) { + $ecmdir = new EcmDirectory($db); $ecmdir->ref = GETPOST("ref"); $ecmdir->label = GETPOST("label"); $ecmdir->description = GETPOST("desc"); diff --git a/htdocs/index.php b/htdocs/index.php index 7cfd12d4bac..f1ce8248921 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -490,7 +490,7 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { foreach ($dashboardgroup as $groupKey => $groupElement) { $boards = array(); - // Scan $groupElement and save the one with 'stats' that lust be used for Open object dashboard + // Scan $groupElement and save the one with 'stats' that must be used for the open objects dashboard if (empty($conf->global->MAIN_DISABLE_NEW_OPENED_DASH_BOARD)) { foreach ($groupElement['stats'] as $infoKey) { if (!empty($valid_dashboardlines[$infoKey])) { @@ -519,10 +519,10 @@ if (empty($conf->global->MAIN_DISABLE_GLOBAL_WORKBOARD)) { $openedDashBoard .= ' '."\n"; $openedDashBoard .= ' '."\n"; - // Show the span for the total of record + // Show the span for the total of record. TODO This seems not used. if (!empty($groupElement['globalStats'])) { $globalStatInTopOpenedDashBoard[] = $globalStatsKey; - $openedDashBoard .= ''.$nbTotal.''; + $openedDashBoard .= ''.$groupElement['globalStats']['nbTotal'].''; } $openedDashBoard .= ''."\n"; diff --git a/htdocs/install/index.php b/htdocs/install/index.php index a7ce50c819f..6810e3c509f 100644 --- a/htdocs/install/index.php +++ b/htdocs/install/index.php @@ -44,7 +44,7 @@ $langs->load("admin"); * View */ -$formadmin = new FormAdmin(''); // Note: $db does not exist yet but we don't need it, so we put ''. +$formadmin = new FormAdmin(null); // Note: $db does not exist yet but we don't need it, so we put ''. pHeader("", "check"); // Next step = check diff --git a/htdocs/install/lib/repair.lib.php b/htdocs/install/lib/repair.lib.php index aea82107d29..c7c45dff053 100644 --- a/htdocs/install/lib/repair.lib.php +++ b/htdocs/install/lib/repair.lib.php @@ -125,7 +125,7 @@ function checkLinkedElements($sourcetype, $targettype) /** * Clean data into ecm_directories table * - * @return void + * @return int <0 if KO, >0 if OK */ function clean_data_ecm_directories() { @@ -145,12 +145,14 @@ function clean_data_ecm_directories() $resqlupdate = $db->query($sqlupdate); if (!$resqlupdate) { dol_print_error($db, 'Failed to update'); + return -1; } } } } else { dol_print_error($db, 'Failed to run request'); + return -1; } - return; + return 1; } diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index d8eb602f624..17912f81101 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1413,7 +1413,7 @@ if (!function_exists("llxHeader")) { } if (empty($conf->dol_hide_leftmenu) && !GETPOST('dol_openinpopup', 'aZ09')) { - left_menu('', $help_url, '', '', 1, $title, 1); // $menumanager is retrieved with a global $menumanager inside this function + left_menu(array(), $help_url, '', '', 1, $title, 1); // $menumanager is retrieved with a global $menumanager inside this function } // main area @@ -2885,7 +2885,7 @@ function left_menu($menu_array_before, $helppagename = '', $notused = '', $menu_ $selected = -1; if (empty($conf->global->MAIN_USE_TOP_MENU_SEARCH_DROPDOWN)) { $usedbyinclude = 1; - $arrayresult = null; + $arrayresult = array(); include DOL_DOCUMENT_ROOT.'/core/ajax/selectsearchbox.php'; // This set $arrayresult if ($conf->use_javascript_ajax && empty($conf->global->MAIN_USE_OLD_SEARCH_FORM)) { diff --git a/htdocs/paybox/lib/paybox.lib.php b/htdocs/paybox/lib/paybox.lib.php index 7f41d45d374..567a4b91669 100644 --- a/htdocs/paybox/lib/paybox.lib.php +++ b/htdocs/paybox/lib/paybox.lib.php @@ -225,5 +225,5 @@ function print_paybox_redirect($PRICE, $CURRENCY, $EMAIL, $urlok, $urlko, $TAG) print ''."\n"; print "\n"; - return; + return 1; } diff --git a/htdocs/public/recruitment/index.php b/htdocs/public/recruitment/index.php index 23a180b9a7b..8724e65ca4f 100644 --- a/htdocs/public/recruitment/index.php +++ b/htdocs/public/recruitment/index.php @@ -252,7 +252,7 @@ if (is_array($results)) { } } print ''; - print $tmpuser->getFullName(-1); + print $tmpuser->getFullName(); print '   '.dol_print_email($emailforcontact, 0, 0, 1, 0, 0, 'envelope'); print ''; print '
'; diff --git a/htdocs/takepos/ajax/ajax.php b/htdocs/takepos/ajax/ajax.php index db6b224466c..87357d10091 100644 --- a/htdocs/takepos/ajax/ajax.php +++ b/htdocs/takepos/ajax/ajax.php @@ -370,6 +370,9 @@ if ($action == 'getProducts') { $place = GETPOST('place', 'alpha'); require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php'; + + $object = new Facture($db); + $printer = new dolReceiptPrinter($db); $printer->sendToPrinter($object, getDolGlobalString('TAKEPOS_TEMPLATE_TO_USE_FOR_INVOICES'.$term), getDolGlobalString('TAKEPOS_PRINTER_TO_USE'.$term)); } From d3c35651906ba23ca9eaf5563149cc8ec37cfcf2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 6 Jan 2023 20:53:09 +0100 Subject: [PATCH 360/816] css --- htdocs/compta/bank/bankentries_list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index b0514c71ee6..6c961e85af9 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -1134,8 +1134,8 @@ if ($resql) { } // Conciliated if (!empty($arrayfields['b.conciliated']['checked'])) { - print '
'; } // Bordereau From 44423bea30c4f1340a34fa6a82be8a666bb5cb39 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 6 Jan 2023 20:53:09 +0100 Subject: [PATCH 361/816] css --- htdocs/compta/bank/bankentries_list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index b0514c71ee6..6c961e85af9 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -1134,8 +1134,8 @@ if ($resql) { } // Conciliated if (!empty($arrayfields['b.conciliated']['checked'])) { - print ''; } // Bordereau From 8d922d89345c4f947e1b47e7d442ce07f8751c67 Mon Sep 17 00:00:00 2001 From: daraelmin Date: Sat, 7 Jan 2023 00:24:57 +0100 Subject: [PATCH 362/816] New Accountancy - 2 line for 1 mvmt in create mode --- htdocs/accountancy/bookkeeping/card.php | 787 +++++++++++------------- 1 file changed, 367 insertions(+), 420 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 4620bf37e4e..e1916310b34 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -4,6 +4,7 @@ * Copyright (C) 2013-2022 Alexandre Spangaro * Copyright (C) 2017 Laurent Destailleur * Copyright (C) 2018-2020 Frédéric France + * Copyright (C) 2022 Waël Almoman * * 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 @@ -44,7 +45,7 @@ $cancel = GETPOST('cancel', 'aZ09'); $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') $id = GETPOST('id', 'int'); // id of record -$mode = GETPOST('mode', 'aZ09'); // '' or '_tmp' +$mode = $mode = $action == 'create' ? "_tmp" : GETPOST('mode', 'aZ09'); // '' or '_tmp' $piece_num = GETPOST("piece_num", 'int'); // id of transaction (several lines share the same transaction id) $accountingaccount = new AccountingAccount($db); @@ -54,10 +55,15 @@ $accountingaccount_number = GETPOST('accountingaccount_number', 'alphanohtml'); $accountingaccount->fetch(null, $accountingaccount_number, true); $accountingaccount_label = $accountingaccount->label; -$journal_code = GETPOST('code_journal', 'alpha'); +$journal_code = GETPOST('code_journal', 'alpha') ? GETPOST('code_journal', 'alpha') : "NULL"; $accountingjournal->fetch(null, $journal_code); $journal_label = $accountingjournal->label; +$next_num_mvt = (int) GETPOST('next_num_mvt', 'alpha'); +$doc_ref = (string) GETPOST('doc_ref', 'alpha'); +$doc_date = (string) GETPOST('doc_date', 'alpha'); +$doc_date = $doc_date = dol_mktime(0, 0, 0, GETPOST('doc_datemonth', 'int'), GETPOST('doc_dateday', 'int'), GETPOST('doc_dateyear', 'int')); + $subledger_account = GETPOST('subledger_account', 'alphanohtml'); if ($subledger_account == -1) { $subledger_account = null; @@ -72,6 +78,10 @@ $save = GETPOST('save', 'alpha'); if (!empty($save)) { $action = 'add'; } +$valid = GETPOST('validate', 'alpha'); +if (!empty($valid)) { + $action = 'valid'; +} $update = GETPOST('update', 'alpha'); if (!empty($update)) { $action = 'confirm_update'; @@ -156,64 +166,79 @@ if ($action == "confirm_update") { } } } -} elseif ($action == "add") { +} elseif ($action == 'add' || $action == 'valid') { $error = 0; - if ((floatval($debit) != 0.0) && (floatval($credit) != 0.0)) { - $error++; - setEventMessages($langs->trans('ErrorDebitCredit'), null, 'errors'); - $action = ''; - } - if (empty($accountingaccount_number) || $accountingaccount_number == '-1') { - $error++; - setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("AccountAccountingShort")), null, 'errors'); - $action = ''; + if (array_sum($debit) != array_sum($credit)) { + $action = 'add'; } - if (!$error) { - $object = new BookKeeping($db); + foreach ($accountingaccount_number as $key => $value) { + $accountingaccount->fetch(null, $accountingaccount_number[$key], true); + $accountingaccount_label[$key] = $accountingaccount->label[$key]; - $object->numero_compte = $accountingaccount_number; - $object->subledger_account = $subledger_account; - $object->subledger_label = $subledger_label; - $object->label_compte = $accountingaccount_label; - $object->label_operation = $label_operation; - $object->debit = $debit; - $object->credit = $credit; - $object->doc_date = (string) GETPOST('doc_date', 'alpha'); - $object->doc_type = (string) GETPOST('doc_type', 'alpha'); - $object->piece_num = $piece_num; - $object->doc_ref = (string) GETPOST('doc_ref', 'alpha'); - $object->code_journal = $journal_code; - $object->journal_label = $journal_label; - $object->fk_doc = GETPOSTINT('fk_doc'); - $object->fk_docdet = GETPOSTINT('fk_docdet'); - - if (floatval($debit) != 0.0) { - $object->montant = $debit; // deprecated - $object->amount = $debit; - $object->sens = 'D'; + // if one added row is empty remove it before continue + if ($key < 1 && (empty($accountingaccount_number[$key]) || $accountingaccount_number[$key] == '-1') || (floatval($debit[$key]) == 0.0) && (floatval($credit[$key]) == 0.0)) { + continue; } - if (floatval($credit) != 0.0) { - $object->montant = $credit; // deprecated - $object->amount = $credit; - $object->sens = 'C'; - } - - $result = $object->createStd($user, false, $mode); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); - } else { - if ($mode != '_tmp') { - setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); - } - - $debit = 0; - $credit = 0; - + if ((floatval($debit[$key]) != 0.0) && (floatval($credit[$key]) != 0.0)) { + $error++; + setEventMessages($langs->trans('ErrorDebitCredit'), null, 'errors'); $action = ''; } + + if (empty($accountingaccount_number[$key]) || $accountingaccount_number[$key] == '-1') { + $error++; + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("AccountAccountingShort")), null, 'errors'); + $action = ''; + } + + if (!$error) { + $object = new BookKeeping($db); + $object->numero_compte = $accountingaccount_number[$key]; + $object->subledger_account = $subledger_account[$key]; + $object->subledger_label = $subledger_label[$key]; + $object->label_compte = $accountingaccount_label[$key]; + $object->label_operation = $label_operation[$key]; + $object->debit = price2num($debit[$key]); + $object->credit = price2num($credit[$key]); + $object->doc_date = $doc_date; + $object->doc_type = (string) GETPOST('doc_type', 'alpha'); + $object->piece_num = $piece_num; + $object->doc_ref = $doc_ref; + $object->code_journal = $journal_code; + $object->journal_label = $journal_label; + $object->fk_doc = GETPOSTINT('fk_doc'); + $object->fk_docdet = GETPOSTINT('fk_docdet'); + + if (floatval($debit[$key]) != 0.0) { + $object->montant = $object->debit; // deprecated + $object->amount = $object->debit; + $object->sens = 'D'; + } + + if (floatval($credit[$key]) != 0.0) { + $object->montant = $object->credit; // deprecated + $object->amount = $object->credit; + $object->sens = 'C'; + } + + $result = $object->createStd($user, false, $mode); + if ($result < 0) { + $error++; + setEventMessages($object->error, $object->errors, 'errors'); + } + } + } + if (empty($error)) { + if ($mode != '_tmp') { + setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); + } + $debit = 0; + $credit = 0; + + $action = $action == 'add' ? '' : $action ; // stay in valid mode when not adding line } } elseif ($action == "confirm_delete") { $object = new BookKeeping($db); @@ -230,17 +255,28 @@ if ($action == "confirm_update") { } } $action = ''; -} elseif ($action == "confirm_create") { +} elseif ($action == 'create') { $error = 0; $object = new BookKeeping($db); + $next_num_mvt = !empty($next_num_mvt) ? $next_num_mvt : $object->getNextNumMvt('_tmp'); + $doc_ref = !empty($doc_ref) ? $doc_ref : $next_num_mvt; + + if (empty($doc_date)) { + $tmp_date = dol_getdate(dol_now()); + $_POST['doc_dateday'] = $tmp_date['mday']; + $_POST['doc_datemonth'] = $tmp_date['mon']; + $_POST['doc_dateyear'] = $tmp_date['year']; + unset($tmp_date); + } + if (!$journal_code || $journal_code == '-1') { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Journal")), null, 'errors'); $action = 'create'; $error++; } - if (!GETPOST('doc_ref', 'alpha')) { + if (empty($doc_ref)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Piece")), null, 'errors'); $action = 'create'; $error++; @@ -252,8 +288,8 @@ if ($action == "confirm_update") { $object->credit = 0; $object->doc_date = $date_start = dol_mktime(0, 0, 0, GETPOST('doc_datemonth', 'int'), GETPOST('doc_dateday', 'int'), GETPOST('doc_dateyear', 'int')); $object->doc_type = GETPOST('doc_type', 'alpha'); - $object->piece_num = GETPOST('next_num_mvt', 'alpha'); - $object->doc_ref = GETPOST('doc_ref', 'alpha'); + $object->piece_num = $next_num_mvt; + $object->doc_ref = $doc_ref; $object->code_journal = $journal_code; $object->journal_label = $journal_label; $object->fk_doc = 0; @@ -302,7 +338,7 @@ if ($action == 'setjournal') { } if ($action == 'setdocref') { - $refdoc = GETPOST('doc_ref', 'alpha'); + $refdoc = $doc_ref; $result = $object->updateByMvt($piece_num, 'doc_ref', $refdoc, $mode); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); @@ -333,7 +369,7 @@ if ($action == 'valid') { $html = new Form($db); $formaccounting = new FormAccounting($db); -$title = $langs->trans("CreateMvts"); +$title = $langs->trans($mode =="_tmp" ? "CreateMvts": "UpdateMvts"); llxHeader('', $title); @@ -343,28 +379,37 @@ if ($action == 'delete') { print $formconfirm; } -if ($action == 'create') { - print load_fiche_titre($title); - $object = new BookKeeping($db); - $next_num_mvt = $object->getNextNumMvt('_tmp'); +$object = new BookKeeping($db); +$result = $object->fetchPerMvt($piece_num, $mode); +if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); +} - if (empty($next_num_mvt)) { - dol_print_error('', 'Failed to get next piece number'); +if (!empty($object->piece_num)) { + $backlink = ''.$langs->trans('BackToList').''; + + print load_fiche_titre($langs->trans($mode =="_tmp" ? "CreateMvts": "UpdateMvts"), $backlink); + + print ''; if ($optioncss != '') { + print ''; } + $head = array(); + $h = 0; + $head[$h][0] = $_SERVER['PHP_SELF'].'?piece_num='.$object->piece_num.($mode ? '&mode='.$mode : ''); + $head[$h][1] = $langs->trans("Transaction"); + $head[$h][2] = 'transaction'; + $h++; - print ''; - if ($optioncss != '') { - print ''; - } - print ''; - print ''."\n"; - print ''."\n"; - print ''."\n"; + print dol_get_fiche_head($head, 'transaction', '', -1); - print dol_get_fiche_head(); + //dol_banner_tab($object, '', $backlink); - print '
'.$langs->trans("Description").' '.$langs->trans("Value").''.$langs->trans("Value").'
'.$langs->trans("ECMAutoTree").' '; +print ''; if ($conf->use_javascript_ajax) { - print ajax_constantonoff('ECM_AUTO_TREE_ENABLED'); + print ajax_constantonoff('ECM_AUTO_TREE_HIDEN', null, null, 1); } else { - if (empty($conf->global->ECM_AUTO_TREE_ENABLED)) { - print ''.img_picto($langs->trans("Disabled"), 'off').''; - } elseif (!empty($conf->global->USER_MAIL_REQUIRED)) { - print ''.img_picto($langs->trans("Enabled"), 'on').''; + if (empty($conf->global->ECM_AUTO_TREE_HIDEN)) { + print ''.img_picto($langs->trans("Enabled"), 'on').''; + } else { + print ''.img_picto($langs->trans("Disabled"), 'off').''; } } print '
'.price2num($sub_bom->total_cost * $sub_bom_line->qty * $line->qty, 'MT').''.price(price2num($sub_bom->total_cost * $sub_bom_line->qty * $line->qty, 'MT')).''.price2num($sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty, 'MT').''.price(price2num($sub_bom_product->cost_price * $sub_bom_line->qty * $line->qty, 'MT')).''.price2num($sub_bom_product->pmp * $sub_bom_line->qty * $line->qty, 'MT').''.price(price2num($sub_bom_product->pmp * $sub_bom_line->qty * $line->qty, 'MT')).''; + + $durationtouse_start = 0; + if ($search_timespent_starthour || $search_timespent_startmin) { + $durationtouse_start = ($search_timespent_starthour * 3600 + $search_timespent_startmin * 60); + } + print '
'.$langs->trans('from').' '; + $form->select_duration('search_timespent_duration_start', $durationtouse_start, 0, 'text'); + print '
'; + + $durationtouse_end = 0; + if ($search_timespent_endhour || $search_timespent_endmin) { + $durationtouse_end = ($search_timespent_endhour * 3600 + $search_timespent_endmin * 60); + } + print '
'.$langs->trans('at').' '; + $form->select_duration('search_timespent_duration_end', $durationtouse_end, 0, 'text'); + print '
'; + + print '
'; + print ''; + print ''; $selectarray = array('0'=>$langs->trans("ContactPublic"), '1'=>$langs->trans("ContactPrivate")); @@ -1105,6 +1128,9 @@ if (!empty($arrayfields['p.fk_soc']['checked'])) { if (!empty($arrayfields['s.nom']['checked'])) { print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", $begin, $param, '', $sortfield, $sortorder); } +if (!empty($arrayfields['s.name_alias']['checked'])) { + print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", $begin, $param, '', $sortfield, $sortorder); +} if (!empty($arrayfields['p.priv']['checked'])) { print_liste_field_titre($arrayfields['p.priv']['label'], $_SERVER["PHP_SELF"], "p.priv", $begin, $param, '', $sortfield, $sortorder, 'center '); } @@ -1323,7 +1349,7 @@ while ($i < min($num, $limit)) { if ($obj->socid) { $objsoc = new Societe($db); $objsoc->fetch($obj->socid); - print $objsoc->getNomUrl(1); + print $objsoc->getNomUrl(1, 'customer', 100, 0, 1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); } else { print ' '; } @@ -1333,6 +1359,16 @@ while ($i < min($num, $limit)) { } } + // Alias name + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print $obj->alias; + print ''.$contactstatic->LibPubPriv($obj->priv).''; $label = preg_replace('/_NAME$/', '', $keyforsupportedoauth2array); - print ''; + print ''; print img_picto('', 'delete'); print ''; @@ -298,7 +298,8 @@ if (count($listinsetup) > 0) { $redirect_uri = $urlwithroot.'/core/modules/oauth/'.$supportedoauth2array[$keyforsupportedoauth2array]['callbackfile'].'_oauthcallback.php'; print '
'.$langs->trans("UseTheFollowingUrlAsRedirectURI").''; + print ''; + print ajax_autoselect('uri'.$keyforsupportedoauth2array.$keyforprovider); print '
'.$langs->trans("URLOfServiceForAuthorization").''; + print ''; print '
"; - print $obj->label; + print dol_escape_htmltag($obj->label); print ""; - print $obj->labelshort; + print dol_escape_htmltag($obj->labelshort); print ""; - print $obj->pcg_type; + print dol_escape_htmltag($obj->pcg_type); + print ""; + // TODO Get all custom groups labels the account is in + print dol_escape_htmltag($obj->fk_accounting_category); + print ""; + print dol_escape_htmltag($obj->import_key); print "
'.$langs->trans("NoRecordFound").'
'.$langs->trans("NoRecordFound").'
'; - print $form->selectarray('search_status', array('0'=>$langs->trans('ActivityCeased'), '1'=>$langs->trans('InActivity')), $search_status, 1, 0, 0, '', 0, 0, 0, '', 'search_status minwidth75 maxwidth125 onrightofpage', 1); + print $form->selectarray('search_status', array('0'=>$langs->trans('ActivityCeased'), '1'=>$langs->trans('InActivity')), $search_status, 1, 0, 0, '', 0, 0, 0, '', 'search_status minwidth75imp maxwidth125 onrightofpage', 1); print ''; - print $form->selectarray('search_statut', array('-1'=>'', '0'=>$langs->trans('Disabled'), '1'=>$langs->trans('Enabled')), $search_statut, 0, 0, 0, '', 0, 0, 0, '', 'minwidth75imp'); + print $form->selectarray('search_statut', array('-1'=>'', '0'=>$langs->trans('Disabled'), '1'=>$langs->trans('Enabled')), $search_statut, 0, 0, 0, '', 0, 0, 0, '', 'search_status minwidth75imp maxwidth125 onrightofpage'); print ''; - print $form->selectarray('search_status', array('0'=>$langs->trans('ActivityCeased'), '1'=>$langs->trans('InActivity')), $search_status, 1, 0, 0, '', 0, 0, 0, '', 'search_status minwidth75 maxwidth125 onrightofpage', 1); + print $form->selectarray('search_status', array('0'=>$langs->trans('ActivityCeased'), '1'=>$langs->trans('InActivity')), $search_status, 1, 0, 0, '', 0, 0, 0, '', 'search_status minwidth75imp maxwidth125 onrightofpage', 1); print ''; - print $form->selectarray('search_statut', array('-1'=>'', '0'=>$langs->trans('Disabled'), '1'=>$langs->trans('Enabled')), $search_statut, 0, 0, 0, '', 0, 0, 0, '', 'minwidth75imp'); + print $form->selectarray('search_statut', array('-1'=>'', '0'=>$langs->trans('Disabled'), '1'=>$langs->trans('Enabled')), $search_statut, 0, 0, 0, '', 0, 0, 0, '', 'search_status minwidth75imp maxwidth125 onrightofpage'); print ''; - print $form->selectyesno('search_conciliated', $search_conciliated, 1, false, 1, 1); + print ''; + print $form->selectyesno('search_conciliated', $search_conciliated, 1, false, 1, 1, 'search_status onrightofpage maxwidth75'); print ''; - print $form->selectyesno('search_conciliated', $search_conciliated, 1, false, 1, 1); + print ''; + print $form->selectyesno('search_conciliated', $search_conciliated, 1, false, 1, 1, 'search_status onrightofpage maxwidth75'); print '
'; + print '
'; + print '
'; + + print '
'; + print '
'; /*print ''; print ''; @@ -374,7 +419,7 @@ if ($action == 'create') { print ''; print ''; print ''; print ''; @@ -385,262 +430,151 @@ if ($action == 'create') { print ''; print ''; - print ''; + print ''; print ''; /* print ''; print ''; - print ''; + print ''; print ''; */ print '
' . $langs->trans("NumPiece") . '
'.$langs->trans("Docdate").''; - print $html->selectDate('', 'doc_date', '', '', '', "create_mvt", 1, 1); + print $html->selectDate($doc_date, 'doc_date', '', '', '', "create_mvt", 1, 1); print '
'.$langs->trans("Piece").'
' . $langs->trans("Doctype") . '
'; - print dol_get_fiche_end(); + print ''; - print $form->buttonsSaveCancel("Create"); + print '
'; - print ''; -} else { - $object = new BookKeeping($db); - $result = $object->fetchPerMvt($piece_num, $mode); - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); + print '
'; + print ''; + + // Doc type + if (!empty($object->doc_type)) { + print ''; + print ''; + print ''; + print ''; } - if (!empty($object->piece_num)) { - $backlink = ''.$langs->trans('BackToList').''; + // Date document creation + print ''; + print ''; + print ''; + print ''; - print load_fiche_titre($langs->trans("UpdateMvts"), $backlink); - - $head = array(); - $h = 0; - $head[$h][0] = $_SERVER['PHP_SELF'].'?piece_num='.$object->piece_num.($mode ? '&mode='.$mode : ''); - $head[$h][1] = $langs->trans("Transaction"); - $head[$h][2] = 'transaction'; - $h++; - - print dol_get_fiche_head($head, 'transaction', '', -1); - - //dol_banner_tab($object, '', $backlink); - - print '
'; - print '
'; - - print '
'; - print '
'.$langs->trans("Doctype").''.$object->doc_type.'
'.$langs->trans("DateCreation").''; + print $object->date_creation ? dol_print_date($object->date_creation, 'day') : ' '; + print '
'; - - // Account movement + // Don't show in tmp mode, inevitably empty + if ($mode != "_tmp") { + // Date document export print ''; - print ''; - print ''; - print ''; - - // Date - print ''; - print ''; - - // Journal - print ''; - print ''; - - // Ref document - print ''; - print ''; - - print '
'.$langs->trans("NumMvts").''.($mode == '_tmp' ? ''.$langs->trans("Draft").'' : $object->piece_num).'
'; - print ''; - if ($action != 'editdate') { - print ''; - } - print '
'; - print $langs->trans('Docdate'); - print 'piece_num).'&mode='.urlencode($mode).'">'.img_edit($langs->transnoentitiesnoconv('SetDate'), 1).'
'; - print '
'; - if ($action == 'editdate') { - print '
'; - if ($optioncss != '') { - print ''; - } - print ''; - print ''; - print ''; - print $form->selectDate($object->doc_date ? $object->doc_date : - 1, 'doc_date', '', '', '', "setdate"); - print ''; - print '
'; - } else { - print $object->doc_date ? dol_print_date($object->doc_date, 'day') : ' '; - } - print '
'; - print ''; - if ($action != 'editjournal') { - print ''; - } - print '
'; - print $langs->trans('Codejournal'); - print 'piece_num).'&mode='.urlencode($mode).'">'.img_edit($langs->transnoentitiesnoconv('Edit'), 1).'
'; - print '
'; - if ($action == 'editjournal') { - print '
'; - if ($optioncss != '') { - print ''; - } - print ''; - print ''; - print ''; - print $formaccounting->select_journal($object->code_journal, 'code_journal', 0, 0, array(), 1, 1); - print ''; - print '
'; - } else { - print $object->code_journal; - } - print '
'; - print ''; - if ($action != 'editdocref') { - print ''; - } - print '
'; - print $langs->trans('Piece'); - print 'piece_num).'&mode='.urlencode($mode).'">'.img_edit($langs->transnoentitiesnoconv('Edit'), 1).'
'; - print '
'; - if ($action == 'editdocref') { - print '
'; - if ($optioncss != '') { - print ''; - } - print ''; - print ''; - print ''; - print ''; - print ''; - print '
'; - } else { - print $object->doc_ref; - } - print '
'; - - print '
'; - - print '
'; - - print '
'; - print ''; - - // Doc type - if (!empty($object->doc_type)) { - print ''; - print ''; - print ''; - print ''; - } - - // Date document creation - print ''; - print ''; + print ''; print ''; print ''; - // Don't show in tmp mode, inevitably empty - if ($mode != "_tmp") { - // Date document export - print ''; - print ''; - print ''; - print ''; - - // Date document validation - print ''; - print ''; - print ''; - print ''; - } - - // Validate - /* + // Date document validation print ''; - print ''; + print ''; print ''; + print $object->date_validation ? dol_print_date($object->date_validation, 'dayhour') : ' '; + print ''; print ''; - */ + } + // Validate + /* + print ''; + print ''; + print ''; + print ''; + */ // check data - /* - print ''; - print ''; - if ($object->doc_type == 'customer_invoice') - { - $sqlmid = 'SELECT rowid as ref'; - $sqlmid .= " FROM ".MAIN_DB_PREFIX."facture as fac"; - $sqlmid .= " WHERE fac.rowid=" . ((int) $object->fk_doc); - dol_syslog("accountancy/bookkeeping/card.php::sqlmid=" . $sqlmid, LOG_DEBUG); - $resultmid = $db->query($sqlmid); - if ($resultmid) { - $objmid = $db->fetch_object($resultmid); - $invoicestatic = new Facture($db); - $invoicestatic->fetch($objmid->ref); - $ref=$langs->trans("Invoice").' '.$invoicestatic->getNomUrl(1); - } - else dol_print_error($db); - } - print ''; - print ''; - */ - print "
'.$langs->trans("Doctype").''.$object->doc_type.'
'.$langs->trans("DateCreation").''.$langs->trans("DateExport").''; - print $object->date_creation ? dol_print_date($object->date_creation, 'day') : ' '; + print $object->date_export ? dol_print_date($object->date_export, 'dayhour') : ' '; print '
' . $langs->trans("DateExport") . ''; - print $object->date_export ? dol_print_date($object->date_export, 'dayhour') : ' '; - print '
' . $langs->trans("DateValidation") . ''; - print $object->date_validation ? dol_print_date($object->date_validation, 'dayhour') : ' '; - print '
' . $langs->trans("Status") . ''.$langs->trans("DateValidation").''; - if (empty($object->validated)) { - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); - print ''; - } else { - print ''; - print img_picto($langs->trans("Activated"), 'switch_on'); - print ''; - } - print '
' . $langs->trans("Status") . ''; + if (empty($object->validated)) { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } else { + print ''; + print img_picto($langs->trans("Activated"), 'switch_on'); + print ''; + } + print '
' . $langs->trans("Control") . '' . $ref .'
\n"; - - print '
'; - - print dol_get_fiche_end(); - - print '
'; - - print '
'; - - $result = $object->fetchAllPerMvt($piece_num, $mode); // This load $object->linesmvt - - if ($result < 0) { - setEventMessages($object->error, $object->errors, 'errors'); + /* + print ''; + print '' . $langs->trans("Control") . ''; + if ($object->doc_type == 'customer_invoice') { + $sqlmid = 'SELECT rowid as ref'; + $sqlmid .= " FROM ".MAIN_DB_PREFIX."facture as fac"; + $sqlmid .= " WHERE fac.rowid=" . ((int) $object->fk_doc); + dol_syslog("accountancy/bookkeeping/card.php::sqlmid=" . $sqlmid, LOG_DEBUG); + $resultmid = $db->query($sqlmid); + if ($resultmid) { + $objmid = $db->fetch_object($resultmid); + $invoicestatic = new Facture($db); + $invoicestatic->fetch($objmid->ref); + $ref=$langs->trans("Invoice").' '.$invoicestatic->getNomUrl(1); } else { - // List of movements - print load_fiche_titre($langs->trans("ListeMvts"), '', ''); + dol_print_error($db); + } + } + print '' . $ref .''; + print ''; + */ + print "\n"; - print '
'; - if ($optioncss != '') { - print ''; + print dol_get_fiche_end(); + + print '
'; + + print '
'; + + $result = $object->fetchAllPerMvt($piece_num, $mode); // This load $object->linesmvt + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } else { + // List of movements + print load_fiche_titre($langs->trans("ListeMvts"), '', ''); + + if ($optioncss != '') { + print ''; + } + + print ''; + print ''."\n"; + print ''."\n"; + print ''."\n"; + print ''."\n"; + + if (count($object->linesmvt) > 0) { + print '
'; + print ''; + + $total_debit = 0; + $total_credit = 0; + + // Don't show in tmp mode, inevitably empty + if ($mode != "_tmp") { + // Date document export + print ''; + print ''; + print ''; + print ''; + + // Date document validation + print ''; + print ''; + print ''; + print ''; } - print ''; - print ''."\n"; - print ''."\n"; - print ''."\n"; - print ''."\n"; - print ''."\n"; - print ''."\n"; - print ''."\n"; - if (count($object->linesmvt) > 0) { - print '
'; - print '
' . $langs->trans("DateExport") . ''; + print $object->date_export ? dol_print_date($object->date_export, 'dayhour') : ' '; + print '
' . $langs->trans("DateValidation") . ''; + print $object->date_validation ? dol_print_date($object->date_validation, 'dayhour') : ' '; + print '
'; - - $total_debit = 0; - $total_credit = 0; - - print ''; + print ''; print_liste_field_titre("AccountAccountingShort"); print_liste_field_titre("SubledgerAccount"); @@ -655,24 +589,59 @@ if ($action == 'create') { print "\n"; - // Add an empty line if there is not yet - if (!empty($object->linesmvt[0])) { - $tmpline = $object->linesmvt[0]; - if (!empty($tmpline->numero_compte)) { - $line = new BookKeepingLine(); - $object->linesmvt[] = $line; + // In _tmp mode the first line is empty so we remove it + if ($mode == "_tmp") { + array_shift($object->linesmvt); + } + + // Add an empty line at the end to be able to add transaction + $line = new BookKeepingLine(); + $object->linesmvt[] = $line; + + // Add a second line empty line if there is not yet + if (empty($object->linesmvt[1])) { + $line = new BookKeepingLine(); + $object->linesmvt[] = $line; + } + + $count_line = count($object->linesmvt); + $num_line = 0; + foreach ($object->linesmvt as $key => $line) { + $num_line++; + print ''; + $total_debit += $line->debit; + $total_credit += $line->credit; + + if ($action == 'update' && $line->id == $id) { + print ''; + print ''; + print ''; - $total_debit += $line->debit; - $total_credit += $line->credit; - - if ($action == 'update' && $line->id == $id) { - print ''; + // Add also input for subledger label + print '
subledger_label).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccountLabel")).'" />'; + print ''; + print ''; + print ''; + print ''; + print ''; + } elseif (empty($line->numero_compte) || (empty($line->debit) && empty($line->credit))) { + if ($action == "" || $action == 'add') { + print ''; print ''; print ''; - print ''; - print ''; - print ''; - print ''; - } elseif (empty($line->numero_compte) || (empty($line->debit) && empty($line->credit))) { - if ($action == "" || $action == 'add') { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - } - } else { - print ''; - $resultfetch = $accountingaccount->fetch(null, $line->numero_compte, true); - print ''; + print ''; + print ''; + // Add button should not appear twice + if ($num_line === $count_line) { + print ''; } else { - print $line->numero_compte.' ('.$langs->trans("AccountRemovedFromCurrentChartOfAccount").')'; + print ''; } - print ''; - print ''; - print ''; - print ''; - print ''; - - print ''; } - print "\n"; - } - - $total_debit = price2num($total_debit, 'MT'); - $total_credit = price2num($total_credit, 'MT'); - - if ($total_debit != $total_credit) { - setEventMessages(null, array($langs->trans('MvtNotCorrectlyBalanced', $total_debit, $total_credit)), 'warnings'); - } - - print '
'; + print $formaccounting->select_account((GETPOSTISSET("accountingaccount_number") ? GETPOST("accountingaccount_number", "alpha") : $line->numero_compte), 'accountingaccount_number', 1, array(), 1, 1, ''); + print ''; + // TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because: + // It does not use the setup of "key pressed" to select a thirdparty and this hang browser on large databases. + // Also, it is not possible to use a value that is not in the list. + // Also, the label is not automatically filled when a value is selected. + if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { + print $formaccounting->select_auxaccount((GETPOSTISSET("subledger_account") ? GETPOST("subledger_account", "alpha") : $line->subledger_account), 'subledger_account', 1, 'maxwidth250', '', 'subledger_label'); + } else { + print 'subledger_account).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccount")).'" />'; } - } - - foreach ($object->linesmvt as $line) { - print '
label_operation).'" />debit)).'" />credit)).'" />'; + print ''."\n"; + print ''; + print ''; - print $formaccounting->select_account((GETPOSTISSET("accountingaccount_number") ? GETPOST("accountingaccount_number", "alpha") : $line->numero_compte), 'accountingaccount_number', 1, array(), 1, 1, 'minwidth200 maxwidth500'); + print $formaccounting->select_account((is_array($accountingaccount_number) ? $accountingaccount_number[$key] : $accountingaccount_number ), 'accountingaccount_number['.$key.']', 1, array(), 1, 1, ''); print ''; // TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because: @@ -680,124 +649,102 @@ if ($action == 'create') { // Also, it is not possible to use a value that is not in the list. // Also, the label is not automatically filled when a value is selected. if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { - print $formaccounting->select_auxaccount((GETPOSTISSET("subledger_account") ? GETPOST("subledger_account", "alpha") : $line->subledger_account), 'subledger_account', 1, 'maxwidth250', '', 'subledger_label'); + print $formaccounting->select_auxaccount((is_array($subledger_account) ? $subledger_account[$key] : $subledger_account ), 'subledger_account['.$key.']', 1, 'maxwidth250', '', 'subledger_label'); } else { - print 'subledger_account).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccount")).'">'; + print ''; } - // Add also input for subledger label - print '
subledger_label).'" placeholder="'.dol_escape_htmltag($langs->trans("SubledgerAccountLabel")).'">'; + print '
'; print '
label_operation).'">debit)).'">credit)).'">'; - print ''."\n"; - print ''; - print ''; - print $formaccounting->select_account('', 'accountingaccount_number', 1, array(), 1, 1, 'minwidth200 maxwidth500'); - print ''; - // TODO For the moment we keep a free input text instead of a combo. The select_auxaccount has problem because: - // It does not use the setup of "key pressed" to select a thirdparty and this hang browser on large databases. - // Also, it is not possible to use a value that is not in the list. - // Also, the label is not automatically filled when a value is selected. - if (!empty($conf->global->ACCOUNTANCY_COMBO_FOR_AUX)) { - print $formaccounting->select_auxaccount('', 'subledger_account', 1, 'maxwidth250', '', 'subledger_label'); - } else { - print ''; - } - print '
'; - print '
'; - if ($resultfetch > 0) { - print $accountingaccount->getNomUrl(0, 1, 1, '', 0); + print ''.length_accounta($line->subledger_account); - if ($line->subledger_label) { - print ' - '.$line->subledger_label.''; - } - print ''.$line->label_operation.''.($line->debit != 0 ? price($line->debit) : '').''.($line->credit != 0 ? price($line->credit) : '').''; - if (empty($line->date_export) && empty($line->date_validation)) { - print 'id . '&piece_num=' . urlencode($line->piece_num) . '&mode=' . urlencode($mode) . '&token=' . urlencode(newToken()) . '">'; - print img_edit('', 0, 'class="marginrightonly"'); - print '  '; - } else { - print ''; - print img_edit($langs->trans("ForbiddenTransactionAlreadyExported"), 0, 'class="marginrightonly"'); - print '  '; - } - - if (empty($line->date_validation)) { - $actiontodelete = 'delete'; - if ($mode == '_tmp' || $action != 'delmouv') { - $actiontodelete = 'confirm_delete'; - } - - print ''; - print img_delete(); - print ''; - } else { - print ''; - print img_delete($langs->trans("ForbiddenTransactionAlreadyValidated")); - print ''; - } - - print '
'; - print '
'; - - if ($mode == '_tmp' && $action == '') { - print '
'; - print '
'; - if ($total_debit == $total_credit) { - print ''.$langs->trans("ValidTransaction").''; + } else { + print ''; + $resultfetch = $accountingaccount->fetch(null, $line->numero_compte, true); + print ''; + if ($resultfetch > 0) { + print $accountingaccount->getNomUrl(0, 1, 1, '', 0); } else { - print ''; + print $line->numero_compte.' ('.$langs->trans("AccountRemovedFromCurrentChartOfAccount").')'; + } + print ''; + print ''.length_accounta($line->subledger_account); + if ($line->subledger_label) { + print ' - '.$line->subledger_label.''; + } + print ''; + print ''.$line->label_operation.''; + print ''.($line->debit != 0 ? price($line->debit) : '').''; + print ''.($line->credit != 0 ? price($line->credit) : '').''; + + print ''; + if (empty($line->date_export) && empty($line->date_validation)) { + print 'id . '&piece_num=' . urlencode($line->piece_num) . '&mode=' . urlencode($mode) . '&token=' . urlencode(newToken()) . '">'; + print img_edit('', 0, 'class="marginrightonly"'); + print '  '; + } else { + print ''; + print img_edit($langs->trans("ForbiddenTransactionAlreadyExported"), 0, 'class="marginrightonly"'); + print '  '; } - print '   '; - print ''.$langs->trans("Cancel").''; + if (empty($line->date_validation)) { + $actiontodelete = 'delete'; + if ($mode == '_tmp' || $action != 'delmouv') { + $actiontodelete = 'confirm_delete'; + } - print "
"; + print ''; + print img_delete(); + print ''; + } else { + print ''; + print img_delete($langs->trans("ForbiddenTransactionAlreadyValidated")); + print ''; + } + + print ''; } + print "\n"; } - print '
'; + $total_debit = price2num($total_debit, 'MT'); + $total_credit = price2num($total_credit, 'MT'); + + if ($total_debit != $total_credit) { + setEventMessages(null, array($langs->trans('MvtNotCorrectlyBalanced', $total_debit, $total_credit)), 'warnings'); + } + + print ''; + print ''; + + if ($mode == '_tmp' && $action == '') { + print '
'; + print '
'; + if ($total_debit == $total_credit) { + print ''; + } else { + print ''; + } + + print '   '; + print ''.$langs->trans("Cancel").''; + + print "
"; + } } - } else { - print load_fiche_titre($langs->trans("NoRecords")); + + print ''; } +} else { + print load_fiche_titre($langs->trans("NoRecords")); } print dol_get_fiche_end(); From 35256d4ecb7213f09ec41ce5ab82fc0f1da652cf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Jan 2023 02:36:05 +0100 Subject: [PATCH 363/816] Fix css --- htdocs/theme/eldy/global.inc.php | 2 +- htdocs/theme/md/style.css.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 4a148611a76..4f44ab20bad 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -634,7 +634,7 @@ table.tableforfield .buttonDelete:not(.bordertransp):not(.buttonpayment) { -webkit-box-shadow: 0px 0px 5px 1px rgba(0, 0, 60, 0.2), 0px 0px 0px rgba(60,60,60,0.1); box-shadow: 0px 0px 5px 1px rgba(0, 0, 60, 0.2), 0px 0px 0px rgba(60,60,60,0.1); } -.button:hover, .buttonDelete:hover { +.button:hover:not(.nohover), .buttonDelete:hover:not(.nohover) { /* warning: having a larger shadow has side effect when button is completely on left of a table */ -webkit-box-shadow: 0px 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 0px 0px rgba(60,60,60,0.1); box-shadow: 0px 0px 1px 1px rgba(0, 0, 0, 0.2), 0px 0px 0px rgba(60,60,60,0.1); diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 6fd33800eb0..41c20074d6a 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -879,7 +879,7 @@ table.tableforfield .buttonDelete:not(.bordertransp):not(.buttonpayment) { -webkit-box-shadow: 0px 0px 6px 1px rgba(0, 0, 60, 0.2), 0px 0px 0px rgba(60,60,60,0.1); box-shadow: 0px 0px 6px 1px rgba(0, 0, 60, 0.2), 0px 0px 0px rgba(60,60,60,0.1); } -.button:hover, .buttonDelete:hover { +.button:hover:not(.nohover), .buttonDelete:hover:not(.nohover) { -webkit-box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.2), 0px 0px 0px rgba(60,60,60,0.1); box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.2), 0px 0px 0px rgba(60,60,60,0.1); } From e228536329e7dcfaa7d19aee48d3b744d8c24220 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Jan 2023 03:11:33 +0100 Subject: [PATCH 364/816] Fix date now --- htdocs/public/recruitment/view.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/public/recruitment/view.php b/htdocs/public/recruitment/view.php index 57cb82d9b08..0d856539902 100644 --- a/htdocs/public/recruitment/view.php +++ b/htdocs/public/recruitment/view.php @@ -159,6 +159,8 @@ include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; * View */ +$now = dol_now(); + $head = ''; if (!empty($conf->global->MAIN_RECRUITMENT_CSS_URL)) { $head = ''."\n"; From 880be173fa4289cf479fcce1caceb26898b33118 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Jan 2023 03:28:21 +0100 Subject: [PATCH 365/816] Fix typo --- htdocs/public/recruitment/view.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/public/recruitment/view.php b/htdocs/public/recruitment/view.php index 0d856539902..de8297d3ef0 100644 --- a/htdocs/public/recruitment/view.php +++ b/htdocs/public/recruitment/view.php @@ -203,7 +203,7 @@ $paramlogo = 'ONLINE_RECRUITMENT_LOGO_'.$suffix; if (!empty($conf->global->$paramlogo)) { $logosmall = $conf->global->$paramlogo; } elseif (!empty($conf->global->ONLINE_RECRUITMENT_LOGO)) { - $logosmall = $conf->global->ONLINE_RECRUITMENT_LOGO_; + $logosmall = $conf->global->ONLINE_RECRUITMENT_LOGO; } //print ''."\n"; // Define urllogo @@ -236,7 +236,7 @@ if ($urllogo) { if (!empty($conf->global->RECRUITMENT_IMAGE_PUBLIC_INTERFACE)) { print '
'; - print ''; + print ''; print '
'; } From 00740ca267563eee40691aa8ab94294b2f363ad6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Jan 2023 04:05:59 +0100 Subject: [PATCH 366/816] WIP Work on public virtual card --- htdocs/adherents/admin/website.php | 2 +- htdocs/core/class/vcard.class.php | 87 +++++++ htdocs/core/lib/functions.lib.php | 47 ++-- htdocs/core/lib/functions2.lib.php | 2 +- htdocs/langs/en_US/users.lang | 3 + htdocs/public/users/view.php | 381 +++++++++++++++++++++++++++++ htdocs/theme/eldy/global.inc.php | 4 +- htdocs/theme/md/style.css.php | 3 + htdocs/user/card.php | 10 +- htdocs/user/class/user.class.php | 24 ++ htdocs/user/info.php | 2 +- htdocs/user/vcard.php | 105 ++------ htdocs/user/virtualcard.php | 248 +++++++++++++++++++ 13 files changed, 810 insertions(+), 108 deletions(-) create mode 100644 htdocs/public/users/view.php create mode 100644 htdocs/user/virtualcard.php diff --git a/htdocs/adherents/admin/website.php b/htdocs/adherents/admin/website.php index 08e9f617750..14379166247 100644 --- a/htdocs/adherents/admin/website.php +++ b/htdocs/adherents/admin/website.php @@ -178,7 +178,7 @@ if (!empty($conf->global->MEMBER_ENABLE_PUBLIC)) { //print $langs->trans('FollowingLinksArePublic').'
'; print img_picto('', 'globe').' '.$langs->trans('BlankSubscriptionForm').'
'; if (isModEnabled('multicompany')) { - $entity_qr = '?entity='.$conf->entity; + $entity_qr = '?entity='.((int) $conf->entity); } else { $entity_qr = ''; } diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index dbe505a894b..91e3a5565e1 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -1,4 +1,7 @@ * Copyright (C) 2005-2017 Laurent Destailleur * Copyright (C) 2020 Tobias Sekan @@ -367,6 +370,90 @@ class vCard return $this->filename; } + /** + * Return a VCARD string + * + * @param Object $object Object + * @param Societe $company Company + * @param Translate $langs Lang object + * @return string String + */ + public function buildVCardString($object, $company, $langs) + { + $this->setProdId('Dolibarr '.DOL_VERSION); + + $this->setUid('DOLIBARR-USERID-'.$object->id); + $this->setName($object->lastname, $object->firstname, "", $object->civility_code, ""); + $this->setFormattedName($object->getFullName($langs, 1)); + + $this->setPhoneNumber($object->office_phone, "TYPE=WORK;VOICE"); + $this->setPhoneNumber($object->personal_mobile, "TYPE=HOME;VOICE"); + $this->setPhoneNumber($object->user_mobile, "TYPE=CELL;VOICE"); + $this->setPhoneNumber($object->office_fax, "TYPE=WORK;FAX"); + + $country = $object->country_code ? $object->country : ''; + + $this->setAddress("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=WORK;POSTAL"); + $this->setLabel("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=WORK"); + + $this->setEmail($object->email, "TYPE=WORK"); + $this->setNote($object->note_public); + $this->setTitle($object->job); + + if ($company->id > 0) { + $this->setURL($company->url, "TYPE=WORK"); + if (!$object->office_phone) { + $this->setPhoneNumber($company->phone, "TYPE=WORK;VOICE"); + } + if (!$object->office_fax) { + $this->setPhoneNumber($company->fax, "TYPE=WORK;FAX"); + } + if (!$object->zip) { + $this->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, "TYPE=WORK;POSTAL"); + } + + // when company e-mail is empty, use only user e-mail + if (empty(trim($company->email))) { + // was set before, don't set twice + } elseif (empty(trim($object->email))) { + // when user e-mail is empty, use only company e-mail + $this->setEmail($company->email, "TYPE=WORK"); + } else { + $tmpuser2 = explode("@", trim($object->email)); + $tmpcompany = explode("@", trim($company->email)); + + if (strtolower(end($tmpuser2)) == strtolower(end($tmpcompany))) { + // when e-mail domain of user and company are the same, use user e-mail at first (and company e-mail at second) + $this->setEmail($object->email, "TYPE=WORK"); + + // support by Microsoft Outlook (2019 and possible earlier) + $this->setEmail($company->email, 'INTERNET'); + } else { + // when e-mail of user and company complete different use company e-mail at first (and user e-mail at second) + $this->setEmail($company->email, "TYPE=WORK"); + + // support by Microsoft Outlook (2019 and possible earlier) + $this->setEmail($object->email, 'INTERNET'); + } + } + + // Si user lie a un tiers non de type "particulier" + if ($company->typent_code != 'TE_PRIVATE') { + $this->setOrg($company->name); + } + } + + // Personal informations + $this->setPhoneNumber($object->personal_mobile, "TYPE=HOME;VOICE"); + if ($object->birth) { + $this->setBirthday($object->birth); + } + + // Return VCard string + return $this->getVCard(); + } + + /* Example from Microsoft Outlook 2019 BEGIN:VCARD diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 7ac6150c5ac..ac774209d30 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -101,31 +101,41 @@ function getDolGlobalInt($key, $default = 0) } /** - * Return dolibarr user constant string value + * Return Dolibarr user constant string value * * @param string $key key to return value, return '' if not set * @param string $default value to return + * @param User $tmpuser To get another user than current user * @return string */ -function getDolUserString($key, $default = '') +function getDolUserString($key, $default = '', $tmpuser = null) { - global $user; + if (empty($tmpuser)) { + global $user; + $tmpuser = $user; + } + // return $conf->global->$key ?? $default; - return (string) (empty($user->conf->$key) ? $default : $user->conf->$key); + return (string) (empty($tmpuser->conf->$key) ? $default : $$tmpuser->conf->$key); } /** - * Return dolibarr user constant int value + * Return Dolibarr user constant int value * * @param string $key key to return value, return 0 if not set * @param int $default value to return + * @param User $tmpuser To get another user than current user * @return int */ -function getDolUserInt($key, $default = 0) +function getDolUserInt($key, $default = 0, $tmpuser = null) { - global $user; + if (empty($tmpuser)) { + global $user; + $tmpuser = $user; + } + // return $conf->global->$key ?? $default; - return (int) (empty($user->conf->$key) ? $default : $user->conf->$key); + return (int) (empty($tmpuser->conf->$key) ? $default : $tmpuser->conf->$key); } /** @@ -1717,7 +1727,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = * * @param string $name A name for the html component * @param string $label Label shown in Popup title top bar - * @param string $buttonstring button string + * @param string $buttonstring button string (HTML text we can click on) * @param string $url Relative Url to open. For example '/project/card.php' * @param string $disabled Disabled text * @param string $morecss More CSS @@ -1725,7 +1735,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = * Value is 'keyforpopupid:Name_of_html_component_to_set_with id,Name_of_html_component_to_set_with_label' * @return string HTML component with button */ -function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '', $morecss = 'button bordertransp', $backtopagejsfields = '') +function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '', $morecss = 'classlink button bordertransp', $backtopagejsfields = '') { global $conf; @@ -1753,7 +1763,7 @@ function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $di //print ''; $out .= ''; - $out .= 'use_javascript_ajax)) { $out .= ' href="'.DOL_URL_ROOT.$url.'" target="_blank"'; } @@ -2239,6 +2249,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi } } + // Show barcode if ($showbarcode) { $morehtmlleft .= '
'.$form->showbarcode($object, 100, 'photoref valignmiddle').'
'; } @@ -2988,9 +2999,10 @@ function dol_print_size($size, $shortvalue = 0, $shortunit = 0) * @param string $target Target for link * @param int $max Max number of characters to show * @param int $withpicto With picto + * @param string $morecss More CSS * @return string HTML Link */ -function dol_print_url($url, $target = '_blank', $max = 32, $withpicto = 0) +function dol_print_url($url, $target = '_blank', $max = 32, $withpicto = 0, $morecss = 'float') { global $langs; @@ -3013,7 +3025,12 @@ function dol_print_url($url, $target = '_blank', $max = 32, $withpicto = 0) } $link .= dol_trunc($url, $max); $link .= '
'; - return '
'.($withpicto ?img_picto($langs->trans("Url"), 'globe').' ' : '').$link.'
'; + + if ($morecss == 'float') { + return '
'.($withpicto ?img_picto($langs->trans("Url"), 'globe').' ' : '').$link.'
'; + } else { + return ''.($withpicto ?img_picto($langs->trans("Url"), 'globe').' ' : '').$link.''; + } } /** @@ -4067,7 +4084,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'filter', 'file-code', 'file-export', 'file-import', 'file-upload', 'autofill', 'folder', 'folder-open', 'folder-plus', 'generate', 'globe', 'globe-americas', 'graph', 'grip', 'grip_title', 'group', 'help', 'holiday', - 'images', 'incoterm', 'info', 'intervention', 'inventory', 'intracommreport', 'knowledgemanagement', + 'id-card', 'images', 'incoterm', 'info', 'intervention', 'inventory', 'intracommreport', 'knowledgemanagement', 'label', 'language', 'line', 'link', 'list', 'list-alt', 'listlight', 'loan', 'lock', 'lot', 'long-arrow-alt-right', 'margin', 'map-marker-alt', 'member', 'meeting', 'money-bill-alt', 'movement', 'mrp', 'note', 'next', 'off', 'on', 'order', @@ -4134,7 +4151,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'supplier'=>'building', 'technic'=>'cogs', 'timespent'=>'clock', 'title_setup'=>'tools', 'title_accountancy'=>'money-check-alt', 'title_bank'=>'university', 'title_hrm'=>'umbrella-beach', 'title_agenda'=>'calendar-alt', - 'uncheck'=>'times', 'uparrow'=>'share', 'url'=>'external-link-alt', 'vat'=>'money-check-alt', 'vcard'=>'address-card', + 'uncheck'=>'times', 'uparrow'=>'share', 'url'=>'external-link-alt', 'vat'=>'money-check-alt', 'vcard'=>'arrow-alt-circle-down', 'jabber'=>'comment-o', 'website'=>'globe-americas', 'workstation'=>'pallet', 'webhook'=>'bullseye', 'world'=>'globe', 'private'=>'user-lock', 'conferenceorbooth'=>'chalkboard-teacher', 'eventorganization'=>'project-diagram' diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index 692d01f9ef0..6b51cf76150 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -1784,7 +1784,7 @@ function weight_convert($weight, &$from_unit, $to_unit) * @param DoliDB $db Handler database * @param Conf $conf Object conf * @param User $user Object user - * @param array $tab Array (key=>value) with all parameters to save + * @param array $tab Array (key=>value) with all parameters to save/update * @return int <0 if KO, >0 if OK * * @see dolibarr_get_const(), dolibarr_set_const(), dolibarr_del_const() diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index 757e9f1dedf..2f691153292 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -129,3 +129,6 @@ IPLastLogin=IP last login IPPreviousLogin=IP previous login ShowAllPerms=Show all permission rows HideAllPerms=Hide all permission rows +UserPublicPageDesc=You can enable a virtual card for this user. An url with the user profile and a barcode will be available to allow anybody with a smartphone to scan it and add your contact to its address book. +EnablePublicVirtualCard=Enable the public virtual user card +PublicVirtualCardUrl=Public virtual user card \ No newline at end of file diff --git a/htdocs/public/users/view.php b/htdocs/public/users/view.php new file mode 100644 index 00000000000..2bc5e8e9245 --- /dev/null +++ b/htdocs/public/users/view.php @@ -0,0 +1,381 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/public/users/view.php + * \ingroup user + * \brief Public file to user profile + */ + +if (!defined('NOLOGIN')) { + define("NOLOGIN", 1); // This means this output page does not require to be logged. +} +if (!defined('NOCSRFCHECK')) { + define("NOCSRFCHECK", 1); // We accept to go on this page from external web site. +} +if (!defined('NOIPCHECK')) { + define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +} +if (!defined('NOBROWSERNOTIF')) { + define('NOBROWSERNOTIF', '1'); +} + +// Load Dolibarr environment +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/vcard.class.php'; + +// Load translation files required by the page +$langs->loadLangs(array("companies", "other", "recruitment")); + +// Get parameters +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'alpha'); +$backtopage = ''; + +$id = GETPOST('id', 'int'); +$securekey = GETPOST('securekey', 'alpha'); +$suffix = GETPOST('suffix'); + +$object = new User($db); +$object->fetch($id, '', '', 1); + +// Define $urlwithroot +//$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); +//$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +$urlwithroot = DOL_MAIN_URL_ROOT; // This is to use same domain name than current. For Paypal payment, we can use internal URL like localhost. + +// Security check +global $dolibarr_main_instance_unique_id; +$encodedsecurekey = dol_hash($dolibarr_main_instance_unique_id.'uservirtualcard'.$object->id.'-'.$object->login, 'md5'); +if ($encodedsecurekey != $securekey) { + httponly_accessforbidden('User profile page not found or not allowed'); +} + + +/* + * Actions + */ + +if ($cancel) { + if (!empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + $action = 'view'; +} + +/* +if ($action == "view" || $action == "presend" || $action == "dosubmit") { + $error = 0; + $display_ticket = false; + if (!strlen($ref)) { + $error++; + array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref"))); + $action = ''; + } + if (!strlen($email)) { + $error++; + array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Email"))); + $action = ''; + } else { + if (!isValidEmail($email)) { + $error++; + array_push($object->errors, $langs->trans("ErrorEmailInvalid")); + $action = ''; + } + } + + if (!$error) { + $ret = $object->fetch('', $ref); + } + + if ($error || $errors) { + setEventMessages($object->error, $object->errors, 'errors'); + if ($action == "dosubmit") { + $action = 'presend'; + } else { + $action = ''; + } + } +} +*/ +//var_dump($action); +//$object->doActions($action); + +// Actions to send emails (for ticket, we need to manage the addfile and removefile only) +/*$triggersendname = 'USER_SENTBYMAIL'; +$paramname = 'id'; +$autocopy = 'MAIN_MAIL_AUTOCOPY_USER_TO'; // used to know the automatic BCC to add +$trackid = 'use'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; +*/ + + +/* + * View + */ + +$form = new Form($db); +$company = $mysoc; + +if ($action == 'vcard') { + // We create VCard + $v = new vCard(); + $output = $v->buildVCardString($object, $company, $langs); + + $filename = trim(urldecode($v->getFileName())); // "Nom prenom.vcf" + $filenameurlencoded = dol_sanitizeFileName(urlencode($filename)); + //$filename = dol_sanitizeFileName($filename); + + top_httphead('text/x-vcard; name="'.$filename.'"'); + + header("Content-Disposition: attachment; filename=\"".$filename."\""); + header("Content-Length: ".dol_strlen($output)); + header("Connection: close"); + + print $output; + + $db->close(); + + exit; +} + +$head = ''; +if (!empty($conf->global->MAIN_USER_PROFILE_CSS_URL)) { + $head = ''."\n"; +} + +$conf->dol_hide_topmenu = 1; +$conf->dol_hide_leftmenu = 1; + +if (!getDolUserInt('USER_ENABLE_PUBLIC', 0, $object)) { + $langs->load("errors"); + print '
'.$langs->trans('ErrorPublicInterfaceNotEnabled').'
'; + $db->close(); + exit(); +} + +$arrayofjs = array(); +$arrayofcss = array(); + +$replacemainarea = (empty($conf->dol_hide_leftmenu) ? '
' : '').'
'; +llxHeader($head, $langs->trans("UserProfile").' '.$object->getFullName($langs), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea, 1, 1); + +print ''."\n"; +print '
'."\n"; +print '
'."\n"; +print ''."\n"; +print ''."\n"; +print ''."\n"; +print ''; +print "\n"; +print ''."\n"; + +$modulepart = 'user'; +$imagesize = 'small'; +$dir = $conf->user->dir_output; +$email = $object->email; + +// Show logo (search order: logo defined by ONLINE_SIGN_LOGO_suffix, then ONLINE_SIGN_LOGO_, then small company logo, large company logo, theme logo, common logo) +// Define logo and logosmall +$logo = ''; +$logosmall = ''; +if (!empty($object->photo)) { + if (dolIsAllowedForPreview($object->photo)) { + $logosmall = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.getImageFileNameForSize($object->photo, '_small'); + $logo = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.$object->photo; + //$originalfile = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.$object->photo; + } +} +//print ''."\n"; +// Define urllogo +$urllogo = ''; +$urllogofull = ''; +if (!empty($logosmall) && is_readable($conf->user->dir_output.'/'.$logosmall)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&file='.urlencode($logosmall); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&file='.urlencode($logosmall); +} elseif (!empty($logo) && is_readable($conf->user->dir_output.'/'.$logo)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&file='.urlencode($logo); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&file='.urlencode($logo); +} + +// Output html code for logo +print '
'; +print '
'; + +// Show photo +if ($urllogo) { + /*if (!empty($mysoc->url)) { + print ''; + }*/ + print ''; + /*if (!empty($mysoc->url)) { + print ''; + }*/ +} +print '
'; +/*if (empty($conf->global->MAIN_HIDE_POWERED_BY)) { + print ''; +}*/ +print '
'; + + +if (!empty($conf->global->USER_IMAGE_PUBLIC_INTERFACE)) { + print '
'; + print ''; + print '
'; +} + +$urlforqrcode = $_SERVER["PHP_SELF"].'?action=vcard&id='.((int) $object->id).'&securekey='.urlencode($securekey); + +// Show barcode +$showbarcode = GETPOST('nobarcode') ? 0 : 1; +if ($showbarcode) { + print '
'; + print '
'; + print 'QRCODE...
'; + print $urlforqrcode; + print '
'; + print '
'; + print '
'; +} + + +print '
'.$langs->trans("Me").'
'."\n"; +print ''."\n"; + +// Output payment summary form +print ''."\n"; + +print '
'; + +print '
'; + +print '
'; + +// Add contact info +print '...'; + +print '
'; + + +print '
'."\n"; +print "\n"; + +print '
'."\n"; + + + + +print '
'.$langs->trans("MyCompany").'
'."\n"; +print ''."\n"; + +// Output payment summary form +print ''."\n"; + +print '
'; + +print '
'; + +// Add company info + + +// Show logo (search order: logo defined by ONLINE_SIGN_LOGO_suffix, then ONLINE_SIGN_LOGO_, then small company logo, large company logo, theme logo, common logo) +// Define logo and logosmall +$logosmall = $mysoc->logo_small; +$logo = $mysoc->logo; +$paramlogo = 'ONLINE_USER_LOGO_'.$suffix; +if (!empty($conf->global->$paramlogo)) { + $logosmall = $conf->global->$paramlogo; +} elseif (!empty($conf->global->ONLINE_USER_LOGO)) { + $logosmall = $conf->global->ONLINE_USER_LOGO; +} +//print ''."\n"; +// Define urllogo +$urllogo = ''; +$urllogofull = ''; +if (!empty($logosmall) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$logosmall)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall); +} elseif (!empty($logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$logo)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo); +} +// Output html code for logo +if ($urllogo) { + print '
'; + if (!empty($mysoc->url)) { + print ''; + } + print ''; + if (!empty($mysoc->url)) { + print ''; + } + print '
'; +} + + +if ($mysoc->email) { + print '
'; + print img_picto('', 'email', 'class="pictofixedwidth"').dol_print_email($mysoc->email, 0, 0, 1); + print '
'; +} + +if ($mysoc->url) { + print '
'; + print img_picto('', 'globe', 'class="pictofixedwidth"'); + //print 'rr'; + print dol_print_url($mysoc->url, '_blank', 0, 0, ''); + print '
'; +} + + +print '
'."\n"; +print "\n"; + +print '
'."\n"; + + + +// Description +$text = getDolUserString('USER_PUBLIC_MORE', '', $object); +print $text; + + +print '
'."\n"; +print '
'."\n"; +print '
'; + + +//htmlPrintOnlinePaymentFooter($mysoc, $langs); + +print ''; + +llxFooter('', 'public'); + +$db->close(); diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 4f44ab20bad..983e571e399 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -910,7 +910,9 @@ textarea.centpercent { .nomarginright { margin-: unset; } - +.nowidthimp { + width: unset !important; +} .cursordefault { cursor: default; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 41c20074d6a..89358053ef3 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1147,6 +1147,9 @@ textarea.centpercent { .nomarginright { margin-: unset; } +.nowidthimp { + width: unset !important; +} .cursordefault { cursor: default; diff --git a/htdocs/user/card.php b/htdocs/user/card.php index f26d61da521..8fceddf313b 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1432,10 +1432,18 @@ if ($action == 'create' || $action == 'adduserldap') { if ($action != 'edit') { print dol_get_fiche_head($head, 'user', $title, -1, 'user'); - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; + //$urltovirtualcard = $object->getOnlineVirtualCardUrl(); + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); + + $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl"), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + /*$morehtmlref .= ''; + $morehtmlref .= img_picto($langs->trans("PublicVirtualCardUrl"), 'id-card', 'class="valignmiddle marginleftonly paddingrightonly"'); + $morehtmlref .= '';*/ + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index a4d4c7acfe6..9104dd5cfd4 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -3786,6 +3786,30 @@ class User extends CommonObject } } + /** + * Return string with full Url to virtual card + * + * @return string Url string + */ + public function getOnlineVirtualCardUrl() + { + global $dolibarr_main_instance_unique_id, $dolibarr_main_url_root; + global $conf; + + $encodedsecurekey = dol_hash($dolibarr_main_instance_unique_id.'uservirtualcard'.$this->id.'-'.$this->login, 'md5'); + if (isModEnabled('multicompany')) { + $entity_qr = '&entity='.((int) $conf->entity); + } else { + $entity_qr = ''; + } + // Define $urlwithroot + $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); + $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file + //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + + return $urlwithroot.'/public/users/view.php?id='.$this->id.'&securekey='.$encodedsecurekey.$entity_qr; + } + /** * Load all objects into $this->users * diff --git a/htdocs/user/info.php b/htdocs/user/info.php index dfb1fe23d0b..3f5d1aea604 100644 --- a/htdocs/user/info.php +++ b/htdocs/user/info.php @@ -51,7 +51,7 @@ $feature2 = (($socid && $user->rights->user->self->creer) ? '' : 'user'); $result = restrictedArea($user, 'user', $id, 'user&user', $feature2); // If user is not user that read and no permission to read other users, we stop -if (($object->id != $user->id) && (!$user->rights->user->user->lire)) { +if (($object->id != $user->id) && empty($user->rights->user->user->lire)) { accessforbidden(); } diff --git a/htdocs/user/vcard.php b/htdocs/user/vcard.php index 6e7035d99ec..576d2b90a5b 100644 --- a/htdocs/user/vcard.php +++ b/htdocs/user/vcard.php @@ -21,8 +21,8 @@ /** * \file htdocs/user/vcard.php - * \ingroup societe - * \brief Onglet vcard d'un user + * \ingroup user + * \brief Page to return a user vcard */ // Load Dolibarr environment @@ -31,9 +31,6 @@ require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/vcard.class.php'; -$user2 = new User($db); - - $id = GETPOST('id', 'int'); // Security check @@ -44,106 +41,38 @@ if ($user->socid > 0) { $feature2 = 'user'; $result = restrictedArea($user, 'user', $id, 'user', $feature2); - -$result = $user2->fetch($id); +$object = new User($db); +$result = $object->fetch($id); if ($result <= 0) { - dol_print_error($user2->error); + dol_print_error($object->error); exit; } -$physicalperson = 1; - +// Data from linked company $company = new Societe($db); -if ($user2->socid) { - $result = $company->fetch($user2->socid); +if ($object->socid > 0) { + $result = $company->fetch($object->socid); } + +/* + * View + */ + // We create VCard $v = new vCard(); -$v->setProdId('Dolibarr '.DOL_VERSION); - -$v->setUid('DOLIBARR-USERID-'.$user2->id); -$v->setName($user2->lastname, $user2->firstname, "", $user2->civility_code, ""); -$v->setFormattedName($user2->getFullName($langs, 1)); - -$v->setPhoneNumber($user2->office_phone, "TYPE=WORK;VOICE"); -$v->setPhoneNumber($user2->personal_mobile, "TYPE=HOME;VOICE"); -$v->setPhoneNumber($user2->user_mobile, "TYPE=CELL;VOICE"); -$v->setPhoneNumber($user2->office_fax, "TYPE=WORK;FAX"); - -$country = $user2->country_code ? $user2->country : ''; - -$v->setAddress("", "", $user2->address, $user2->town, $user2->state, $user2->zip, $country, "TYPE=WORK;POSTAL"); -$v->setLabel("", "", $user2->address, $user2->town, $user2->state, $user2->zip, $country, "TYPE=WORK"); - -$v->setEmail($user2->email, "TYPE=WORK"); -$v->setNote($user2->note_public); -$v->setTitle($user2->job); - -// Data from linked company -if ($company->id) { - $v->setURL($company->url, "TYPE=WORK"); - if (!$user2->office_phone) { - $v->setPhoneNumber($company->phone, "TYPE=WORK;VOICE"); - } - if (!$user2->office_fax) { - $v->setPhoneNumber($company->fax, "TYPE=WORK;FAX"); - } - if (!$user2->zip) { - $v->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, "TYPE=WORK;POSTAL"); - } - - // when company e-mail is empty, use only user e-mail - if (empty(trim($company->email))) { - // was set before, don't set twice - } elseif (empty(trim($user2->email))) { - // when user e-mail is empty, use only company e-mail - $v->setEmail($company->email, "TYPE=WORK"); - } else { - $tmpuser2 = explode("@", trim($user2->email)); - $tmpcompany = explode("@", trim($company->email)); - - if (strtolower(end($tmpuser2)) == strtolower(end($tmpcompany))) { - // when e-mail domain of user and company are the same, use user e-mail at first (and company e-mail at second) - $v->setEmail($user2->email, "TYPE=WORK"); - - // support by Microsoft Outlook (2019 and possible earlier) - $v->setEmail($company->email, 'INTERNET'); - } else { - // when e-mail of user and company complete different use company e-mail at first (and user e-mail at second) - $v->setEmail($company->email, "TYPE=WORK"); - - // support by Microsoft Outlook (2019 and possible earlier) - $v->setEmail($user2->email, 'INTERNET'); - } - } - - // Si user lie a un tiers non de type "particulier" - if ($company->typent_code != 'TE_PRIVATE') { - $v->setOrg($company->name); - } -} - -// Personal informations -$v->setPhoneNumber($user2->personal_mobile, "TYPE=HOME;VOICE"); -if ($user2->birth) { - $v->setBirthday($user2->birth); -} - -$db->close(); - -// Renvoi la VCard au navigateur - -$output = $v->getVCard(); +$output = $v->buildVCardString($object, $company, $langs); $filename = trim(urldecode($v->getFileName())); // "Nom prenom.vcf" $filenameurlencoded = dol_sanitizeFileName(urlencode($filename)); //$filename = dol_sanitizeFileName($filename); +top_httphead('text/x-vcard; name="'.$filename.'"'); header("Content-Disposition: attachment; filename=\"".$filename."\""); header("Content-Length: ".dol_strlen($output)); header("Connection: close"); -header("Content-Type: text/x-vcard; name=\"".$filename."\""); print $output; + +$db->close(); diff --git a/htdocs/user/virtualcard.php b/htdocs/user/virtualcard.php new file mode 100644 index 00000000000..30dc32ad01c --- /dev/null +++ b/htdocs/user/virtualcard.php @@ -0,0 +1,248 @@ + + * Copyright (C) 2005-2015 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/user/virtualcard.php + * \ingroup core + * \brief Page to setup a virtual card + */ + +// Load Dolibarr environment +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; + +// Load translation files required by page +$langs->load("users"); + +// Security check +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); + +$object = new User($db); +if ($id > 0 || !empty($ref)) { + $result = $object->fetch($id, $ref, '', 1); + $object->getrights(); +} + +// Security check +$socid = 0; +if ($user->socid > 0) { + $socid = $user->socid; +} +$feature2 = (($socid && $user->rights->user->self->creer) ? '' : 'user'); + +$result = restrictedArea($user, 'user', $id, 'user&user', $feature2); + +// If user is not the user that read and has no permission to read other users, we stop +if (($object->id != $user->id) && empty($user->rights->user->user->lire)) { + accessforbidden(); +} + +/* + * Actions + */ + +if ($action == 'update') { + $tmparray = array(); + $tmparray['USER_PUBLIC_COMPANY_NAME'] = (GETPOST('USER_PUBLIC_COMPANY_NAME') ? 1 : 0); + $tmparray['USER_PUBLIC_JOBPOSITION'] = (GETPOST('USER_PUBLIC_JOBPOSITION') ? 1 : 0); + $tmparray['USER_PUBLIC_EMAIL'] = (GETPOST('USER_PUBLIC_EMAIL') ? 1 : 0); + $tmparray['USER_PUBLIC_PHONE'] = (GETPOST('USER_PUBLIC_PHONE') ? 1 : 0); + $tmparray['USER_PUBLIC_SOCIALNETWORKS'] = (GETPOST('USER_PUBLIC_SOCIALNETWORKS') ? 1 : 0); + $tmparray['USER_PUBLIC_MORE'] = (GETPOST('USER_PUBLIC_MORE') ? GETPOST('USER_PUBLIC_MORE') : ''); + + dol_set_user_param($db, $conf, $object, $tmparray); +} + +if ($action == 'setUSER_ENABLE_PUBLIC') { + if (GETPOST('value')) { + $tmparray = array('USER_ENABLE_PUBLIC' => 1); + } else { + $tmparray = array('USER_ENABLE_PUBLIC' => 0); + } + dol_set_user_param($db, $conf, $object, $tmparray); +} + + +/* + * View + */ + +$form = new Form($db); + +$person_name = !empty($object->firstname) ? $object->lastname.", ".$object->firstname : $object->lastname; +$title = $person_name." - ".$langs->trans('Info'); +$help_url = ''; +llxHeader('', $title, $help_url); + +$head = user_prepare_head($object); + +$title = $langs->trans("User"); +//print dol_get_fiche_head($head, 'info', $title, -1, 'user'); + + +$linkback = ''; + +if ($user->rights->user->user->lire || $user->admin) { + $linkback = ''.$langs->trans("BackToList").''; +} + +$morehtmlref = ''; +$morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); +$morehtmlref .= ''; + +//dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); + + +print '
'; + +print '
'; + +/* + print ''.$langs->trans("VCard").'
'; + +print ''; +print img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); +print ''; + + +print '
'; +//print '
'; + +print '
'; +*/ + +print ''.$langs->trans("UserPublicPageDesc").'

'; + +$param = '&id='.((int) $object->id); + +$enabledisablehtml = $langs->trans("EnablePublicVirtualCard").' '; +if (!getDolUserInt('USER_ENABLE_PUBLIC', 0, $object)) { + // Button off, click to enable + $enabledisablehtml .= ''; + $enabledisablehtml .= img_picto($langs->trans("Disabled"), 'switch_off'); + $enabledisablehtml .= ''; +} else { + // Button on, click to disable + $enabledisablehtml .= ''; + $enabledisablehtml .= img_picto($langs->trans("Activated"), 'switch_on'); + $enabledisablehtml .= ''; +} +print $enabledisablehtml; +print ''; + +print '

'; + +print '
'; +print ''; +print ''; +print ''; + +if (getDolUserInt('USER_ENABLE_PUBLIC', 0, $object)) { + print '
'; + //print $langs->trans('FollowingLinksArePublic').'
'; + print img_picto('', 'globe').' '.$langs->trans('PublicVirtualCardUrl').'
'; + + $fullexternaleurltovirtualcard = $object->getOnlineVirtualCardUrl(); + + print ''; + print ajax_autoselect('publicurluser'); + + print '
'; + + print '
'; + print ''; + + print ''; + print ''; + print ''; + print "\n"; + + // Company name + print '\n"; + + // Job position + print '\n"; + + // Email + print '\n"; + + // Phone + print '\n"; + + // Social networks + print '\n"; + + // More + print '\n"; + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + print $langs->trans("Company"); + print ''; + //print ''; + print $form->selectyesno("USER_PUBLIC_COMPANY_NAME", (getDolUserInt('USER_PUBLIC_COMPANY_NAME', 0, $object) ? getDolUserInt('USER_PUBLIC_COMPANY_NAME', 0, $object) : 0), 1); + print "
'; + print $langs->trans("PostOrFunction"); + print ''; + print $form->selectyesno("USER_PUBLIC_JOBPOSITION", (getDolUserInt('USER_PUBLIC_JOBPOSITION', 0, $object) ? getDolUserInt('USER_PUBLIC_JOBPOSITION', 0, $object) : 0), 1); + print "
'; + print $langs->trans("Email"); + print ''; + print $form->selectyesno("USER_PUBLIC_EMAIL", (getDolUserInt('USER_PUBLIC_EMAIL', 0, $object) ? getDolUserInt('USER_PUBLIC_EMAIL', 0, $object) : 0), 1); + print "
'; + print $langs->trans("Phone"); + print ''; + print $form->selectyesno("USER_PUBLIC_PHONE", (getDolUserInt('USER_PUBLIC_PHONE', 0, $object) ? getDolUserInt('USER_PUBLIC_PHONE', 0, $object) : 0), 1); + print "
'; + print $langs->trans("SocialNetworks"); + print ''; + print $form->selectyesno("USER_PUBLIC_SOCIALNETWORKS", (getDolUserInt('USER_PUBLIC_SOCIALNETWORKS', 0, $object) ? getDolUserInt('USER_PUBLIC_SOCIALNETWORKS', 0, $object) : 0), 1); + print "
'; + print $langs->trans("More"); + print ''; + require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; + $doleditor = new DolEditor('USER_PUBLIC_MORE', getDolUserString('USER_PUBLIC_MORE', '', $object), '', 160, 'dolibarr_notes', '', false, false, isModEnabled('fckeditor'), ROWS_5, '90%'); + $doleditor->Create(); + print "
'; + print '
'; + + print '
'; + print ''; + print '
'; +} + + +print dol_get_fiche_end(); + +print '
'; + + +print '
'; + + +print dol_get_fiche_end(); + +// End of page +llxFooter(); +$db->close(); From 2c9e4495dbd4afca5765e08d36a61fcbb8072ca7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Jan 2023 04:43:09 +0100 Subject: [PATCH 367/816] Fix url --- htdocs/public/recruitment/view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/recruitment/view.php b/htdocs/public/recruitment/view.php index de8297d3ef0..3626693ce89 100644 --- a/htdocs/public/recruitment/view.php +++ b/htdocs/public/recruitment/view.php @@ -223,7 +223,7 @@ if ($urllogo) { if (!empty($mysoc->url)) { print ''; } - print ''; + print ''; if (!empty($mysoc->url)) { print ''; } From 183552461c796b326264820aebc21ee6b3ced1e2 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sat, 7 Jan 2023 08:20:48 +0100 Subject: [PATCH 368/816] NEW Accountancy - Add an option to disable autolettering when transferring to accounting --- htdocs/accountancy/admin/index.php | 28 +++++++++++++++++++ htdocs/accountancy/journal/bankjournal.php | 2 +- .../accountancy/journal/purchasesjournal.php | 2 +- htdocs/accountancy/journal/sellsjournal.php | 2 +- htdocs/langs/en_US/accountancy.lang | 1 + 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 244b6f72330..5caa92ec9ee 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -261,6 +261,20 @@ if ($action == 'setenablelettering') { } } +if ($action == 'setenableautolettering') { + $setenableautolettering = GETPOST('value', 'int'); + $res = dolibarr_set_const($db, "ACCOUNTING_ENABLE_AUTOLETTERING", $setenableautolettering, 'yesno', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + if (!$error) { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'mesgs'); + } +} + /* * View @@ -479,6 +493,7 @@ if (!empty($conf->global->ACCOUNTING_DISABLE_BINDING_ON_EXPENSEREPORTS)) { print ''; print ''; +print '
'; // Lettering params print ''; @@ -499,6 +514,19 @@ if (!empty($conf->global->ACCOUNTING_ENABLE_LETTERING)) { } print ''; +print ''; +print ''; +if (!empty($conf->global->ACCOUNTING_ENABLE_AUTOLETTERING)) { + print ''; +} else { + print ''; +} +print ''; + print '
'.$langs->trans("ACCOUNTING_ENABLE_AUTOLETTERING").''; + print img_picto($langs->trans("Activated"), 'switch_on'); + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print '
'; print '
'; diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 4aba6bfeda4..699002395ab 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -793,7 +793,7 @@ if (!$error && $action == 'writebookkeeping') { setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); } } else { - if ($lettering && getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) { + if ($lettering && getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) { require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php'; $lettering_static = new Lettering($db); $nb_lettering = $lettering_static->bookkeepingLetteringAll(array($bookkeeping->id)); diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index a5b82e7b2d0..746383fef0b 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -376,7 +376,7 @@ if ($action == 'writebookkeeping') { setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); } } else { - if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) { + if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) { require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php'; $lettering_static = new Lettering($db); $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id)); diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 0519762baef..f67fd76b3f1 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -390,7 +390,7 @@ if ($action == 'writebookkeeping') { setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); } } else { - if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING')) { + if (getDolGlobalInt('ACCOUNTING_ENABLE_LETTERING') && getDolGlobalInt('ACCOUNTING_ENABLE_AUTOLETTERING')) { require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php'; $lettering_static = new Lettering($db); $nb_lettering = $lettering_static->bookkeepingLettering(array($bookkeeping->id)); diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 9822a52e8f0..5a1e51a2269 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -339,6 +339,7 @@ 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_AUTOLETTERING=Enable the automatic lettering when transferring to accounting ## Export NotExportLettering=Do not export the lettering when generating the file From 192d641b26e997b8a540eb3cd455b5704186cb7d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Jan 2023 11:29:43 +0100 Subject: [PATCH 369/816] Update for doxygen generation from command line --- build/doxygen/dolibarr-doxygen-build.pl | 10 +- build/doxygen/dolibarr-doxygen.doxyfile | 98 +- build/doxygen/doxygen-awesome.css | 2413 +++++++++++++++++++++++ 3 files changed, 2477 insertions(+), 44 deletions(-) create mode 100644 build/doxygen/doxygen-awesome.css diff --git a/build/doxygen/dolibarr-doxygen-build.pl b/build/doxygen/dolibarr-doxygen-build.pl index 75a5cceddbe..5a4849a3a5b 100755 --- a/build/doxygen/dolibarr-doxygen-build.pl +++ b/build/doxygen/dolibarr-doxygen-build.pl @@ -17,9 +17,9 @@ use Cwd; my $dir = getcwd; print "Current dir is: $dir\n"; -print "Running dir for doxygen must be: $DIR\n"; +#print "Running dir for doxygen must be: $DIR\n"; -if (! -s $CONFFILE) +if (! -s "build/doxygen/$CONFFILE") { print "Error: current directory for building Dolibarr doxygen documentation is not correct.\n"; print "\n"; @@ -30,7 +30,7 @@ if (! -s $CONFFILE) exit 1; } -$SOURCE="../.."; +$SOURCE="."; # Get version $MAJOR, $MINOR and $BUILD $result = open( IN, "< " . $SOURCE . "/htdocs/filefunc.inc.php" ); @@ -47,8 +47,8 @@ $version=$MAJOR.".".$MINOR.".".$BUILD; print "Running doxygen for version ".$version.", please wait...\n"; -print "cat $CONFFILE | sed -e 's/x\.y\.z/".$version."/' | doxygen $OPTIONS - 2>&1\n"; -$result=`cat $CONFFILE | sed -e 's/x\.y\.z/$version/' | doxygen $OPTIONS - 2>&1`; +print "cat build/doxygen/$CONFFILE | sed -e 's/x\.y\.z/".$version."/' | doxygen $OPTIONS - 2>&1\n"; +$result=`cat build/doxygen/$CONFFILE | sed -e 's/x\.y\.z/$version/' | doxygen $OPTIONS - 2>&1`; print $result; diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index 31400661ecc..6f668ebad7e 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -1,14 +1,17 @@ -# Doxyfile 1.7.3 +# Doxyfile 1.8.16 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options @@ -38,7 +41,7 @@ PROJECT_NUMBER = x.y.z # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = ../../build +OUTPUT_DIRECTORY = build # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output @@ -114,7 +117,7 @@ FULL_PATH_NAMES = YES # If left blank the directory from which doxygen is run is used as the # path to strip. -STRIP_FROM_PATH = "../.." +STRIP_FROM_PATH = "/home/dolibarr/doxygen.dolibarr.org/" # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells @@ -287,7 +290,7 @@ TYPEDEF_HIDES_STRUCT = NO # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols -SYMBOL_CACHE_SIZE = 0 +#SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options @@ -448,7 +451,7 @@ GENERATE_TODOLIST = NO # disable (NO) the test list. This list is created by putting \test # commands in the documentation. -GENERATE_TESTLIST = YES +GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug @@ -487,7 +490,7 @@ SHOW_USED_FILES = YES # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. -SHOW_DIRECTORIES = YES +#SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the @@ -571,7 +574,7 @@ WARN_FORMAT = "$file:$line: $text" # and error messages should be written. If left blank the output is written # to stderr. -WARN_LOGFILE = doxygen_warnings.log +WARN_LOGFILE = build/html/doxygen_warnings.log #--------------------------------------------------------------------------- # configuration options related to the input files @@ -582,7 +585,7 @@ WARN_LOGFILE = doxygen_warnings.log # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../../htdocs ../../scripts +INPUT = htdocs scripts # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -611,7 +614,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = ../../build ../../dev ../../doc ../../document ../../documents ../../htdocs/conf/conf.php ../../htdocs/custom ../../htdocs/document ../../htdocs/documents ../../htdocs/includes +EXCLUDE = build dev doc document documents htdocs/conf/conf.php htdocs/custom htdocs/document htdocs/documents htdocs/includes htdocs/install/doctemplates # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded @@ -625,7 +628,7 @@ EXCLUDE_SYMLINKS = YES # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* -EXCLUDE_PATTERNS = */CVS/* *google* *pibarcode* +EXCLUDE_PATTERNS = */CVS/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -639,27 +642,27 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = ../../htdocs/modulebuilder/template +#EXAMPLE_PATH = htdocs/modulebuilder/template # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. -EXAMPLE_PATTERNS = *.php +#EXAMPLE_PATTERNS = *.php # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. -EXAMPLE_RECURSIVE = NO +#EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = ../../doc/images +IMAGE_PATH = doc/images # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -762,7 +765,7 @@ ALPHABETICAL_INDEX = YES # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) -COLS_IN_ALPHA_INDEX = 5 +#COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. @@ -775,14 +778,16 @@ IGNORE_PREFIX = # configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html @@ -797,14 +802,14 @@ HTML_FILE_EXTENSION = .html # standard header. # Does not work with 1.7.3 -#HTML_HEADER = doxygen_header.html +#HTML_HEADER = build/doxygen/doxygen_header.html # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. # Does not work with 1.7.3 -HTML_FOOTER = doxygen_footer.html +HTML_FOOTER = build/doxygen/doxygen_footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to @@ -850,7 +855,18 @@ HTML_TIMESTAMP = YES # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. -HTML_ALIGN_MEMBERS = YES +#HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the @@ -858,7 +874,7 @@ HTML_ALIGN_MEMBERS = YES # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). -HTML_DYNAMIC_SECTIONS = YES +HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 @@ -1003,7 +1019,7 @@ QHG_LOCATION = # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. -GENERATE_ECLIPSEHELP = YES +GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have @@ -1035,7 +1051,7 @@ GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. -USE_INLINE_TREES = NO +#USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree @@ -1072,7 +1088,7 @@ FORMULA_TRANSPARENT = YES # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. -SEARCHENGINE = NO +SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client @@ -1082,7 +1098,7 @@ SEARCHENGINE = NO # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. -SERVER_BASED_SEARCH = NO +SERVER_BASED_SEARCH = YES #--------------------------------------------------------------------------- # configuration options related to the LaTeX output @@ -1260,13 +1276,13 @@ XML_OUTPUT = xml # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_SCHEMA = +#XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_DTD = +#XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting @@ -1431,7 +1447,7 @@ EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). -PERL_PATH = /usr/bin/perl +#PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool @@ -1453,7 +1469,7 @@ CLASS_DIAGRAMS = NO # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. -MSCGEN_PATH = +#MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented @@ -1485,7 +1501,7 @@ DOT_NUM_THREADS = 0 # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. -DOT_FONTNAME = FreeSans.ttf +#DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. @@ -1634,3 +1650,7 @@ GENERATE_LEGEND = YES # the various graphs. DOT_CLEANUP = YES + + +FULL_SIDEBAR = NO +HTML_EXTRA_STYLESHEET = build/doxygen/doxygen-awesome.css diff --git a/build/doxygen/doxygen-awesome.css b/build/doxygen/doxygen-awesome.css new file mode 100644 index 00000000000..0b1c8c20892 --- /dev/null +++ b/build/doxygen/doxygen-awesome.css @@ -0,0 +1,2413 @@ +/** + +Doxygen Awesome +https://github.com/jothepro/doxygen-awesome-css + +MIT License + +Copyright (c) 2021 - 2022 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +html { + /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ + --primary-color: #1779c4; + --primary-dark-color: #335c80; + --primary-light-color: #70b1e9; + + /* page base colors */ + --page-background-color: #ffffff; + --page-foreground-color: #2f4153; + --page-secondary-foreground-color: #6f7e8e; + + /* color for all separators on the website: hr, borders, ... */ + --separator-color: #dedede; + + /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */ + --border-radius-large: 8px; + --border-radius-small: 4px; + --border-radius-medium: 6px; + + /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */ + --spacing-small: 5px; + --spacing-medium: 10px; + --spacing-large: 16px; + + /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */ + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); + + --odd-color: rgba(0,0,0,.028); + + /* font-families. will affect all text on the website + * font-family: the normal font for text, headlines, menus + * font-family-monospace: used for preformatted text in memtitle, code, fragments + */ + --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif; + --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; + + /* font sizes */ + --page-font-size: 15.6px; + --navigation-font-size: 14.4px; + --toc-font-size: 13.4px; + --code-font-size: 14px; /* affects code, fragment */ + --title-font-size: 22px; + + /* content text properties. These only affect the page content, not the navigation or any other ui elements */ + --content-line-height: 27px; + /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ + --content-maxwidth: 1050px; + --table-line-height: 24px; + --toc-sticky-top: var(--spacing-medium); + --toc-width: 200px; + --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px); + + /* colors for various content boxes: @warning, @note, @deprecated @bug */ + --warning-color: #f8d1cc; + --warning-color-dark: #b61825; + --warning-color-darker: #75070f; + --note-color: #faf3d8; + --note-color-dark: #f3a600; + --note-color-darker: #5f4204; + --todo-color: #e4f3ff; + --todo-color-dark: #1879C4; + --todo-color-darker: #274a5c; + --deprecated-color: #ecf0f3; + --deprecated-color-dark: #5b6269; + --deprecated-color-darker: #43454a; + --bug-color: #e4dafd; + --bug-color-dark: #5b2bdd; + --bug-color-darker: #2a0d72; + --invariant-color: #d8f1e3; + --invariant-color-dark: #44b86f; + --invariant-color-darker: #265532; + + /* blockquote colors */ + --blockquote-background: #f8f9fa; + --blockquote-foreground: #636568; + + /* table colors */ + --tablehead-background: #f1f1f1; + --tablehead-foreground: var(--page-foreground-color); + + /* menu-display: block | none + * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible. + * `GENERATE_TREEVIEW` MUST be enabled! + */ + --menu-display: block; + + --menu-focus-foreground: var(--page-background-color); + --menu-focus-background: var(--primary-color); + --menu-selected-background: rgba(0,0,0,.05); + + + --header-background: var(--page-background-color); + --header-foreground: var(--page-foreground-color); + + /* searchbar colors */ + --searchbar-background: var(--side-nav-background); + --searchbar-foreground: var(--page-foreground-color); + + /* searchbar size + * (`searchbar-width` is only applied on screens >= 768px. + * on smaller screens the searchbar will always fill the entire screen width) */ + --searchbar-height: 33px; + --searchbar-width: 210px; + --searchbar-border-radius: var(--searchbar-height); + + /* code block colors */ + --code-background: #f5f5f5; + --code-foreground: var(--page-foreground-color); + + /* fragment colors */ + --fragment-background: #F8F9FA; + --fragment-foreground: #37474F; + --fragment-keyword: #bb6bb2; + --fragment-keywordtype: #8258b3; + --fragment-keywordflow: #d67c3b; + --fragment-token: #438a59; + --fragment-comment: #969696; + --fragment-link: #5383d6; + --fragment-preprocessor: #46aaa5; + --fragment-linenumber-color: #797979; + --fragment-linenumber-background: #f4f4f5; + --fragment-linenumber-border: #e3e5e7; + --fragment-lineheight: 20px; + + /* sidebar navigation (treeview) colors */ + --side-nav-background: #fbfbfb; + --side-nav-foreground: var(--page-foreground-color); + --side-nav-arrow-opacity: 0; + --side-nav-arrow-hover-opacity: 0.9; + + --toc-background: var(--side-nav-background); + --toc-foreground: var(--side-nav-foreground); + + /* height of an item in any tree / collapsable table */ + --tree-item-height: 30px; + + --memname-font-size: var(--code-font-size); + --memtitle-font-size: 18px; + + --webkit-scrollbar-size: 7px; + --webkit-scrollbar-padding: 4px; + --webkit-scrollbar-color: var(--separator-color); +} + +@media screen and (max-width: 767px) { + html { + --page-font-size: 16px; + --navigation-font-size: 16px; + --toc-font-size: 15px; + --code-font-size: 15px; /* affects code, fragment */ + --title-font-size: 22px; + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: #1C1D1F; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #2e1917; + --warning-color-dark: #ad2617; + --warning-color-darker: #f5b1aa; + --note-color: #3b2e04; + --note-color-dark: #f1b602; + --note-color-darker: #ceb670; + --todo-color: #163750; + --todo-color-dark: #1982D2; + --todo-color-darker: #dcf0fa; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2a2536; + --bug-color-dark: #7661b3; + --bug-color-darker: #ae9ed6; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; + } +} + +/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */ +html.dark-mode { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: #1C1D1F; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #2e1917; + --warning-color-dark: #ad2617; + --warning-color-darker: #f5b1aa; + --note-color: #3b2e04; + --note-color-dark: #f1b602; + --note-color-darker: #ceb670; + --todo-color: #163750; + --todo-color-dark: #1982D2; + --todo-color-darker: #dcf0fa; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2a2536; + --bug-color-dark: #7661b3; + --bug-color-darker: #ae9ed6; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; +} + +body { + color: var(--page-foreground-color); + background-color: var(--page-background-color); + font-size: var(--page-font-size); +} + +body, table, div, p, dl, #nav-tree .label, .title, +.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, +.SelectItem, #MSearchField, .navpath li.navelem a, +.navpath li.navelem a:hover, p.reference, p.definition { + font-family: var(--font-family); +} + +h1, h2, h3, h4, h5 { + margin-top: .9em; + font-weight: 600; + line-height: initial; +} + +p, div, table, dl, p.reference, p.definition { + font-size: var(--page-font-size); +} + +p.reference, p.definition { + color: var(--page-secondary-foreground-color); +} + +a:link, a:visited, a:hover, a:focus, a:active { + color: var(--primary-color) !important; + font-weight: 500; +} + +a.anchor { + scroll-margin-top: var(--spacing-large); + display: block; +} + +/* + Title and top navigation + */ + +#top { + background: var(--header-background); + border-bottom: 1px solid var(--separator-color); +} + +@media screen and (min-width: 768px) { + #top { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + } +} + +#main-nav { + flex-grow: 5; + padding: var(--spacing-small) var(--spacing-medium); +} + +#titlearea { + width: auto; + padding: var(--spacing-medium) var(--spacing-large); + background: none; + color: var(--header-foreground); + border-bottom: none; +} + +@media screen and (max-width: 767px) { + #titlearea { + padding-bottom: var(--spacing-small); + } +} + +#titlearea table tbody tr { + height: auto !important; +} + +#projectname { + font-size: var(--title-font-size); + font-weight: 600; +} + +#projectnumber { + font-family: inherit; + font-size: 60%; +} + +#projectbrief { + font-family: inherit; + font-size: 80%; +} + +#projectlogo { + vertical-align: middle; +} + +#projectlogo img { + max-height: calc(var(--title-font-size) * 2); + margin-right: var(--spacing-small); +} + +.sm-dox, .tabs, .tabs2, .tabs3 { + background: none; + padding: 0; +} + +.tabs, .tabs2, .tabs3 { + border-bottom: 1px solid var(--separator-color); + margin-bottom: -1px; +} + +.main-menu-btn-icon, .main-menu-btn-icon:before, .main-menu-btn-icon:after { + background: var(--page-secondary-foreground-color); +} + +@media screen and (max-width: 767px) { + .sm-dox a span.sub-arrow { + background: var(--code-background); + } + + #main-menu a.has-submenu span.sub-arrow { + color: var(--page-secondary-foreground-color); + border-radius: var(--border-radius-medium); + } + + #main-menu a.has-submenu:hover span.sub-arrow { + color: var(--page-foreground-color); + } +} + +@media screen and (min-width: 768px) { + .sm-dox li, .tablist li { + display: var(--menu-display); + } + + .sm-dox a span.sub-arrow { + border-color: var(--header-foreground) transparent transparent transparent; + } + + .sm-dox a:hover span.sub-arrow { + border-color: var(--menu-focus-foreground) transparent transparent transparent; + } + + .sm-dox ul a span.sub-arrow { + border-color: transparent transparent transparent var(--page-foreground-color); + } + + .sm-dox ul a:hover span.sub-arrow { + border-color: transparent transparent transparent var(--menu-focus-foreground); + } +} + +.sm-dox ul { + background: var(--page-background-color); + box-shadow: var(--box-shadow); + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium) !important; + padding: var(--spacing-small); + animation: ease-out 150ms slideInMenu; +} + +@keyframes slideInMenu { + from { + opacity: 0; + transform: translate(0px, -2px); + } + + to { + opacity: 1; + transform: translate(0px, 0px); + } +} + +.sm-dox ul a { + color: var(--page-foreground-color) !important; + background: var(--page-background-color); + font-size: var(--navigation-font-size); +} + +.sm-dox>li>ul:after { + border-bottom-color: var(--page-background-color) !important; +} + +.sm-dox>li>ul:before { + border-bottom-color: var(--separator-color) !important; +} + +.sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus { + font-size: var(--navigation-font-size) !important; + color: var(--menu-focus-foreground) !important; + text-shadow: none; + background-color: var(--menu-focus-background); + border-radius: var(--border-radius-small) !important; +} + +.sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a { + text-shadow: none; + background: transparent; + background-image: none !important; + color: var(--header-foreground) !important; + font-weight: normal; + font-size: var(--navigation-font-size); + border-radius: var(--border-radius-small) !important; +} + +.sm-dox a:focus { + outline: auto; +} + +.sm-dox a:hover, .sm-dox a:active, .tablist li a:hover { + text-shadow: none; + font-weight: normal; + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; + border-radius: var(--border-radius-small) !important; + font-size: var(--navigation-font-size); +} + +.tablist li.current { + border-radius: var(--border-radius-small); + background: var(--menu-selected-background); +} + +.tablist li { + margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small); +} + +.tablist a { + padding: 0 var(--spacing-large); +} + + +/* + Search box + */ + +#MSearchBox { + height: var(--searchbar-height); + background: var(--searchbar-background); + border-radius: var(--searchbar-border-radius); + border: 1px solid var(--separator-color); + overflow: hidden; + width: var(--searchbar-width); + position: relative; + box-shadow: none; + display: block; + margin-top: 0; +} + +/* until Doxygen 1.9.4 */ +.left img#MSearchSelect { + left: 0; + user-select: none; + padding-left: 8px; +} + +/* Doxygen 1.9.5 */ +.left span#MSearchSelect { + left: 0; + user-select: none; + margin-left: 8px; + padding: 0; +} + +.left #MSearchSelect[src$=".png"] { + padding-left: 0 +} + +.SelectionMark { + user-select: none; +} + +.tabs .left #MSearchSelect { + padding-left: 0; +} + +.tabs #MSearchBox { + position: absolute; + right: var(--spacing-medium); +} + +@media screen and (max-width: 767px) { + .tabs #MSearchBox { + position: relative; + right: 0; + margin-left: var(--spacing-medium); + margin-top: 0; + } +} + +#MSearchSelectWindow, #MSearchResultsWindow { + z-index: 9999; +} + +#MSearchBox.MSearchBoxActive { + border-color: var(--primary-color); + box-shadow: inset 0 0 0 1px var(--primary-color); +} + +#main-menu > li:last-child { + margin-right: 0; +} + +@media screen and (max-width: 767px) { + #main-menu > li:last-child { + height: 50px; + } +} + +#MSearchField { + font-size: var(--navigation-font-size); + height: calc(var(--searchbar-height) - 2px); + background: transparent; + width: calc(var(--searchbar-width) - 64px); +} + +.MSearchBoxActive #MSearchField { + color: var(--searchbar-foreground); +} + +#MSearchSelect { + top: calc(calc(var(--searchbar-height) / 2) - 11px); +} + +#MSearchBox span.left, #MSearchBox span.right { + background: none; + background-image: none; +} + +#MSearchBox span.right { + padding-top: calc(calc(var(--searchbar-height) / 2) - 12px); + position: absolute; + right: var(--spacing-small); +} + +.tabs #MSearchBox span.right { + top: calc(calc(var(--searchbar-height) / 2) - 12px); +} + +@keyframes slideInSearchResults { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } +} + +#MSearchResultsWindow { + left: auto !important; + right: var(--spacing-medium); + border-radius: var(--border-radius-large); + border: 1px solid var(--separator-color); + transform: translate(0, 20px); + box-shadow: var(--box-shadow); + animation: ease-out 280ms slideInSearchResults; + background: var(--page-background-color); +} + +iframe#MSearchResults { + margin: 4px; +} + +iframe { + color-scheme: normal; +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) iframe#MSearchResults { + filter: invert() hue-rotate(180deg); + } +} + +html.dark-mode iframe#MSearchResults { + filter: invert() hue-rotate(180deg); +} + +#MSearchResults .SRPage { + background-color: transparent; +} + +#MSearchResults .SRPage .SREntry { + font-size: 10pt; + padding: var(--spacing-small) var(--spacing-medium); +} + +#MSearchSelectWindow { + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + box-shadow: var(--box-shadow); + background: var(--page-background-color); + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); +} + +#MSearchSelectWindow a.SelectItem { + font-size: var(--navigation-font-size); + line-height: var(--content-line-height); + margin: 0 var(--spacing-small); + border-radius: var(--border-radius-small); + color: var(--page-foreground-color) !important; + font-weight: normal; +} + +#MSearchSelectWindow a.SelectItem:hover { + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; +} + +@media screen and (max-width: 767px) { + #MSearchBox { + margin-top: var(--spacing-medium); + margin-bottom: var(--spacing-medium); + width: calc(100vw - 30px); + } + + #main-menu > li:last-child { + float: none !important; + } + + #MSearchField { + width: calc(100vw - 110px); + } + + @keyframes slideInSearchResultsMobile { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } + } + + #MSearchResultsWindow { + left: var(--spacing-medium) !important; + right: var(--spacing-medium); + overflow: auto; + transform: translate(0, 20px); + animation: ease-out 280ms slideInSearchResultsMobile; + width: auto !important; + } + + /* + * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2 + */ + label.main-menu-btn ~ #searchBoxPos1 { + top: 3px !important; + right: 6px !important; + left: 45px; + display: flex; + } + + label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox { + margin-top: 0; + margin-bottom: 0; + flex-grow: 2; + float: left; + } +} + +/* + Tree view + */ + +#side-nav { + padding: 0 !important; + background: var(--side-nav-background); +} + +@media screen and (max-width: 767px) { + #side-nav { + display: none; + } + + #doc-content { + margin-left: 0 !important; + } +} + +#nav-tree { + background: transparent; +} + +#nav-tree .label { + font-size: var(--navigation-font-size); +} + +#nav-tree .item { + height: var(--tree-item-height); + line-height: var(--tree-item-height); +} + +#nav-sync { + bottom: 12px; + right: 12px; + top: auto !important; + user-select: none; +} + +#nav-tree .selected { + text-shadow: none; + background-image: none; + background-color: transparent; + position: relative; +} + +#nav-tree .selected::after { + content: ""; + position: absolute; + top: 1px; + bottom: 1px; + left: 0; + width: 4px; + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + background: var(--primary-color); +} + + +#nav-tree a { + color: var(--side-nav-foreground) !important; + font-weight: normal; +} + +#nav-tree a:focus { + outline-style: auto; +} + +#nav-tree .arrow { + opacity: var(--side-nav-arrow-opacity); +} + +.arrow { + color: inherit; + cursor: pointer; + font-size: 45%; + vertical-align: middle; + margin-right: 2px; + font-family: serif; + height: auto; + text-align: right; +} + +#nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow { + opacity: var(--side-nav-arrow-hover-opacity); +} + +#nav-tree .selected a { + color: var(--primary-color) !important; + font-weight: bolder; + font-weight: 600; +} + +.ui-resizable-e { + background: var(--separator-color); + width: 1px; +} + +/* + Contents + */ + +div.header { + border-bottom: 1px solid var(--separator-color); + background-color: var(--page-background-color); + background-image: none; +} + +@media screen and (min-width: 1000px) { + #doc-content > div > div.contents, + .PageDoc > div.contents { + display: flex; + flex-direction: row-reverse; + flex-wrap: nowrap; + align-items: flex-start; + } + + div.contents .textblock { + min-width: 200px; + flex-grow: 1; + } +} + +div.contents, div.header .title, div.header .summary { + max-width: var(--content-maxwidth); +} + +div.contents, div.header .title { + line-height: initial; + margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto; +} + +div.header .summary { + margin: var(--spacing-medium) auto 0 auto; +} + +div.headertitle { + padding: 0; +} + +div.header .title { + font-weight: 600; + font-size: 225%; + padding: var(--spacing-medium) var(--spacing-large); + word-break: break-word; +} + +div.header .summary { + width: auto; + display: block; + float: none; + padding: 0 var(--spacing-large); +} + +td.memSeparator { + border-color: var(--separator-color); +} + +span.mlabel { + background: var(--primary-color); + border: none; + padding: 4px 9px; + border-radius: 12px; + margin-right: var(--spacing-medium); +} + +span.mlabel:last-of-type { + margin-right: 2px; +} + +div.contents { + padding: 0 var(--spacing-large); +} + +div.contents p, div.contents li { + line-height: var(--content-line-height); +} + +div.contents div.dyncontent { + margin: var(--spacing-medium) 0; +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) div.contents div.dyncontent img, + html:not(.light-mode) div.contents center img, + html:not(.light-mode) div.contents > table img, + html:not(.light-mode) div.contents div.dyncontent iframe, + html:not(.light-mode) div.contents center iframe, + html:not(.light-mode) div.contents table iframe { + filter: hue-rotate(180deg) invert(); + } +} + +html.dark-mode div.contents div.dyncontent img, +html.dark-mode div.contents center img, +html.dark-mode div.contents > table img, +html.dark-mode div.contents div.dyncontent iframe, +html.dark-mode div.contents center iframe, +html.dark-mode div.contents table iframe { + filter: hue-rotate(180deg) invert(); +} + +h2.groupheader { + border-bottom: 0px; + color: var(--page-foreground-color); + box-shadow: + 100px 0 var(--page-background-color), + -100px 0 var(--page-background-color), + 100px 0.75px var(--separator-color), + -100px 0.75px var(--separator-color), + 500px 0 var(--page-background-color), + -500px 0 var(--page-background-color), + 500px 0.75px var(--separator-color), + -500px 0.75px var(--separator-color), + 900px 0 var(--page-background-color), + -900px 0 var(--page-background-color), + 900px 0.75px var(--separator-color), + -900px 0.75px var(--separator-color), + 1400px 0 var(--page-background-color), + -1400px 0 var(--page-background-color), + 1400px 0.75px var(--separator-color), + -1400px 0.75px var(--separator-color), + 1900px 0 var(--page-background-color), + -1900px 0 var(--page-background-color), + 1900px 0.75px var(--separator-color), + -1900px 0.75px var(--separator-color); +} + +blockquote { + margin: 0 var(--spacing-medium) 0 var(--spacing-medium); + padding: var(--spacing-small) var(--spacing-large); + background: var(--blockquote-background); + color: var(--blockquote-foreground); + border-left: 0; + overflow: visible; + border-radius: var(--border-radius-medium); + overflow: visible; + position: relative; +} + +blockquote::before, blockquote::after { + font-weight: bold; + font-family: serif; + font-size: 360%; + opacity: .15; + position: absolute; +} + +blockquote::before { + content: "“"; + left: -10px; + top: 4px; +} + +blockquote::after { + content: "”"; + right: -8px; + bottom: -25px; +} + +blockquote p { + margin: var(--spacing-small) 0 var(--spacing-medium) 0; +} +.paramname { + font-weight: 600; + color: var(--primary-dark-color); +} + +.paramname > code { + border: 0; +} + +table.params .paramname { + font-weight: 600; + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + padding-right: var(--spacing-small); + line-height: var(--table-line-height); +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px var(--primary-light-color); +} + +.alphachar a { + color: var(--page-foreground-color); +} + +/* + Table of Contents + */ + +div.contents .toc { + max-height: var(--toc-max-height); + min-width: var(--toc-width); + border: 0; + border-left: 1px solid var(--separator-color); + border-radius: 0; + background-color: transparent; + box-shadow: none; + position: sticky; + top: var(--toc-sticky-top); + padding: 0 var(--spacing-large); + margin: var(--spacing-small) 0 var(--spacing-large) var(--spacing-large); +} + +div.toc h3 { + color: var(--toc-foreground); + font-size: var(--navigation-font-size); + margin: var(--spacing-large) 0 var(--spacing-medium) 0; +} + +div.toc li { + padding: 0; + background: none; + line-height: var(--toc-font-size); + margin: var(--toc-font-size) 0 0 0; +} + +div.toc li::before { + display: none; +} + +div.toc ul { + margin-top: 0 +} + +div.toc li a { + font-size: var(--toc-font-size); + color: var(--page-foreground-color) !important; + text-decoration: none; +} + +div.toc li a:hover, div.toc li a.active { + color: var(--primary-color) !important; +} + +div.toc li a.aboveActive { + color: var(--page-secondary-foreground-color) !important; +} + + +@media screen and (max-width: 999px) { + div.contents .toc { + max-height: 45vh; + float: none; + width: auto; + margin: 0 0 var(--spacing-medium) 0; + position: relative; + top: 0; + position: relative; + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + background-color: var(--toc-background); + box-shadow: var(--box-shadow); + } + + div.contents .toc.interactive { + max-height: calc(var(--navigation-font-size) + 2 * var(--spacing-large)); + overflow: hidden; + } + + div.contents .toc > h3 { + -webkit-tap-highlight-color: transparent; + cursor: pointer; + position: sticky; + top: 0; + background-color: var(--toc-background); + margin: 0; + padding: var(--spacing-large) 0; + display: block; + } + + div.contents .toc.interactive > h3::before { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + display: inline-block; + margin-right: var(--spacing-small); + margin-bottom: calc(var(--navigation-font-size) / 4); + transform: rotate(-90deg); + transition: transform 0.25s ease-out; + } + + div.contents .toc.interactive.open > h3::before { + transform: rotate(0deg); + } + + div.contents .toc.interactive.open { + max-height: 45vh; + overflow: auto; + transition: max-height 0.2s ease-in-out; + } + + div.contents .toc a, div.contents .toc a.active { + color: var(--primary-color) !important; + } + + div.contents .toc a:hover { + text-decoration: underline; + } +} + +/* + Code & Fragments + */ + +code, div.fragment, pre.fragment { + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + overflow: hidden; +} + +code { + display: inline; + background: var(--code-background); + color: var(--code-foreground); + padding: 2px 6px; +} + +div.fragment, pre.fragment { + margin: var(--spacing-medium) 0; + padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large); + background: var(--fragment-background); + color: var(--fragment-foreground); + overflow-x: auto; +} + +@media screen and (max-width: 767px) { + div.fragment, pre.fragment { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right: 0; + } + + .contents > div.fragment, + .textblock > div.fragment, + .textblock > pre.fragment, + .contents > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .doxygen-awesome-fragment-wrapper > div.fragment, + .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + border-radius: 0; + border-left: 0; + } + + .textblock li > .fragment, + .textblock li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + } + + .memdoc li > .fragment, + .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + } + + .textblock ul, .memdoc ul { + overflow: initial; + } + + .memdoc > div.fragment, + .memdoc > pre.fragment, + dl dd > div.fragment, + dl dd pre.fragment, + .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment, + .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment, + dl dd > .doxygen-awesome-fragment-wrapper > div.fragment, + dl dd .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + border-radius: 0; + border-left: 0; + } +} + +code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size) !important; +} + +div.line:after { + margin-right: var(--spacing-medium); +} + +div.fragment .line, pre.fragment { + white-space: pre; + word-wrap: initial; + line-height: var(--fragment-lineheight); +} + +div.fragment span.keyword { + color: var(--fragment-keyword); +} + +div.fragment span.keywordtype { + color: var(--fragment-keywordtype); +} + +div.fragment span.keywordflow { + color: var(--fragment-keywordflow); +} + +div.fragment span.stringliteral { + color: var(--fragment-token) +} + +div.fragment span.comment { + color: var(--fragment-comment); +} + +div.fragment a.code { + color: var(--fragment-link) !important; +} + +div.fragment span.preprocessor { + color: var(--fragment-preprocessor); +} + +div.fragment span.lineno { + display: inline-block; + width: 27px; + border-right: none; + background: var(--fragment-linenumber-background); + color: var(--fragment-linenumber-color); +} + +div.fragment span.lineno a { + background: none; + color: var(--fragment-link) !important; +} + +div.fragment .line:first-child .lineno { + box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border); +} + +div.line { + border-radius: var(--border-radius-small); +} + +div.line.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +/* + dl warning, attention, note, deprecated, bug, ... + */ + +dl.bug dt a, dl.deprecated dt a, dl.todo dt a { + font-weight: bold !important; +} + +dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.todo, dl.remark { + padding: var(--spacing-medium); + margin: var(--spacing-medium) 0; + color: var(--page-background-color); + overflow: hidden; + margin-left: 0; + border-radius: var(--border-radius-small); +} + +dl.section dd { + margin-bottom: 2px; +} + +dl.warning, dl.attention { + background: var(--warning-color); + border-left: 8px solid var(--warning-color-dark); + color: var(--warning-color-darker); +} + +dl.warning dt, dl.attention dt { + color: var(--warning-color-dark); +} + +dl.note, dl.remark { + background: var(--note-color); + border-left: 8px solid var(--note-color-dark); + color: var(--note-color-darker); +} + +dl.note dt, dl.remark dt { + color: var(--note-color-dark); +} + +dl.todo { + background: var(--todo-color); + border-left: 8px solid var(--todo-color-dark); + color: var(--todo-color-darker); +} + +dl.todo dt { + color: var(--todo-color-dark); +} + +dl.bug dt a { + color: var(--todo-color-dark) !important; +} + +dl.bug { + background: var(--bug-color); + border-left: 8px solid var(--bug-color-dark); + color: var(--bug-color-darker); +} + +dl.bug dt a { + color: var(--bug-color-dark) !important; +} + +dl.deprecated { + background: var(--deprecated-color); + border-left: 8px solid var(--deprecated-color-dark); + color: var(--deprecated-color-darker); +} + +dl.deprecated dt a { + color: var(--deprecated-color-dark) !important; +} + +dl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd { + margin-inline-start: 0px; +} + +dl.invariant, dl.pre { + background: var(--invariant-color); + border-left: 8px solid var(--invariant-color-dark); + color: var(--invariant-color-darker); +} + +dl.invariant dt, dl.pre dt { + color: var(--invariant-color-dark); +} + +/* + memitem + */ + +div.memdoc, div.memproto, h2.memtitle { + box-shadow: none; + background-image: none; + border: none; +} + +div.memdoc { + padding: 0 var(--spacing-medium); + background: var(--page-background-color); +} + +h2.memtitle, div.memitem { + border: 1px solid var(--separator-color); + box-shadow: var(--box-shadow); +} + +h2.memtitle { + box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow); +} + +div.memitem { + transition: none; +} + +div.memproto, h2.memtitle { + background: var(--fragment-background); +} + +h2.memtitle { + font-weight: 500; + font-size: var(--memtitle-font-size); + font-family: var(--font-family-monospace); + border-bottom: none; + border-top-left-radius: var(--border-radius-medium); + border-top-right-radius: var(--border-radius-medium); + word-break: break-all; + position: relative; +} + +h2.memtitle:after { + content: ""; + display: block; + background: var(--fragment-background); + height: var(--spacing-medium); + bottom: calc(0px - var(--spacing-medium)); + left: 0; + right: -14px; + position: absolute; + border-top-right-radius: var(--border-radius-medium); +} + +h2.memtitle > span.permalink { + font-size: inherit; +} + +h2.memtitle > span.permalink > a { + text-decoration: none; + padding-left: 3px; + margin-right: -4px; + user-select: none; + display: inline-block; + margin-top: -6px; +} + +h2.memtitle > span.permalink > a:hover { + color: var(--primary-dark-color) !important; +} + +a:target + h2.memtitle, a:target + h2.memtitle + div.memitem { + border-color: var(--primary-light-color); +} + +div.memitem { + border-top-right-radius: var(--border-radius-medium); + border-bottom-right-radius: var(--border-radius-medium); + border-bottom-left-radius: var(--border-radius-medium); + overflow: hidden; + display: block !important; +} + +div.memdoc { + border-radius: 0; +} + +div.memproto { + border-radius: 0 var(--border-radius-small) 0 0; + overflow: auto; + border-bottom: 1px solid var(--separator-color); + padding: var(--spacing-medium); + margin-bottom: -1px; +} + +div.memtitle { + border-top-right-radius: var(--border-radius-medium); + border-top-left-radius: var(--border-radius-medium); +} + +div.memproto table.memname { + font-family: var(--font-family-monospace); + color: var(--page-foreground-color); + font-size: var(--memname-font-size); + text-shadow: none; +} + +div.memproto div.memtemplate { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--memname-font-size); + margin-left: 2px; + text-shadow: none; +} + +table.mlabels, table.mlabels > tbody { + display: block; +} + +td.mlabels-left { + width: auto; +} + +td.mlabels-right { + margin-top: 3px; + position: sticky; + left: 0; +} + +table.mlabels > tbody > tr:first-child { + display: flex; + justify-content: space-between; + flex-wrap: wrap; +} + +.memname, .memitem span.mlabels { + margin: 0 +} + +/* + reflist + */ + +dl.reflist { + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-medium); + border: 1px solid var(--separator-color); + overflow: hidden; + padding: 0; +} + + +dl.reflist dt, dl.reflist dd { + box-shadow: none; + text-shadow: none; + background-image: none; + border: none; + padding: 12px; +} + + +dl.reflist dt { + font-weight: 500; + border-radius: 0; + background: var(--code-background); + border-bottom: 1px solid var(--separator-color); + color: var(--page-foreground-color) +} + + +dl.reflist dd { + background: none; +} + +/* + Table + */ + +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname), +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: inline-block; + max-width: 100%; +} + +.contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); +} + +table.fieldtable, +table.markdownTable tbody, +table.doxtable tbody { + border: none; + margin: var(--spacing-medium) 0; + box-shadow: 0 0 0 1px var(--separator-color); + border-radius: var(--border-radius-small); +} + +table.doxtable caption { + display: block; +} + +table.fieldtable { + border-collapse: collapse; + width: 100%; +} + +th.markdownTableHeadLeft, +th.markdownTableHeadRight, +th.markdownTableHeadCenter, +th.markdownTableHeadNone, +table.doxtable th { + background: var(--tablehead-background); + color: var(--tablehead-foreground); + font-weight: 600; + font-size: var(--page-font-size); +} + +th.markdownTableHeadLeft:first-child, +th.markdownTableHeadRight:first-child, +th.markdownTableHeadCenter:first-child, +th.markdownTableHeadNone:first-child, +table.doxtable tr th:first-child { + border-top-left-radius: var(--border-radius-small); +} + +th.markdownTableHeadLeft:last-child, +th.markdownTableHeadRight:last-child, +th.markdownTableHeadCenter:last-child, +th.markdownTableHeadNone:last-child, +table.doxtable tr th:last-child { + border-top-right-radius: var(--border-radius-small); +} + +table.markdownTable td, +table.markdownTable th, +table.fieldtable td, +table.fieldtable th, +table.doxtable td, +table.doxtable th { + border: 1px solid var(--separator-color); + padding: var(--spacing-small) var(--spacing-medium); +} + +table.markdownTable td:last-child, +table.markdownTable th:last-child, +table.fieldtable td:last-child, +table.fieldtable th:last-child, +table.doxtable td:last-child, +table.doxtable th:last-child { + border-right: none; +} + +table.markdownTable td:first-child, +table.markdownTable th:first-child, +table.fieldtable td:first-child, +table.fieldtable th:first-child, +table.doxtable td:first-child, +table.doxtable th:first-child { + border-left: none; +} + +table.markdownTable tr:first-child td, +table.markdownTable tr:first-child th, +table.fieldtable tr:first-child td, +table.fieldtable tr:first-child th, +table.doxtable tr:first-child td, +table.doxtable tr:first-child th { + border-top: none; +} + +table.markdownTable tr:last-child td, +table.markdownTable tr:last-child th, +table.fieldtable tr:last-child td, +table.fieldtable tr:last-child th, +table.doxtable tr:last-child td, +table.doxtable tr:last-child th { + border-bottom: none; +} + +table.markdownTable tr, table.doxtable tr { + border-bottom: 1px solid var(--separator-color); +} + +table.markdownTable tr:last-child, table.doxtable tr:last-child { + border-bottom: none; +} + +table.fieldtable th { + font-size: var(--page-font-size); + font-weight: 600; + background-image: none; + background-color: var(--tablehead-background); + color: var(--tablehead-foreground); +} + +table.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fielddoc, .fieldtable th { + border-bottom: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); +} + +table.fieldtable tr:last-child td:first-child { + border-bottom-left-radius: var(--border-radius-small); +} + +table.fieldtable tr:last-child td:last-child { + border-bottom-right-radius: var(--border-radius-small); +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +table.memberdecls { + display: block; + -webkit-tap-highlight-color: transparent; +} + +table.memberdecls tr[class^='memitem'] { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); +} + +table.memberdecls tr[class^='memitem'] .memTemplParams { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + color: var(--primary-dark-color); + white-space: normal; +} + +table.memberdecls .memItemLeft, +table.memberdecls .memItemRight, +table.memberdecls .memTemplItemLeft, +table.memberdecls .memTemplItemRight, +table.memberdecls .memTemplParams { + transition: none; + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + background-color: var(--fragment-background); +} + +table.memberdecls .memTemplItemLeft, +table.memberdecls .memTemplItemRight { + padding-top: 2px; +} + +table.memberdecls .memTemplParams { + border-bottom: 0; + border-left: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + padding-bottom: var(--spacing-small); +} + +table.memberdecls .memTemplItemLeft { + border-radius: 0 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + border-top: 0; +} + +table.memberdecls .memTemplItemRight { + border-radius: 0 0 var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-left: 0; + border-top: 0; +} + +table.memberdecls .memItemLeft { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + padding-left: var(--spacing-medium); + padding-right: 0; +} + +table.memberdecls .memItemRight { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-right: var(--spacing-medium); + padding-left: 0; + +} + +table.memberdecls .mdescLeft, table.memberdecls .mdescRight { + background: none; + color: var(--page-foreground-color); + padding: var(--spacing-small) 0; +} + +table.memberdecls .memItemLeft, +table.memberdecls .memTemplItemLeft { + padding-right: var(--spacing-medium); +} + +table.memberdecls .memSeparator { + background: var(--page-background-color); + height: var(--spacing-large); + border: 0; + transition: none; +} + +table.memberdecls .groupheader { + margin-bottom: var(--spacing-large); +} + +table.memberdecls .inherit_header td { + padding: 0 0 var(--spacing-medium) 0; + text-indent: -12px; + color: var(--page-secondary-foreground-color); +} + +table.memberdecls img[src="closed.png"], +table.memberdecls img[src="open.png"], +div.dynheader img[src="open.png"], +div.dynheader img[src="closed.png"] { + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + margin-top: 8px; + display: block; + float: left; + margin-left: -10px; + transition: transform 0.25s ease-out; +} + +table.memberdecls img { + margin-right: 10px; +} + +table.memberdecls img[src="closed.png"], +div.dynheader img[src="closed.png"] { + transform: rotate(-90deg); + +} + +.compoundTemplParams { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--code-font-size); +} + +@media screen and (max-width: 767px) { + + table.memberdecls .memItemLeft, + table.memberdecls .memItemRight, + table.memberdecls .mdescLeft, + table.memberdecls .mdescRight, + table.memberdecls .memTemplItemLeft, + table.memberdecls .memTemplItemRight, + table.memberdecls .memTemplParams { + display: block; + text-align: left; + padding-left: var(--spacing-large); + margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large)); + border-right: none; + border-left: none; + border-radius: 0; + white-space: normal; + } + + table.memberdecls .memItemLeft, + table.memberdecls .mdescLeft, + table.memberdecls .memTemplItemLeft { + border-bottom: 0; + padding-bottom: 0; + } + + table.memberdecls .memTemplItemLeft { + padding-top: 0; + } + + table.memberdecls .mdescLeft { + margin-bottom: calc(0px - var(--page-font-size)); + } + + table.memberdecls .memItemRight, + table.memberdecls .mdescRight, + table.memberdecls .memTemplItemRight { + border-top: 0; + padding-top: 0; + padding-right: var(--spacing-large); + overflow-x: auto; + } + + table.memberdecls tr[class^='memitem']:not(.inherit) { + display: block; + width: calc(100vw - 2 * var(--spacing-large)); + } + + table.memberdecls .mdescRight { + color: var(--page-foreground-color); + } + + table.memberdecls tr.inherit { + visibility: hidden; + } + + table.memberdecls tr[style="display: table-row;"] { + display: block !important; + visibility: visible; + width: calc(100vw - 2 * var(--spacing-large)); + animation: fade .5s; + } + + @keyframes fade { + 0% { + opacity: 0; + max-height: 0; + } + + 100% { + opacity: 1; + max-height: 200px; + } + } +} + + +/* + Horizontal Rule + */ + +hr { + margin-top: var(--spacing-large); + margin-bottom: var(--spacing-large); + height: 1px; + background-color: var(--separator-color); + border: 0; +} + +.contents hr { + box-shadow: 100px 0 0 var(--separator-color), + -100px 0 0 var(--separator-color), + 500px 0 0 var(--separator-color), + -500px 0 0 var(--separator-color), + 1500px 0 0 var(--separator-color), + -1500px 0 0 var(--separator-color), + 2000px 0 0 var(--separator-color), + -2000px 0 0 var(--separator-color); +} + +.contents img, .contents .center, .contents center, .contents div.image object { + max-width: 100%; + overflow: auto; +} + +@media screen and (max-width: 767px) { + .contents .dyncontent > .center, .contents > center { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); + } +} + +/* + Directories + */ +div.directory { + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + width: auto; +} + +table.directory { + font-family: var(--font-family); + font-size: var(--page-font-size); + font-weight: normal; + width: 100%; +} + +table.directory td.entry, table.directory td.desc { + padding: calc(var(--spacing-small) / 2) var(--spacing-small); + line-height: var(--table-line-height); +} + +table.directory tr.even td:last-child { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; +} + +table.directory tr.even td:first-child { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); +} + +table.directory tr.even:last-child td:last-child { + border-radius: 0 var(--border-radius-small) 0 0; +} + +table.directory tr.even:last-child td:first-child { + border-radius: var(--border-radius-small) 0 0 0; +} + +table.directory td.desc { + min-width: 250px; +} + +table.directory tr.even { + background-color: var(--odd-color); +} + +table.directory tr.odd { + background-color: transparent; +} + +.icona { + width: auto; + height: auto; + margin: 0 var(--spacing-small); +} + +.icon { + background: var(--primary-color); + border-radius: var(--border-radius-small); + font-size: var(--page-font-size); + padding: calc(var(--page-font-size) / 5); + line-height: var(--page-font-size); + transform: scale(0.8); + height: auto; + width: var(--page-font-size); + user-select: none; +} + +.iconfopen, .icondoc, .iconfclosed { + background-position: center; + margin-bottom: 0; + height: var(--table-line-height); +} + +.icondoc { + filter: saturate(0.2); +} + +@media screen and (max-width: 767px) { + div.directory { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + } +} + +@media (prefers-color-scheme: dark) { + html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed { + filter: hue-rotate(180deg) invert(); + } +} + +html.dark-mode .iconfopen, html.dark-mode .iconfclosed { + filter: hue-rotate(180deg) invert(); +} + +/* + Class list + */ + +.classindex dl.odd { + background: var(--odd-color); + border-radius: var(--border-radius-small); +} + +.classindex dl.even { + background-color: transparent; +} + +/* + Class Index Doxygen 1.8 +*/ + +table.classindex { + margin-left: 0; + margin-right: 0; + width: 100%; +} + +table.classindex table div.ah { + background-image: none; + background-color: initial; + border-color: var(--separator-color); + color: var(--page-foreground-color); + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-large); + padding: var(--spacing-small); +} + +div.qindex { + background-color: var(--odd-color); + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + padding: var(--spacing-small) 0; +} + +/* + Footer and nav-path + */ + +#nav-path { + width: 100%; +} + +#nav-path ul { + background-image: none; + background: var(--page-background-color); + border: none; + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + border-bottom: 0; + box-shadow: 0 0.75px 0 var(--separator-color); + font-size: var(--navigation-font-size); +} + +img.footer { + width: 60px; +} + +.navpath li.footer { + color: var(--page-secondary-foreground-color); +} + +address.footer { + color: var(--page-secondary-foreground-color); + margin-bottom: var(--spacing-large); +} + +#nav-path li.navelem { + background-image: none; + display: flex; + align-items: center; +} + +.navpath li.navelem a { + text-shadow: none; + display: inline-block; + color: var(--primary-color) !important; +} + +.navpath li.navelem b { + color: var(--primary-dark-color); + font-weight: 500; +} + +li.navelem { + padding: 0; + margin-left: -8px; +} + +li.navelem:first-child { + margin-left: var(--spacing-large); +} + +li.navelem:first-child:before { + display: none; +} + +#nav-path li.navelem:after { + content: ''; + border: 5px solid var(--page-background-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(4.2); + z-index: 10; + margin-left: 6px; +} + +#nav-path li.navelem:before { + content: ''; + border: 5px solid var(--separator-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(3.2); + margin-right: var(--spacing-small); +} + +.navpath li.navelem a:hover { + color: var(--primary-color); +} + +/* + Scrollbars for Webkit +*/ + +#nav-tree::-webkit-scrollbar, +div.fragment::-webkit-scrollbar, +pre.fragment::-webkit-scrollbar, +div.memproto::-webkit-scrollbar, +.contents center::-webkit-scrollbar, +.contents .center::-webkit-scrollbar, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar, +div.contents .toc::-webkit-scrollbar { + background: transparent; + width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); +} + +#nav-tree::-webkit-scrollbar-thumb, +div.fragment::-webkit-scrollbar-thumb, +pre.fragment::-webkit-scrollbar-thumb, +div.memproto::-webkit-scrollbar-thumb, +.contents center::-webkit-scrollbar-thumb, +.contents .center::-webkit-scrollbar-thumb, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb, +div.contents .toc::-webkit-scrollbar-thumb { + background-color: transparent; + border: var(--webkit-scrollbar-padding) solid transparent; + border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + background-clip: padding-box; +} + +#nav-tree:hover::-webkit-scrollbar-thumb, +div.fragment:hover::-webkit-scrollbar-thumb, +pre.fragment:hover::-webkit-scrollbar-thumb, +div.memproto:hover::-webkit-scrollbar-thumb, +.contents center:hover::-webkit-scrollbar-thumb, +.contents .center:hover::-webkit-scrollbar-thumb, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb, +div.contents .toc:hover::-webkit-scrollbar-thumb { + background-color: var(--webkit-scrollbar-color); +} + +#nav-tree::-webkit-scrollbar-track, +div.fragment::-webkit-scrollbar-track, +pre.fragment::-webkit-scrollbar-track, +div.memproto::-webkit-scrollbar-track, +.contents center::-webkit-scrollbar-track, +.contents .center::-webkit-scrollbar-track, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track, +div.contents .toc::-webkit-scrollbar-track { + background: transparent; +} + +#nav-tree::-webkit-scrollbar-corner { + background-color: var(--side-nav-background); +} + +#nav-tree, +div.fragment, +pre.fragment, +div.memproto, +.contents center, +.contents .center, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +div.contents .toc { + overflow-x: auto; + overflow-x: overlay; +} + +#nav-tree { + overflow-x: auto; + overflow-y: auto; + overflow-y: overlay; +} + +/* + Scrollbars for Firefox +*/ + +#nav-tree, +div.fragment, +pre.fragment, +div.memproto, +.contents center, +.contents .center, +.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +div.contents .toc { + scrollbar-width: thin; +} + +/* + Optional Dark mode toggle button +*/ + +doxygen-awesome-dark-mode-toggle { + display: inline-block; + margin: 0 0 0 var(--spacing-small); + padding: 0; + width: var(--searchbar-height); + height: var(--searchbar-height); + background: none; + border: none; + border-radius: var(--searchbar-height); + vertical-align: middle; + text-align: center; + line-height: var(--searchbar-height); + font-size: 22px; + display: flex; + align-items: center; + justify-content: center; + user-select: none; + cursor: pointer; +} + +doxygen-awesome-dark-mode-toggle > svg { + transition: transform .1s ease-in-out; +} + +doxygen-awesome-dark-mode-toggle:active > svg { + transform: scale(.5); +} + +doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.03); +} + +html.dark-mode doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.18); +} + +/* + Optional fragment copy button +*/ +.doxygen-awesome-fragment-wrapper { + position: relative; +} + +doxygen-awesome-fragment-copy-button { + opacity: 0; + background: var(--fragment-background); + width: 28px; + height: 28px; + position: absolute; + right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + border: 1px solid var(--fragment-foreground); + cursor: pointer; + border-radius: var(--border-radius-small); + display: flex; + justify-content: center; + align-items: center; +} + +.doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, doxygen-awesome-fragment-copy-button.success { + opacity: .28; +} + +doxygen-awesome-fragment-copy-button:hover, doxygen-awesome-fragment-copy-button.success { + opacity: 1 !important; +} + +doxygen-awesome-fragment-copy-button:active:not([class~=success]) svg { + transform: scale(.91); +} + +doxygen-awesome-fragment-copy-button svg { + fill: var(--fragment-foreground); + width: 18px; + height: 18px; +} + +doxygen-awesome-fragment-copy-button.success svg { + fill: rgb(14, 168, 14); +} + +doxygen-awesome-fragment-copy-button.success { + border-color: rgb(14, 168, 14); +} + +@media screen and (max-width: 767px) { + .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button { + right: 0; + } +} + +/* + Optional paragraph link button +*/ + +a.anchorlink { + font-size: 90%; + margin-left: var(--spacing-small); + color: var(--page-foreground-color) !important; + text-decoration: none; + opacity: .15; + display: none; + transition: opacity .1s ease-in-out, color .1s ease-in-out; +} + +a.anchorlink svg { + fill: var(--page-foreground-color); +} + +h3 a.anchorlink svg, h4 a.anchorlink svg { + margin-bottom: -3px; + margin-top: -4px; +} + +a.anchorlink:hover { + opacity: .45; +} + +h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink { + display: inline-block; +} + + +#MSearchBox .left { + background: none !important; +} +#MSearchBox .right { + background: none !important; +} From a89995b63f7598820e47c781f17541ab193a14f7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Jan 2023 12:36:53 +0100 Subject: [PATCH 370/816] WIP Public virtual card --- htdocs/core/lib/functions.lib.php | 12 ++++++++---- htdocs/langs/en_US/main.lang | 3 ++- htdocs/main.inc.php | 20 ++++++++++++++------ htdocs/projet/card.php | 2 +- htdocs/public/users/view.php | 6 +++--- htdocs/user/card.php | 4 +--- htdocs/user/virtualcard.php | 1 + 7 files changed, 30 insertions(+), 18 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index ac774209d30..e32cbc3ca9d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1731,11 +1731,13 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = * @param string $url Relative Url to open. For example '/project/card.php' * @param string $disabled Disabled text * @param string $morecss More CSS + * @param string $jsonopen Some JS code to execute on click/open of popup * @param string $backtopagejsfields The back to page must be managed using javascript instead of a redirect. * Value is 'keyforpopupid:Name_of_html_component_to_set_with id,Name_of_html_component_to_set_with_label' + * @param string $accesskey A key to use shortcut * @return string HTML component with button */ -function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '', $morecss = 'classlink button bordertransp', $backtopagejsfields = '') +function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '', $morecss = 'classlink button bordertransp', $jsonopen = '', $backtopagejsfields = '', $accesskey = '') { global $conf; @@ -1763,9 +1765,11 @@ function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $di //print ''; $out .= ''; - $out .= 'use_javascript_ajax)) { $out .= ' href="'.DOL_URL_ROOT.$url.'" target="_blank"'; + } elseif ($jsonopen) { + $out .= ' onclick="javascript:'.$jsonopen.'"'; } $out .= '>'.$buttonstring.''; @@ -2324,7 +2328,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi // Add alias for thirdparty if (!empty($object->name_alias)) { - $morehtmlref .= '
'.$object->name_alias.'
'; + $morehtmlref .= '
'.dol_escape_htmltag($object->name_alias).'
'; } // Add label @@ -2346,7 +2350,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi if (!empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && ($conf->global->MAIN_SHOW_TECHNICAL_ID == '1' || preg_match('/'.preg_quote($object->element, '/').'/i', $conf->global->MAIN_SHOW_TECHNICAL_ID)) && !empty($object->id)) { $morehtmlref .= '
'; $morehtmlref .= '
'; - $morehtmlref .= $langs->trans("TechnicalID").': '.$object->id; + $morehtmlref .= $langs->trans("TechnicalID").': '.((int) $object->id); $morehtmlref .= '
'; } diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index e747f004c87..daa01cfcfa4 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -226,6 +226,7 @@ NoUserGroupDefined=No user group defined Password=Password PasswordRetype=Repeat your password NoteSomeFeaturesAreDisabled=Note that a lot of features/modules are disabled in this demonstration. +YourUserFile=Your user file Name=Name NameSlashCompany=Name / Company Person=Person @@ -1213,4 +1214,4 @@ InternalUser=Internal user ExternalUser=External user NoSpecificContactAddress=No specific contact or address NoSpecificContactAddressBis=This tab is dedicated to force specific contacts or addresses for the current object. Use it only if you want to define one or several specific contacts or addresses for the object when the information on the thirdparty is not enough or not accurate. - +AddToContacts=Add address to my contacts diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 17912f81101..a21082a8bc6 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2280,12 +2280,14 @@ function top_menu_user($hideloginname = 0, $urllogout = '') if (empty($urllogout)) { $urllogout = DOL_URL_ROOT.'/user/logout.php?token='.newToken(); } - $logoutLink = ' '.$langs->trans("Logout").''; - $profilLink = ' '.$langs->trans("Card").''; + // Defined the links for bottom of card + $profilLink = ' '.$langs->trans("Card").''; + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $user->id); + $virtuelcardLink = dolButtonToOpenUrlInDialogPopup('publicvirtualcardmenu', $langs->trans("PublicVirtualCardUrl"), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', ''), $urltovirtualcard, '', 'button-top-menu-dropdown marginleftonly nohover', "closeTopMenuLoginDropdown()", '', 'v'); + $logoutLink = ' '.$langs->trans("Logout").''; $profilName = $user->getFullName($langs).' ('.$user->login.')'; - if (!empty($user->admin)) { $profilName = ' '.$profilName; } @@ -2341,6 +2343,9 @@ function top_menu_user($hideloginname = 0, $urllogout = '')
'.$profilLink.'
+
+ '.$virtuelcardLink.' +
'.$logoutLink.'
@@ -2363,12 +2368,15 @@ function top_menu_user($hideloginname = 0, $urllogout = '') $btnUser .= ' '; + + if ($type == 'sub') { + $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly')); + $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); + } else { + $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); + $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly')); + } + $newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create'); + } + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); + } + if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); } - print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $button, $result, $nbtotalofrecords, 'title_accountancy', 0, '', '', $limit); + print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $result, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1); $selectedfields = ''; @@ -275,18 +341,38 @@ if ($action != 'export_csv') { $moreforfilter .= $form->selectDate($search_date_start ? $search_date_start : -1, 'date_start', 0, 0, 1, '', 1, 0); $moreforfilter .= $langs->trans('DateEnd').': '; $moreforfilter .= $form->selectDate($search_date_end ? $search_date_end : -1, 'date_end', 0, 0, 1, '', 1, 0); - - $moreforfilter .= ' - '; - $moreforfilter .= ': '; - $moreforfilter .= ''; - $moreforfilter .= '
'; $moreforfilter .= '
'; + $moreforfilter .= ': '; + $moreforfilter .= ''; + $moreforfilter .= '
'; - $moreforfilter .= $langs->trans("Journal"); + $moreforfilter .= '
'; + $moreforfilter .= $langs->trans("Journals").': '; $moreforfilter .= $formaccounting->multi_select_journal($search_ledger_code, 'search_ledger_code', 0, 1, 1, 1); + $moreforfilter .= '
'; + $moreforfilter .= '
'; + $moreforfilter .= '
'; + // Accountancy account + $moreforfilter .= $langs->trans('AccountAccounting').': '; + if ($type == 'sub') { + $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), 'maxwidth200'); + } else { + $moreforfilter .= $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200', 'accounts'); + } + $moreforfilter .= ' '; + if ($type == 'sub') { + $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), 'maxwidth200'); + } else { + $moreforfilter .= $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200', 'accounts'); + } + $moreforfilter .= '
'; + + $moreforfilter .= '
'; + $moreforfilter .= ': '; + $moreforfilter .= ''; $moreforfilter .= '
'; if (!empty($moreforfilter)) { @@ -305,9 +391,6 @@ if ($action != 'export_csv') { print ''; print ''; - print $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, '', 'accounts'); - print ' '; - print $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, '', 'accounts'); print ''; // Fields from hook @@ -324,6 +407,10 @@ if ($action != 'export_csv') { print ''; print_liste_field_titre("AccountAccounting", $_SERVER['PHP_SELF'], "t.numero_compte", "", $param, "", $sortfield, $sortorder); + // TODO : Retrieve the type of third party: Customer / Supplier / Employee + //if ($type == 'sub') { + // print_liste_field_titre("Type", $_SERVER['PHP_SELF'], "t.type", "", $param, "", $sortfield, $sortorder); + //} if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) { print_liste_field_titre("OpeningBalance", $_SERVER['PHP_SELF'], "", $param, "", 'class="right"', $sortfield, $sortorder); } @@ -359,7 +446,7 @@ if ($action != 'export_csv') { $sql .= " GROUP BY t.numero_compte"; $resql = $db->query($sql); - $nrows = $db->num_rows($resql); + $nrows = $resql->num_rows; $opening_balances = array(); for ($i = 0; $i < $nrows; $i++) { $arr = $resql->fetch_array(); @@ -372,11 +459,13 @@ if ($action != 'export_csv') { $accountingaccountstatic->id = 0; $accountingaccountstatic->account_number = ''; - $accountingaccountstatic->fetch(null, $line->numero_compte, true); - if (!empty($accountingaccountstatic->account_number)) { - $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 0, '', 0, -1, 0, 'accountcard'); - } else { - $accounting_account = length_accountg($line->numero_compte); + if ($type != 'sub') { + $accountingaccountstatic->fetch(null, $line->numero_compte, true); + if (!empty($accountingaccountstatic->account_number)) { + $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 0, '', 0, -1, 0, 'ledger'); + } else { + $accounting_account = length_accountg($line->numero_compte); + } } $link = ''; @@ -427,7 +516,7 @@ if ($action != 'export_csv') { // Show first line of a break print ''; - print ''.$line->numero_compte.($root_account_description ? ' - '.$root_account_description : '').''; + print ''.$line->numero_compte.($root_account_description ? ' - '.$root_account_description : '').''; print ''; $displayed_account = $root_account_number; @@ -438,19 +527,43 @@ if ($action != 'export_csv') { } print ''; - print ''.$accounting_account.''; + // Accounting account + if ($type == 'sub') { + print ''.$line->subledger_account.' ('.$line->subledger_label.')'; + } else { + print ''.$accounting_account.''; + } + + // Type + // TODO Retrieve the type of third party: Customer / Supplier / Employee + //if ($type == 'sub') { + // print ''; + //} + if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) { print ''.price(price2num($opening_balance, 'MT')).''; } $urlzoom = ''; - if ($line->numero_compte) { - $urlzoom = DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start='.urlencode($line->numero_compte).'&search_accountancy_code_end='.urlencode($line->numero_compte); - if (GETPOSTISSET('date_startmonth')) { - $urlzoom .= '&search_date_startmonth='.GETPOST('date_startmonth', 'int').'&search_date_startday='.GETPOST('date_startday', 'int').'&search_date_startyear='.GETPOST('date_startyear', 'int'); + if ($type == 'sub') { + if ($line->subledger_account) { + $urlzoom = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&search_accountancy_code_start=' . urlencode($line->subledger_account) . '&search_accountancy_code_end=' . urlencode($line->subledger_account); + if (GETPOSTISSET('date_startmonth')) { + $urlzoom .= '&search_date_startmonth=' . GETPOST('date_startmonth', 'int') . '&search_date_startday=' . GETPOST('date_startday', 'int') . '&search_date_startyear=' . GETPOST('date_startyear', 'int'); + } + if (GETPOSTISSET('date_endmonth')) { + $urlzoom .= '&search_date_endmonth=' . GETPOST('date_endmonth', 'int') . '&search_date_endday=' . GETPOST('date_endday', 'int') . '&search_date_endyear=' . GETPOST('date_endyear', 'int'); + } } - if (GETPOSTISSET('date_endmonth')) { - $urlzoom .= '&search_date_endmonth='.GETPOST('date_endmonth', 'int').'&search_date_endday='.GETPOST('date_endday', 'int').'&search_date_endyear='.GETPOST('date_endyear', 'int'); + } else { + if ($line->numero_compte) { + $urlzoom = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start=' . urlencode($line->numero_compte) . '&search_accountancy_code_end=' . urlencode($line->numero_compte); + if (GETPOSTISSET('date_startmonth')) { + $urlzoom .= '&search_date_startmonth=' . GETPOST('date_startmonth', 'int') . '&search_date_startday=' . GETPOST('date_startday', 'int') . '&search_date_startyear=' . GETPOST('date_startyear', 'int'); + } + if (GETPOSTISSET('date_endmonth')) { + $urlzoom .= '&search_date_endmonth=' . GETPOST('date_endmonth', 'int') . '&search_date_endday=' . GETPOST('date_endday', 'int') . '&search_date_endyear=' . GETPOST('date_endyear', 'int'); + } } } // Debit diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 95ba38d20bb..803e2feb619 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1139,9 +1139,10 @@ class BookKeeping extends CommonObject * @param int $offset offset limit * @param array $filter filter array * @param string $filtermode filter mode (AND or OR) + * @param int $option option (0: general account or 1: subaccount) * @return int <0 if KO, >0 if OK */ - public function fetchAllBalance($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + public function fetchAllBalance($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND', $option = 0) { global $conf; @@ -1151,6 +1152,9 @@ class BookKeeping extends CommonObject $sql = 'SELECT'; $sql .= " t.numero_compte,"; + $sql .= " t.label_compte,"; + $sql .= " t.subledger_account,"; + $sql .= " t.subledger_label,"; $sql .= " SUM(t.debit) as debit,"; $sql .= " SUM(t.credit) as credit"; $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; @@ -1176,6 +1180,8 @@ class BookKeeping extends CommonObject } else { $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); } + } elseif ($key == 't.reconciled_option') { + $sqlwhere[] = 't.lettering_code IS NULL'; } else { $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; } @@ -1186,7 +1192,17 @@ class BookKeeping extends CommonObject $sql .= " AND ".implode(" ".$filtermode." ", $sqlwhere); } - $sql .= ' GROUP BY t.numero_compte'; + if (!empty($option)) { + $sql .= ' AND t.subledger_account IS NOT NULL'; + $sql .= ' AND t.subledger_account != ""'; + $sql .= ' GROUP BY t.subledger_account'; + $sortfield = 't.subledger_account'.($sortfield ? ','.$sortfield : ''); + $sortorder = 'ASC'.($sortfield ? ','.$sortfield : ''); + } else { + $sql .= ' GROUP BY t.numero_compte'; + $sortfield = 't.numero_compte'.($sortfield ? ','.$sortfield : ''); + $sortorder = 'ASC'.($sortorder ? ','.$sortorder : ''); + } if (!empty($sortfield)) { $sql .= $this->db->order($sortfield, $sortorder); @@ -1204,6 +1220,9 @@ class BookKeeping extends CommonObject $line = new BookKeepingLine(); $line->numero_compte = $obj->numero_compte; + $line->label_compte = $obj->label_compte; + $line->subledger_account = $obj->subledger_account; + $line->subledger_label = $obj->subledger_label; $line->debit = $obj->debit; $line->credit = $obj->credit; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index e988764d8ba..19abe47fd0b 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -126,6 +126,7 @@ WriteBookKeeping=Record transactions in accounting Bookkeeping=Ledger BookkeepingSubAccount=Subledger AccountBalance=Account balance +AccountBalanceSubAccount=Sub-accounts balance ObjectsRef=Source object ref CAHTF=Total purchase vendor before tax TotalExpenseReport=Total expense report From a85e1c46946325bfbd57a564cb75a463515fa081 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 10 Jan 2023 08:49:09 +0100 Subject: [PATCH 419/816] Remove link --- htdocs/accountancy/bookkeeping/balance.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/bookkeeping/balance.php b/htdocs/accountancy/bookkeeping/balance.php index 0d26213e52f..1b3973ae0cd 100644 --- a/htdocs/accountancy/bookkeeping/balance.php +++ b/htdocs/accountancy/bookkeeping/balance.php @@ -462,7 +462,7 @@ if ($action != 'export_csv') { if ($type != 'sub') { $accountingaccountstatic->fetch(null, $line->numero_compte, true); if (!empty($accountingaccountstatic->account_number)) { - $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 0, '', 0, -1, 0, 'ledger'); + $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 1); } else { $accounting_account = length_accountg($line->numero_compte); } From 1c3d4f9301b29a107fae617fd279a711fbb4cfad Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 10 Jan 2023 09:09:39 +0100 Subject: [PATCH 420/816] Add warning --- htdocs/accountancy/bookkeeping/balance.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/htdocs/accountancy/bookkeeping/balance.php b/htdocs/accountancy/bookkeeping/balance.php index 1b3973ae0cd..fd8cd8ad688 100644 --- a/htdocs/accountancy/bookkeeping/balance.php +++ b/htdocs/accountancy/bookkeeping/balance.php @@ -334,6 +334,11 @@ if ($action != 'export_csv') { $selectedfields = ''; + // Warning to explain why list of record is not consistent with the other list view (missing a lot of lines) + if ($type == 'sub') { + print info_admin($langs->trans("WarningRecordWithoutSubledgerAreExcluded")); + } + $moreforfilter = ''; $moreforfilter .= '
'; From 81d2c7fa0ee8d1775c2f84960b313b8f343d31fa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 10:21:36 +0100 Subject: [PATCH 421/816] NEW Can bin accounting line for a given month --- htdocs/accountancy/customer/index.php | 15 ++++++++++++--- htdocs/accountancy/expensereport/index.php | 22 +++++++++++++++++++--- htdocs/accountancy/supplier/index.php | 22 +++++++++++++++++++--- htdocs/langs/en_US/accountancy.lang | 1 + 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 393629ae505..46e6832dba2 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -300,7 +300,10 @@ if ($action == 'validatehistory') { $db->rollback(); } else { $db->commit(); - setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, 'mesgs'); + setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, ($notpossible ? 'warnings' : 'mesgs')); + if ($notpossible) { + setEventMessages($langs->trans('DoManualBindingForFailedRecord', $notpossible), null, 'warnings'); + } } } @@ -324,7 +327,7 @@ print '
'; $y = $year_current; -$buttonbind = ''.$langs->trans("ValidateHistory").''; +$buttonbind = ''.img_picto($langs->trans("ValidateHistory"), 'link', 'class="pictofixedwidth fa-color-unset"').$langs->trans("ValidateHistory").''; print_barre_liste(img_picto('', 'unlink', 'class="paddingright fa-color-unset"').$langs->trans("OverviewOfAmountOfLinesNotBound"), '', '', '', '', '', '', -1, '', '', 0, $buttonbind, '', 0, 1, 1); //print load_fiche_titre($langs->trans("OverviewOfAmountOfLinesNotBound"), $buttonbind, ''); @@ -420,6 +423,12 @@ if ($resql) { print ''; print price($row[$i]); + // Add link to make binding + if (!empty(price2num($row[$i]))) { + print ''; + print img_picto($langs->trans("ValidateHistory").' ('.$langs->trans('Month'.str_pad($cursormonth, 2, '0', STR_PAD_LEFT)).' '.$cursoryear.')', 'link', 'class="marginleft2"'); + print ''; + } print ''; } print ''.price($row[14]).''; @@ -558,7 +567,7 @@ print "\n"; print '
'; -if ($conf->global->MAIN_FEATURES_LEVEL > 0) { // This part of code looks strange. Why showing a report that should rely on result of this step ? +if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This part of code looks strange. Why showing a report that should rely on result of this step ? print '
'; print '
'; diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index 5064003c7ff..df226ce115d 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -162,7 +162,10 @@ if ($action == 'validatehistory') { $db->rollback(); } else { $db->commit(); - setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, 'mesgs'); + setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, ($notpossible ? 'warnings' : 'mesgs')); + if ($notpossible) { + setEventMessages($langs->trans('DoManualBindingForFailedRecord', $notpossible), null, 'warnings'); + } } } @@ -185,7 +188,7 @@ print '
'; $y = $year_current; -$buttonbind = ''.$langs->trans("ValidateHistory").''; +$buttonbind = ''.img_picto('', 'link', 'class="paddingright fa-color-unset"').$langs->trans("ValidateHistory").''; print_barre_liste(img_picto('', 'unlink', 'class="paddingright fa-color-unset"').$langs->trans("OverviewOfAmountOfLinesNotBound"), '', '', '', '', '', '', -1, '', '', 0, $buttonbind, '', 0, 1, 1); @@ -269,8 +272,21 @@ if ($resql) { } print ''; for ($i = 2; $i <= 13; $i++) { + $cursormonth = (($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) + $i - 2); + if ($cursormonth > 12) { + $cursormonth -= 12; + } + $cursoryear = ($cursormonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; + $tmp = dol_getdate(dol_get_last_day($cursoryear, $cursormonth, 'gmt'), false, 'gmt'); + print ''; print price($row[$i]); + // Add link to make binding + if (!empty(price2num($row[$i]))) { + print ''; + print img_picto($langs->trans("ValidateHistory").' ('.$langs->trans('Month'.str_pad($cursormonth, 2, '0', STR_PAD_LEFT)).' '.$cursoryear.')', 'link', 'class="marginleft2"'); + print ''; + } print ''; } print ''.price($row[14]).''; @@ -367,7 +383,7 @@ print '
'; -if ($conf->global->MAIN_FEATURES_LEVEL > 0) { // This part of code looks strange. Why showing a report where results depends on next step (so not yet available) ? +if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This part of code looks strange. Why showing a report that should rely on result of this step ? print '
'; print '
'; diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index b214b89734c..b66b791f7b1 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -298,7 +298,10 @@ if ($action == 'validatehistory') { $db->rollback(); } else { $db->commit(); - setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, 'mesgs'); + setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, ($notpossible ? 'warnings' : 'mesgs')); + if ($notpossible) { + setEventMessages($langs->trans('DoManualBindingForFailedRecord', $notpossible), null, 'warnings'); + } } } @@ -320,7 +323,7 @@ print '
'; $y = $year_current; -$buttonbind = ''.$langs->trans("ValidateHistory").''; +$buttonbind = ''.img_picto('', 'link', 'class="paddingright fa-color-unset"').$langs->trans("ValidateHistory").''; print_barre_liste(img_picto('', 'unlink', 'class="paddingright fa-color-unset"').$langs->trans("OverviewOfAmountOfLinesNotBound"), '', '', '', '', '', '', -1, '', '', 0, $buttonbind, '', 0, 1, 1); @@ -408,8 +411,21 @@ if ($resql) { } print ''; for ($i = 2; $i <= 13; $i++) { + $cursormonth = (($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) + $i - 2); + if ($cursormonth > 12) { + $cursormonth -= 12; + } + $cursoryear = ($cursormonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; + $tmp = dol_getdate(dol_get_last_day($cursoryear, $cursormonth, 'gmt'), false, 'gmt'); + print ''; print price($row[$i]); + // Add link to make binding + if (!empty(price2num($row[$i]))) { + print ''; + print img_picto($langs->trans("ValidateHistory").' ('.$langs->trans('Month'.str_pad($cursormonth, 2, '0', STR_PAD_LEFT)).' '.$cursoryear.')', 'link', 'class="marginleft2"'); + print ''; + } print ''; } print ''.price($row[14]).''; @@ -541,7 +557,7 @@ print "\n"; print '
'; -if ($conf->global->MAIN_FEATURES_LEVEL > 0) { // This part of code looks strange. Why showing a report that should rely on result of this step ? +if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This part of code looks strange. Why showing a report that should rely on result of this step ? print '
'; print '
'; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 419b69a3f90..554087ad5c4 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -297,6 +297,7 @@ DescValidateMovements=Any modification or deletion of writing, lettering and del ValidateHistory=Bind Automatically AutomaticBindingDone=Automatic bindings done (%s) - Automatic binding not possible for some record (%s) +DoManualBindingForFailedRecord=You have to do a manual link for the rows not linked %s automatically. ErrorAccountancyCodeIsAlreadyUse=Error, you cannot remove or disable this account of chart of account because it is used MvtNotCorrectlyBalanced=Movement not correctly balanced. Debit = %s & Credit = %s From 765a542e1265493a21996da33021354e665ecbf3 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 10 Jan 2023 10:32:35 +0100 Subject: [PATCH 422/816] kanban mode for list of fournisseur commande --- .../class/fournisseur.commande.class.php | 32 + htdocs/fourn/commande/list.php | 672 +++++++++--------- 2 files changed, 384 insertions(+), 320 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 00ed65e7616..9482ff7f500 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -3544,6 +3544,38 @@ class CommandeFournisseur extends CommonOrder return -1; } } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + //$return .= ''; // Can be image + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + if (property_exists($this, 'socid') || property_exists($this, 'total_tva')) { + $return .='
'.$this->socid.''; + } + if (property_exists($this, 'billed')) { + $return .= '
'.$langs->trans("Billed").' : '.yn($this->billed).''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index 3d458247bcf..96c2f7d6cbf 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -56,6 +56,7 @@ $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'supplierorderlist'; +$mode = GETPOST('mode', 'alpha'); // Search Criteria $search_date_order_startday = GETPOST('search_date_order_startday', 'int'); @@ -576,6 +577,9 @@ if (empty($reshook)) { // Make a redirect to avoid to bill twice if we make a refresh or back $param = ''; + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -998,6 +1002,9 @@ if ($resql) { llxHeader('', $title, $help_url); $param = ''; + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -1184,7 +1191,10 @@ if ($resql) { $url .= '&socid='.((int) $socid); $url .= '&backtopage='.urlencode(DOL_URL_ROOT.'/fourn/commande/list.php?socid='.((int) $socid)); } - $newcardbutton = dolGetButtonTitle($langs->trans('NewSupplierOrderShort'), '', 'fa fa-plus-circle', $url, '', $permissiontoadd); + $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')); + $newcardbutton .= dolGetButtonTitle($langs->trans('NewSupplierOrderShort'), '', 'fa fa-plus-circle', $url, '', $permissiontoadd); // Lines of title fields print '
'; @@ -1198,6 +1208,7 @@ if ($resql) { print ''; print ''; print ''; + print ''; print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'supplier_order', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -1660,344 +1671,365 @@ if ($resql) { $objectstatic->note_private = $obj->note_private; $objectstatic->statut = $obj->fk_statut; - print ''; - // 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->rowid, $arrayofselected)) { - $selected = 1; - } - print ''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } - print ''; - } - // Ref - if (!empty($arrayfields['cf.ref']['checked'])) { - print ''; - // Picto + Ref - print $objectstatic->getNomUrl(1, '', 0, -1, 1); - // Other picto tool - $filename = dol_sanitizeFileName($obj->ref); - $filedir = $conf->fournisseur->commande->dir_output.'/'.dol_sanitizeFileName($obj->ref); - print $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); - - print ''."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Ref Supplier - if (!empty($arrayfields['cf.ref_supplier']['checked'])) { - print ''.dol_escape_htmltag($obj->ref_supplier).''."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Project - if (!empty($arrayfields['cf.fk_projet']['checked'])) { - $projectstatic->id = $obj->project_id; - $projectstatic->ref = $obj->project_ref; - $projectstatic->title = $obj->project_title; - print ''; - if ($obj->project_id > 0) { - print $projectstatic->getNomUrl(1); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Author - $userstatic->id = $obj->fk_user_author; - $userstatic->lastname = $obj->lastname; - $userstatic->firstname = $obj->firstname; - $userstatic->login = $obj->login; - $userstatic->photo = $obj->photo; - $userstatic->email = $obj->user_email; - $userstatic->statut = $obj->user_status; - if (!empty($arrayfields['u.login']['checked'])) { - print ''; - if ($userstatic->id) { - print $userstatic->getNomUrl(1); - } - print ""; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Thirdparty - if (!empty($arrayfields['cf.fk_soc']['checked'])) { - print ''; $thirdpartytmp->id = $obj->socid; $thirdpartytmp->name = $obj->name; $thirdpartytmp->email = $obj->email; $thirdpartytmp->name_alias = $obj->alias; $thirdpartytmp->client = $obj->client; $thirdpartytmp->fournisseur = $obj->fournisseur; - print $thirdpartytmp->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); - print ''."\n"; - if (!$i) { - $totalarray['nbfield']++; + $objectstatic->socid = $thirdpartytmp->getNomUrl('supplier', 0, 0, -1); + // Output Kanban + print $objectstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; } - } - //alias - if (!empty($arrayfields['s.name_alias']['checked'])) { - print ''; - print $obj->alias; - print ''."\n"; - if (!$i) { - $totalarray['nbfield']++; + } else { + print ''; + // 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; } - } - // Town - if (!empty($arrayfields['s.town']['checked'])) { - print ''; - print $obj->town; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Zip - if (!empty($arrayfields['s.zip']['checked'])) { - print ''; - print $obj->zip; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['state.nom']['checked'])) { - print "".$obj->state_name."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['country.code_iso']['checked'])) { - print ''; - $tmparray = getCountry($obj->fk_pays, 'all'); - print $tmparray['label']; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Type ent - if (!empty($arrayfields['typent.code']['checked'])) { - print ''; - if (empty($typenArray)) { - $typenArray = $formcompany->typent_array(1); - } - print $typenArray[$obj->typent_code]; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } + // Ref + if (!empty($arrayfields['cf.ref']['checked'])) { + print ''; - // Order date - if (!empty($arrayfields['cf.date_commande']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_commande), 'day'); - if ($objectstatic->statut != $objectstatic::STATUS_ORDERSENT && $objectstatic->statut != $objectstatic::STATUS_RECEIVED_PARTIALLY) { - if ($objectstatic->hasDelay()) { - print ' '.img_picto($langs->trans("Late").' : '.$objectstatic->showDelay(), "warning"); + // Picto + Ref + print $objectstatic->getNomUrl(1, '', 0, -1, 1); + // Other picto tool + $filename = dol_sanitizeFileName($obj->ref); + $filedir = $conf->fournisseur->commande->dir_output.'/'.dol_sanitizeFileName($obj->ref); + print $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); + + print ''."\n"; + if (!$i) { + $totalarray['nbfield']++; } } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Plannned date of delivery - if (!empty($arrayfields['cf.date_livraison']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_livraison), 'day'); - if ($objectstatic->statut == $objectstatic::STATUS_ORDERSENT || $objectstatic->statut == $objectstatic::STATUS_RECEIVED_PARTIALLY) { - if ($objectstatic->hasDelay()) { - print ' '.img_picto($langs->trans("Late").' : '.$objectstatic->showDelay(), "warning"); + // Ref Supplier + if (!empty($arrayfields['cf.ref_supplier']['checked'])) { + print ''.dol_escape_htmltag($obj->ref_supplier).''."\n"; + if (!$i) { + $totalarray['nbfield']++; } } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount HT - if (!empty($arrayfields['cf.total_ht']['checked'])) { - print ''.price($obj->total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'cf.total_ht'; - } - $totalarray['val']['cf.total_ht'] += $obj->total_ht; - } - // Amount VAT - if (!empty($arrayfields['cf.total_tva']['checked'])) { - print ''.price($obj->total_tva)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'cf.total_tva'; - } - $totalarray['val']['cf.total_tva'] += $obj->total_tva; - } - // Amount TTC - if (!empty($arrayfields['cf.total_ttc']['checked'])) { - print ''.price($obj->total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'cf.total_ttc'; - } - $totalarray['val']['cf.total_ttc'] += $obj->total_ttc; - } - - // Currency - if (!empty($arrayfields['cf.multicurrency_code']['checked'])) { - print ''.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Currency rate - if (!empty($arrayfields['cf.multicurrency_tx']['checked'])) { - print ''; - $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount HT - if (!empty($arrayfields['cf.multicurrency_total_ht']['checked'])) { - print ''.price($obj->multicurrency_total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount VAT - if (!empty($arrayfields['cf.multicurrency_total_tva']['checked'])) { - print ''.price($obj->multicurrency_total_tva)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount TTC - if (!empty($arrayfields['cf.multicurrency_total_ttc']['checked'])) { - print ''.price($obj->multicurrency_total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - // Date creation - if (!empty($arrayfields['cf.date_creation']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['cf.tms']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status - if (!empty($arrayfields['cf.fk_statut']['checked'])) { - print ''.$objectstatic->LibStatut($obj->fk_statut, 5, $obj->billed).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Billed - if (!empty($arrayfields['cf.billed']['checked'])) { - print ''.yn($obj->billed).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // valid date - if (!empty($arrayfields['cf.date_valid']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_valid), 'day'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // approve date - if (!empty($arrayfields['cf.date_approve']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_approve), 'day'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Note public - if (!empty($arrayfields['cf.note_public']['checked'])) { - print ''; - print dol_string_nohtmltag($obj->note_public); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Note private - if (!empty($arrayfields['cf.note_private']['checked'])) { - print ''; - print dol_string_nohtmltag($obj->note_private); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // 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->rowid, $arrayofselected)) { - $selected = 1; + // Project + if (!empty($arrayfields['cf.fk_projet']['checked'])) { + $projectstatic->id = $obj->project_id; + $projectstatic->ref = $obj->project_ref; + $projectstatic->title = $obj->project_title; + print ''; + if ($obj->project_id > 0) { + print $projectstatic->getNomUrl(1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Author + $userstatic->id = $obj->fk_user_author; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->login = $obj->login; + $userstatic->photo = $obj->photo; + $userstatic->email = $obj->user_email; + $userstatic->statut = $obj->user_status; + if (!empty($arrayfields['u.login']['checked'])) { + print ''; + if ($userstatic->id) { + print $userstatic->getNomUrl(1); + } + print ""; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Thirdparty + if (!empty($arrayfields['cf.fk_soc']['checked'])) { + print ''; + $thirdpartytmp->id = $obj->socid; + $thirdpartytmp->name = $obj->name; + $thirdpartytmp->email = $obj->email; + $thirdpartytmp->name_alias = $obj->alias; + $thirdpartytmp->client = $obj->client; + $thirdpartytmp->fournisseur = $obj->fournisseur; + print $thirdpartytmp->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + print ''."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + //alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print $obj->alias; + print ''."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Town + if (!empty($arrayfields['s.town']['checked'])) { + print ''; + print $obj->town; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Zip + if (!empty($arrayfields['s.zip']['checked'])) { + print ''; + print $obj->zip; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['state.nom']['checked'])) { + print "".$obj->state_name."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['country.code_iso']['checked'])) { + print ''; + $tmparray = getCountry($obj->fk_pays, 'all'); + print $tmparray['label']; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Type ent + if (!empty($arrayfields['typent.code']['checked'])) { + print ''; + if (empty($typenArray)) { + $typenArray = $formcompany->typent_array(1); + } + print $typenArray[$obj->typent_code]; + print ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; } - print ''; - } - if (!$i) { - $totalarray['nbfield']++; - } - print "\n"; + // Order date + if (!empty($arrayfields['cf.date_commande']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_commande), 'day'); + if ($objectstatic->statut != $objectstatic::STATUS_ORDERSENT && $objectstatic->statut != $objectstatic::STATUS_RECEIVED_PARTIALLY) { + if ($objectstatic->hasDelay()) { + print ' '.img_picto($langs->trans("Late").' : '.$objectstatic->showDelay(), "warning"); + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Plannned date of delivery + if (!empty($arrayfields['cf.date_livraison']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_livraison), 'day'); + if ($objectstatic->statut == $objectstatic::STATUS_ORDERSENT || $objectstatic->statut == $objectstatic::STATUS_RECEIVED_PARTIALLY) { + if ($objectstatic->hasDelay()) { + print ' '.img_picto($langs->trans("Late").' : '.$objectstatic->showDelay(), "warning"); + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['cf.total_ht']['checked'])) { + print ''.price($obj->total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'cf.total_ht'; + } + $totalarray['val']['cf.total_ht'] += $obj->total_ht; + } + // Amount VAT + if (!empty($arrayfields['cf.total_tva']['checked'])) { + print ''.price($obj->total_tva)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'cf.total_tva'; + } + $totalarray['val']['cf.total_tva'] += $obj->total_tva; + } + // Amount TTC + if (!empty($arrayfields['cf.total_ttc']['checked'])) { + print ''.price($obj->total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'cf.total_ttc'; + } + $totalarray['val']['cf.total_ttc'] += $obj->total_ttc; + } - $total += $obj->total_ht; - $subtotal += $obj->total_ht; + // Currency + if (!empty($arrayfields['cf.multicurrency_code']['checked'])) { + print ''.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Currency rate + if (!empty($arrayfields['cf.multicurrency_tx']['checked'])) { + print ''; + $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['cf.multicurrency_total_ht']['checked'])) { + print ''.price($obj->multicurrency_total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount VAT + if (!empty($arrayfields['cf.multicurrency_total_tva']['checked'])) { + print ''.price($obj->multicurrency_total_tva)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount TTC + if (!empty($arrayfields['cf.multicurrency_total_ttc']['checked'])) { + print ''.price($obj->multicurrency_total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Date creation + if (!empty($arrayfields['cf.date_creation']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['cf.tms']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status + if (!empty($arrayfields['cf.fk_statut']['checked'])) { + print ''.$objectstatic->LibStatut($obj->fk_statut, 5, $obj->billed).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Billed + if (!empty($arrayfields['cf.billed']['checked'])) { + print ''.yn($obj->billed).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // valid date + if (!empty($arrayfields['cf.date_valid']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_valid), 'day'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // approve date + if (!empty($arrayfields['cf.date_approve']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_approve), 'day'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Note public + if (!empty($arrayfields['cf.note_public']['checked'])) { + print ''; + print dol_string_nohtmltag($obj->note_public); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Note private + if (!empty($arrayfields['cf.note_private']['checked'])) { + print ''; + print dol_string_nohtmltag($obj->note_private); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + + print "\n"; + + $total += $obj->total_ht; + $subtotal += $obj->total_ht; + } $i++; } From 04a216bf62a7d4acb3bf1f408c4feb3a6af32071 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 10:26:36 +0100 Subject: [PATCH 423/816] Debug and clean link page --- htdocs/accountancy/customer/index.php | 27 +++++++++------------- htdocs/accountancy/expensereport/index.php | 24 ++++++++++++++++++- htdocs/accountancy/supplier/index.php | 27 +++++++++------------- htdocs/langs/en_US/accountancy.lang | 2 +- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 46e6832dba2..1029934b8c6 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -126,21 +126,6 @@ if ($action == 'validatehistory') { $db->begin(); // Now make the binding. Bind automatically only for product with a dedicated account that exists into chart of account, others need a manual bind - /*if ($db->type == 'pgsql') { - $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facturedet"; - $sql1 .= " SET fk_code_ventilation = accnt.rowid"; - $sql1 .= " FROM " . MAIN_DB_PREFIX . "product as p, " . MAIN_DB_PREFIX . "accounting_account as accnt , " . MAIN_DB_PREFIX . "accounting_system as syst"; - $sql1 .= " WHERE " . MAIN_DB_PREFIX . "facturedet.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . ((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.((int) $conf->entity); - $sql1 .= " AND accnt.active = 1 AND p.accountancy_code_sell=accnt.account_number"; - $sql1 .= " AND " . MAIN_DB_PREFIX . "facturedet.fk_code_ventilation = 0"; - } else { - $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facturedet as fd, " . MAIN_DB_PREFIX . "product as p, " . MAIN_DB_PREFIX . "accounting_account as accnt , " . MAIN_DB_PREFIX . "accounting_system as syst"; - $sql1 .= " SET fk_code_ventilation = accnt.rowid"; - $sql1 .= " WHERE fd.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . ((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.((int) $conf->entity); - $sql1 .= " AND accnt.active = 1 AND p.accountancy_code_sell=accnt.account_number"; - $sql1 .= " AND fd.fk_code_ventilation = 0"; - }*/ - // Customer Invoice lines (must be same request than into page list.php for manual binding) $sql = "SELECT f.rowid as facid, f.ref as ref, f.datef, f.type as ftype, f.fk_facture_source,"; $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; @@ -408,7 +393,17 @@ if ($resql) { print ''; print ''; if ($row[0] == 'tobind') { - print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/customer/list.php?search_year='.((int) $y), $langs->transnoentitiesnoconv("ToBind")); + $startmonth = ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1); + if ($startmonth > 12) { + $startmonth -= 12; + } + $startyear = ($startmonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; + $endmonth = ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) + 11; + if ($endmonth > 12) { + $endmonth -= 12; + } + $endyear = ($endmonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; + print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/customer/list.php?search_date_startday=1&search_date_startmonth='.((int) $startmonth).'&search_date_startyear='.((int) $startyear).'&search_date_endday=&search_date_endmonth='.((int) $endmonth).'&search_date_endyear='.((int) $endyear), $langs->transnoentitiesnoconv("ToBind")); } else { print $row[1]; } diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index df226ce115d..aefa03651cb 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -266,7 +266,17 @@ if ($resql) { print ''; print ''; if ($row[0] == 'tobind') { - print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/expensereport/list.php?search_year='.((int) $y), $langs->transnoentitiesnoconv("ToBind")); + $startmonth = ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1); + if ($startmonth > 12) { + $startmonth -= 12; + } + $startyear = ($startmonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; + $endmonth = ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) + 11; + if ($endmonth > 12) { + $endmonth -= 12; + } + $endyear = ($endmonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; + print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/customer/list.php?search_date_startday=1&search_date_startmonth='.((int) $startmonth).'&search_date_startyear='.((int) $startyear).'&search_date_endday=&search_date_endmonth='.((int) $endmonth).'&search_date_endyear='.((int) $endyear), $langs->transnoentitiesnoconv("ToBind")); } else { print $row[1]; } @@ -293,6 +303,12 @@ if ($resql) { print ''; } $db->free($resql); + + if ($num == 0) { + print ''; + print ''.$langs->trans("NoRecordFound").''; + print ''; + } } else { print $db->lasterror(); // Show last sql error } @@ -375,6 +391,12 @@ if ($resql) { print ''; } $db->free($resql); + + if ($num == 0) { + print ''; + print ''.$langs->trans("NoRecordFound").''; + print ''; + } } else { print $db->lasterror(); // Show last sql error } diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index b66b791f7b1..1ffe913f9aa 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -124,21 +124,6 @@ if ($action == 'validatehistory') { $db->begin(); // Now make the binding. Bind automatically only for product with a dedicated account that exists into chart of account, others need a manual bind - /*if ($db->type == 'pgsql') { - $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_det"; - $sql1 .= " SET fk_code_ventilation = accnt.rowid"; - $sql1 .= " FROM " . MAIN_DB_PREFIX . "product as p, " . MAIN_DB_PREFIX . "accounting_account as accnt , " . MAIN_DB_PREFIX . "accounting_system as syst"; - $sql1 .= " WHERE " . MAIN_DB_PREFIX . "facture_fourn_det.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . ((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.$conf->entity; - $sql1 .= " AND accnt.active = 1 AND p.accountancy_code_buy=accnt.account_number"; - $sql1 .= " AND " . MAIN_DB_PREFIX . "facture_fourn_det.fk_code_ventilation = 0"; - } else { - $sql1 = "UPDATE " . MAIN_DB_PREFIX . "facture_fourn_det as fd, " . MAIN_DB_PREFIX . "product as p, " . MAIN_DB_PREFIX . "accounting_account as accnt , " . MAIN_DB_PREFIX . "accounting_system as syst"; - $sql1 .= " SET fk_code_ventilation = accnt.rowid"; - $sql1 .= " WHERE fd.fk_product = p.rowid AND accnt.fk_pcg_version = syst.pcg_version AND syst.rowid=" . ((int) $conf->global->CHARTOFACCOUNTS).' AND accnt.entity = '.$conf->entity; - $sql1 .= " AND accnt.active = 1 AND p.accountancy_code_buy=accnt.account_number"; - $sql1 .= " AND fd.fk_code_ventilation = 0"; - }*/ - // Supplier Invoice Lines (must be same request than into page list.php for manual binding) $sql = "SELECT f.rowid as facid, f.ref, f.ref_supplier, f.libelle as invoice_label, f.datef, f.type as ftype, f.fk_facture_source,"; $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; @@ -405,7 +390,17 @@ if ($resql) { print ''; print ''; if ($row[0] == 'tobind') { - print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/supplier/list.php?search_year='.((int) $y), $langs->transnoentitiesnoconv("ToBind")); + $startmonth = ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1); + if ($startmonth > 12) { + $startmonth -= 12; + } + $startyear = ($startmonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; + $endmonth = ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1) + 11; + if ($endmonth > 12) { + $endmonth -= 12; + } + $endyear = ($endmonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; + print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/customer/list.php?search_date_startday=1&search_date_startmonth='.((int) $startmonth).'&search_date_startyear='.((int) $startyear).'&search_date_endday=&search_date_endmonth='.((int) $endmonth).'&search_date_endyear='.((int) $endyear), $langs->transnoentitiesnoconv("ToBind")); } else { print $row[1]; } diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 554087ad5c4..5fb63c1c2ae 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -297,7 +297,7 @@ DescValidateMovements=Any modification or deletion of writing, lettering and del ValidateHistory=Bind Automatically AutomaticBindingDone=Automatic bindings done (%s) - Automatic binding not possible for some record (%s) -DoManualBindingForFailedRecord=You have to do a manual link for the rows not linked %s automatically. +DoManualBindingForFailedRecord=You have to do a manual link for the %s row(s) not linked automatically. ErrorAccountancyCodeIsAlreadyUse=Error, you cannot remove or disable this account of chart of account because it is used MvtNotCorrectlyBalanced=Movement not correctly balanced. Debit = %s & Credit = %s From 919849ab088a9c09a198a09c82bc2f8f637075cd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 10:48:26 +0100 Subject: [PATCH 424/816] Fix link --- htdocs/accountancy/customer/index.php | 2 +- htdocs/accountancy/expensereport/index.php | 2 +- htdocs/accountancy/supplier/index.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 1029934b8c6..69702d8b10e 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -420,7 +420,7 @@ if ($resql) { print price($row[$i]); // Add link to make binding if (!empty(price2num($row[$i]))) { - print ''; + print ''; print img_picto($langs->trans("ValidateHistory").' ('.$langs->trans('Month'.str_pad($cursormonth, 2, '0', STR_PAD_LEFT)).' '.$cursoryear.')', 'link', 'class="marginleft2"'); print ''; } diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index aefa03651cb..6bc3ff6a0e8 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -293,7 +293,7 @@ if ($resql) { print price($row[$i]); // Add link to make binding if (!empty(price2num($row[$i]))) { - print ''; + print ''; print img_picto($langs->trans("ValidateHistory").' ('.$langs->trans('Month'.str_pad($cursormonth, 2, '0', STR_PAD_LEFT)).' '.$cursoryear.')', 'link', 'class="marginleft2"'); print ''; } diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index 1ffe913f9aa..e67a75103ac 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -417,7 +417,7 @@ if ($resql) { print price($row[$i]); // Add link to make binding if (!empty(price2num($row[$i]))) { - print ''; + print ''; print img_picto($langs->trans("ValidateHistory").' ('.$langs->trans('Month'.str_pad($cursormonth, 2, '0', STR_PAD_LEFT)).' '.$cursoryear.')', 'link', 'class="marginleft2"'); print ''; } From 92a815644189c57f4c98ad39ad737461b1cb9d00 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 11:03:41 +0100 Subject: [PATCH 425/816] Fix link --- htdocs/accountancy/expensereport/index.php | 2 +- htdocs/accountancy/supplier/index.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index 6bc3ff6a0e8..d256d13252a 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -276,7 +276,7 @@ if ($resql) { $endmonth -= 12; } $endyear = ($endmonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; - print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/customer/list.php?search_date_startday=1&search_date_startmonth='.((int) $startmonth).'&search_date_startyear='.((int) $startyear).'&search_date_endday=&search_date_endmonth='.((int) $endmonth).'&search_date_endyear='.((int) $endyear), $langs->transnoentitiesnoconv("ToBind")); + print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/expensereport/list.php?search_date_startday=1&search_date_startmonth='.((int) $startmonth).'&search_date_startyear='.((int) $startyear).'&search_date_endday=&search_date_endmonth='.((int) $endmonth).'&search_date_endyear='.((int) $endyear), $langs->transnoentitiesnoconv("ToBind")); } else { print $row[1]; } diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index e67a75103ac..3e0f4fbd784 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -400,7 +400,7 @@ if ($resql) { $endmonth -= 12; } $endyear = ($endmonth < ($conf->global->SOCIETE_FISCAL_MONTH_START ? $conf->global->SOCIETE_FISCAL_MONTH_START : 1)) ? $y + 1 : $y; - print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/customer/list.php?search_date_startday=1&search_date_startmonth='.((int) $startmonth).'&search_date_startyear='.((int) $startyear).'&search_date_endday=&search_date_endmonth='.((int) $endmonth).'&search_date_endyear='.((int) $endyear), $langs->transnoentitiesnoconv("ToBind")); + print $langs->trans("UseMenuToSetBindindManualy", DOL_URL_ROOT.'/accountancy/supplier/list.php?search_date_startday=1&search_date_startmonth='.((int) $startmonth).'&search_date_startyear='.((int) $startyear).'&search_date_endday=&search_date_endmonth='.((int) $endmonth).'&search_date_endyear='.((int) $endyear), $langs->transnoentitiesnoconv("ToBind")); } else { print $row[1]; } From 86ad9118f3dcc036e22a35ca96aedeb14ed42762 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 10 Jan 2023 11:14:14 +0100 Subject: [PATCH 426/816] kanban mode for list of proposal commande --- htdocs/comm/propal/class/propal.class.php | 35 + htdocs/comm/propal/list.php | 1128 +++++++++++---------- 2 files changed, 611 insertions(+), 552 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index a5fd221de87..a363ff03bad 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -3890,6 +3890,41 @@ class Propal extends CommonObject return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables); } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + //$return .= ''; // Can be image + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + if (property_exists($this, 'fk_project')) { + $return .= ' | '.$this->fk_project.''; + } + if (property_exists($this, 'author')) { + $return .= '
'.$this->author.''; + } + if (property_exists($this, 'total_ht')) { + $return .='
'.$langs->trans("AmountHT").' : '.price($this->total_ht).''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } /** diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 2426abad9f4..3de7b0bf781 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -70,6 +70,7 @@ $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'proposallist'; +$mode = GETPOST('mode', 'alpha'); $search_user = GETPOST('search_user', 'int'); $search_sale = GETPOST('search_sale', 'int'); @@ -864,6 +865,9 @@ if ($resql) { } $param = '&search_status='.urlencode($search_status); + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -1072,6 +1076,9 @@ if ($resql) { if (!empty($socid)) { $url .= '&socid='.$socid; } + $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')); $newcardbutton = dolGetButtonTitle($langs->trans('NewPropal'), '', 'fa fa-plus-circle', $url, '', $user->rights->propal->creer); // Fields title search @@ -1085,6 +1092,7 @@ if ($resql) { print ''; print ''; print ''; + print ''; print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'propal', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -1702,574 +1710,590 @@ if ($resql) { $total_margin += $marginInfo['total_margin']; } - print ''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban + $userstatic->fetch($obj->fk_user_author); + $objectstatic->author = $userstatic->getNomUrl(1); + $objectstatic->fk_project = $projectstatic->getNomUrl(1); + print $objectstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + print ''; - // Action column - if (!empty($conf->global->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->rowid, $arrayofselected)) { - $selected = 1; + // Action column + if (!empty($conf->global->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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - if (!empty($arrayfields['p.ref']['checked'])) { - print ''; - - print ''; - // Picto + Ref - print ''; - // Warning - $warnornote = ''; - if ($obj->status == Propal::STATUS_VALIDATED && $db->jdate($obj->dfv) < ($now - $conf->propal->cloture->warning_delay)) { - $warnornote .= img_warning($langs->trans("Late")); - } - if ($warnornote) { - print ''; - } - // Other picto tool - print '
'; - print $objectstatic->getNomUrl(1, '', '', 0, 1, (isset($conf->global->PROPAL_LIST_SHOW_NOTES) ? $conf->global->PROPAL_LIST_SHOW_NOTES : 1)); - print ''; - print $warnornote; print ''; - $filename = dol_sanitizeFileName($obj->ref); - $filedir = $conf->propal->multidir_output[$obj->propal_entity].'/'.dol_sanitizeFileName($obj->ref); - $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; - print $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); - print '
'; - - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - if (!empty($arrayfields['p.ref_client']['checked'])) { - // Customer ref - print ''; - print dol_escape_htmltag($obj->ref_client); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - if (!empty($arrayfields['pr.ref']['checked'])) { - // Project ref - print ''; - if ($obj->project_id > 0) { - print $projectstatic->getNomUrl(1); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - if (!empty($arrayfields['pr.title']['checked'])) { - // Project label - print ''; - if ($obj->project_id > 0) { - print dol_escape_htmltag($projectstatic->title); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Thirdparty - if (!empty($arrayfields['s.nom']['checked'])) { - print ''; - print $companystatic->getNomUrl(1, 'customer', 0, 0, 1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Alias - if (!empty($arrayfields['s.name_alias']['checked'])) { - print ''; - print $obj->alias; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Town - if (!empty($arrayfields['s.town']['checked'])) { - print ''; - print $obj->town; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Zip - if (!empty($arrayfields['s.zip']['checked'])) { - print ''; - print $obj->zip; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['state.nom']['checked'])) { - print "".$obj->state_name."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['country.code_iso']['checked'])) { - print ''; - $tmparray = getCountry($obj->fk_pays, 'all'); - print $tmparray['label']; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Type ent - if (!empty($arrayfields['typent.code']['checked'])) { - if (!is_array($typenArray) || empty($typenArray)) { - $typenArray = $formcompany->typent_array(1); - } - - print ''; - print $typenArray[$obj->typent_code]; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date proposal - if (!empty($arrayfields['p.date']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->dp), 'day'); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date end validity - if (!empty($arrayfields['p.fin_validite']['checked'])) { - if ($obj->dfv) { - print ''.dol_print_date($db->jdate($obj->dfv), 'day'); - print ''; - } else { - print ' '; - } - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date delivery - if (!empty($arrayfields['p.date_livraison']['checked'])) { - if ($obj->ddelivery) { - print ''.dol_print_date($db->jdate($obj->ddelivery), 'day'); - print ''; - } else { - print ' '; - } - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date Signature - if (!empty($arrayfields['p.date_signature']['checked'])) { - if ($obj->dsignature) { - print ''.dol_print_date($db->jdate($obj->dsignature), 'day'); - print ''; - } else { - print ' '; - } - if (!$i) { - $totalarray['nbfield']++; - } - } - // Availability - if (!empty($arrayfields['ava.rowid']['checked'])) { - print ''; - $form->form_availability('', $obj->availability, 'none', 1); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Shipping Method - if (!empty($arrayfields['p.fk_shipping_method']['checked'])) { - print ''; - $form->formSelectShippingMethod('', $obj->fk_shipping_method, 'none', 1); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Source - input reason - if (!empty($arrayfields['p.fk_input_reason']['checked'])) { - print ''; - if ($obj->fk_input_reason > 0) { - print $form->cache_demand_reason[$obj->fk_input_reason]['label']; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Payment terms - if (!empty($arrayfields['p.fk_cond_reglement']['checked'])) { - print ''; - $form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 0, '', 1, $obj->deposit_percent); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Payment mode - if (!empty($arrayfields['p.fk_mode_reglement']['checked'])) { - print ''; - $form->form_modes_reglement($_SERVER['PHP_SELF'], $obj->fk_mode_reglement, 'none', '', -1); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount HT - if (!empty($arrayfields['p.total_ht']['checked'])) { - print ''.price($obj->total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'p.total_ht'; - } - if (empty($totalarray['val']['p.total_ht'])) { - $totalarray['val']['p.total_ht'] = $obj->total_ht; - } else { - $totalarray['val']['p.total_ht'] += $obj->total_ht; - } - } - // Amount VAT - if (!empty($arrayfields['p.total_tva']['checked'])) { - print ''.price($obj->total_tva)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'p.total_tva'; - } - if (empty($totalarray['val']['p.total_tva'])) { - $totalarray['val']['p.total_tva'] = $obj->total_tva; - } else { - $totalarray['val']['p.total_tva'] += $obj->total_tva; - } - } - // Amount TTC - if (!empty($arrayfields['p.total_ttc']['checked'])) { - print ''.price($obj->total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'p.total_ttc'; - } - if (empty($totalarray['val']['p.total_ttc'])) { - $totalarray['val']['p.total_ttc'] = $obj->total_ttc; - } else { - $totalarray['val']['p.total_ttc'] += $obj->total_ttc; - } - } - // Amount invoiced HT - if (!empty($arrayfields['p.total_ht_invoiced']['checked'])) { - print ''.price($totalInvoicedHT)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'p.total_ht_invoiced'; - } - if (empty($totalarray['val']['p.total_ht_invoiced'])) { - $totalarray['val']['p.total_ht_invoiced'] = $totalInvoicedHT; - } else { - $totalarray['val']['p.total_ht_invoiced'] += $totalInvoicedHT; - } - } - // Amount invoiced TTC - if (!empty($arrayfields['p.total_invoiced']['checked'])) { - print ''.price($totalInvoicedTTC)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'p.total_invoiced'; - } - if (empty($totalarray['val']['p.total_invoiced'])) { - $totalarray['val']['p.total_invoiced'] = $totalInvoicedTTC; - } else { - $totalarray['val']['p.total_invoiced'] += $totalInvoicedTTC; - } - } - // Currency - if (!empty($arrayfields['p.multicurrency_code']['checked'])) { - print ''.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Currency rate - if (!empty($arrayfields['p.multicurrency_tx']['checked'])) { - print ''; - $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount HT - if (!empty($arrayfields['p.multicurrency_total_ht']['checked'])) { - print ''.price($obj->multicurrency_total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount VAT - if (!empty($arrayfields['p.multicurrency_total_tva']['checked'])) { - print ''.price($obj->multicurrency_total_tva)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount TTC - if (!empty($arrayfields['p.multicurrency_total_ttc']['checked'])) { - print ''.price($obj->multicurrency_total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount invoiced - if (!empty($arrayfields['p.multicurrency_total_ht_invoiced']['checked'])) { - print ''.price($multicurrency_totalInvoicedHT)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount invoiced - if (!empty($arrayfields['p.multicurrency_total_invoiced']['checked'])) { - print ''.price($multicurrency_totalInvoicedTTC)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - $userstatic->id = $obj->fk_user_author; - $userstatic->login = $obj->login; - $userstatic->lastname = $obj->lastname; - $userstatic->firstname = $obj->firstname; - $userstatic->email = $obj->user_email; - $userstatic->statut = $obj->user_statut; - $userstatic->entity = $obj->user_entity; - $userstatic->photo = $obj->photo; - $userstatic->office_phone = $obj->office_phone; - $userstatic->office_fax = $obj->office_fax; - $userstatic->user_mobile = $obj->user_mobile; - $userstatic->job = $obj->job; - $userstatic->gender = $obj->gender; - - // Author - if (!empty($arrayfields['u.login']['checked'])) { - print ''; - if ($userstatic->id) { - print $userstatic->getNomUrl(-1); - } - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - if (!empty($arrayfields['sale_representative']['checked'])) { - // Sales representatives - print ''; - if ($obj->socid > 0) { - $listsalesrepresentatives = $companystatic->getSalesRepresentatives($user); - if ($listsalesrepresentatives < 0) { - dol_print_error($db); + if (!$i) { + $totalarray['nbfield']++; } - $nbofsalesrepresentative = count($listsalesrepresentatives); - if ($nbofsalesrepresentative > 6) { - // We print only number - print $nbofsalesrepresentative; - } elseif ($nbofsalesrepresentative > 0) { - $userstatic = new User($db); - $j = 0; - foreach ($listsalesrepresentatives as $val) { - $userstatic->id = $val['id']; - $userstatic->lastname = $val['lastname']; - $userstatic->firstname = $val['firstname']; - $userstatic->email = $val['email']; - $userstatic->statut = $val['statut']; - $userstatic->entity = $val['entity']; - $userstatic->photo = $val['photo']; - $userstatic->login = $val['login']; - $userstatic->office_phone = $val['office_phone']; - $userstatic->office_fax = $val['office_fax']; - $userstatic->user_mobile = $val['user_mobile']; - $userstatic->job = $val['job']; - $userstatic->gender = $val['gender']; - //print '
': - print ($nbofsalesrepresentative < 2) ? $userstatic->getNomUrl(-1, '', 0, 0, 12) : $userstatic->getNomUrl(-2); - $j++; - if ($j < $nbofsalesrepresentative) { - print ' '; + } + + if (!empty($arrayfields['p.ref']['checked'])) { + print ''; + + print ''; + // Picto + Ref + print ''; + // Warning + $warnornote = ''; + if ($obj->status == Propal::STATUS_VALIDATED && $db->jdate($obj->dfv) < ($now - $conf->propal->cloture->warning_delay)) { + $warnornote .= img_warning($langs->trans("Late")); + } + if ($warnornote) { + print ''; + } + // Other picto tool + print '
'; + print $objectstatic->getNomUrl(1, '', '', 0, 1, (isset($conf->global->PROPAL_LIST_SHOW_NOTES) ? $conf->global->PROPAL_LIST_SHOW_NOTES : 1)); + print ''; + print $warnornote; + print ''; + $filename = dol_sanitizeFileName($obj->ref); + $filedir = $conf->propal->multidir_output[$obj->propal_entity].'/'.dol_sanitizeFileName($obj->ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; + print $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); + print '
'; + + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + if (!empty($arrayfields['p.ref_client']['checked'])) { + // Customer ref + print ''; + print dol_escape_htmltag($obj->ref_client); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + if (!empty($arrayfields['pr.ref']['checked'])) { + // Project ref + print ''; + if ($obj->project_id > 0) { + print $projectstatic->getNomUrl(1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + if (!empty($arrayfields['pr.title']['checked'])) { + // Project label + print ''; + if ($obj->project_id > 0) { + print dol_escape_htmltag($projectstatic->title); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Thirdparty + if (!empty($arrayfields['s.nom']['checked'])) { + print ''; + print $companystatic->getNomUrl(1, 'customer', 0, 0, 1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print $obj->alias; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Town + if (!empty($arrayfields['s.town']['checked'])) { + print ''; + print $obj->town; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Zip + if (!empty($arrayfields['s.zip']['checked'])) { + print ''; + print $obj->zip; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['state.nom']['checked'])) { + print "".$obj->state_name."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['country.code_iso']['checked'])) { + print ''; + $tmparray = getCountry($obj->fk_pays, 'all'); + print $tmparray['label']; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Type ent + if (!empty($arrayfields['typent.code']['checked'])) { + if (!is_array($typenArray) || empty($typenArray)) { + $typenArray = $formcompany->typent_array(1); + } + + print ''; + print $typenArray[$obj->typent_code]; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date proposal + if (!empty($arrayfields['p.date']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->dp), 'day'); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date end validity + if (!empty($arrayfields['p.fin_validite']['checked'])) { + if ($obj->dfv) { + print ''.dol_print_date($db->jdate($obj->dfv), 'day'); + print ''; + } else { + print ' '; + } + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date delivery + if (!empty($arrayfields['p.date_livraison']['checked'])) { + if ($obj->ddelivery) { + print ''.dol_print_date($db->jdate($obj->ddelivery), 'day'); + print ''; + } else { + print ' '; + } + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date Signature + if (!empty($arrayfields['p.date_signature']['checked'])) { + if ($obj->dsignature) { + print ''.dol_print_date($db->jdate($obj->dsignature), 'day'); + print ''; + } else { + print ' '; + } + if (!$i) { + $totalarray['nbfield']++; + } + } + // Availability + if (!empty($arrayfields['ava.rowid']['checked'])) { + print ''; + $form->form_availability('', $obj->availability, 'none', 1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Shipping Method + if (!empty($arrayfields['p.fk_shipping_method']['checked'])) { + print ''; + $form->formSelectShippingMethod('', $obj->fk_shipping_method, 'none', 1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Source - input reason + if (!empty($arrayfields['p.fk_input_reason']['checked'])) { + print ''; + if ($obj->fk_input_reason > 0) { + print $form->cache_demand_reason[$obj->fk_input_reason]['label']; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Payment terms + if (!empty($arrayfields['p.fk_cond_reglement']['checked'])) { + print ''; + $form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 0, '', 1, $obj->deposit_percent); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Payment mode + if (!empty($arrayfields['p.fk_mode_reglement']['checked'])) { + print ''; + $form->form_modes_reglement($_SERVER['PHP_SELF'], $obj->fk_mode_reglement, 'none', '', -1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['p.total_ht']['checked'])) { + print ''.price($obj->total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'p.total_ht'; + } + if (empty($totalarray['val']['p.total_ht'])) { + $totalarray['val']['p.total_ht'] = $obj->total_ht; + } else { + $totalarray['val']['p.total_ht'] += $obj->total_ht; + } + } + // Amount VAT + if (!empty($arrayfields['p.total_tva']['checked'])) { + print ''.price($obj->total_tva)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'p.total_tva'; + } + if (empty($totalarray['val']['p.total_tva'])) { + $totalarray['val']['p.total_tva'] = $obj->total_tva; + } else { + $totalarray['val']['p.total_tva'] += $obj->total_tva; + } + } + // Amount TTC + if (!empty($arrayfields['p.total_ttc']['checked'])) { + print ''.price($obj->total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'p.total_ttc'; + } + if (empty($totalarray['val']['p.total_ttc'])) { + $totalarray['val']['p.total_ttc'] = $obj->total_ttc; + } else { + $totalarray['val']['p.total_ttc'] += $obj->total_ttc; + } + } + // Amount invoiced HT + if (!empty($arrayfields['p.total_ht_invoiced']['checked'])) { + print ''.price($totalInvoicedHT)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'p.total_ht_invoiced'; + } + if (empty($totalarray['val']['p.total_ht_invoiced'])) { + $totalarray['val']['p.total_ht_invoiced'] = $totalInvoicedHT; + } else { + $totalarray['val']['p.total_ht_invoiced'] += $totalInvoicedHT; + } + } + // Amount invoiced TTC + if (!empty($arrayfields['p.total_invoiced']['checked'])) { + print ''.price($totalInvoicedTTC)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'p.total_invoiced'; + } + if (empty($totalarray['val']['p.total_invoiced'])) { + $totalarray['val']['p.total_invoiced'] = $totalInvoicedTTC; + } else { + $totalarray['val']['p.total_invoiced'] += $totalInvoicedTTC; + } + } + // Currency + if (!empty($arrayfields['p.multicurrency_code']['checked'])) { + print ''.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Currency rate + if (!empty($arrayfields['p.multicurrency_tx']['checked'])) { + print ''; + $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['p.multicurrency_total_ht']['checked'])) { + print ''.price($obj->multicurrency_total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount VAT + if (!empty($arrayfields['p.multicurrency_total_tva']['checked'])) { + print ''.price($obj->multicurrency_total_tva)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount TTC + if (!empty($arrayfields['p.multicurrency_total_ttc']['checked'])) { + print ''.price($obj->multicurrency_total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount invoiced + if (!empty($arrayfields['p.multicurrency_total_ht_invoiced']['checked'])) { + print ''.price($multicurrency_totalInvoicedHT)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount invoiced + if (!empty($arrayfields['p.multicurrency_total_invoiced']['checked'])) { + print ''.price($multicurrency_totalInvoicedTTC)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + $userstatic->id = $obj->fk_user_author; + $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->email = $obj->user_email; + $userstatic->statut = $obj->user_statut; + $userstatic->entity = $obj->user_entity; + $userstatic->photo = $obj->photo; + $userstatic->office_phone = $obj->office_phone; + $userstatic->office_fax = $obj->office_fax; + $userstatic->user_mobile = $obj->user_mobile; + $userstatic->job = $obj->job; + $userstatic->gender = $obj->gender; + + // Author + if (!empty($arrayfields['u.login']['checked'])) { + print ''; + if ($userstatic->id) { + print $userstatic->getNomUrl(-1); + } + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + if (!empty($arrayfields['sale_representative']['checked'])) { + // Sales representatives + print ''; + if ($obj->socid > 0) { + $listsalesrepresentatives = $companystatic->getSalesRepresentatives($user); + if ($listsalesrepresentatives < 0) { + dol_print_error($db); + } + $nbofsalesrepresentative = count($listsalesrepresentatives); + if ($nbofsalesrepresentative > 6) { + // We print only number + print $nbofsalesrepresentative; + } elseif ($nbofsalesrepresentative > 0) { + $userstatic = new User($db); + $j = 0; + foreach ($listsalesrepresentatives as $val) { + $userstatic->id = $val['id']; + $userstatic->lastname = $val['lastname']; + $userstatic->firstname = $val['firstname']; + $userstatic->email = $val['email']; + $userstatic->statut = $val['statut']; + $userstatic->entity = $val['entity']; + $userstatic->photo = $val['photo']; + $userstatic->login = $val['login']; + $userstatic->office_phone = $val['office_phone']; + $userstatic->office_fax = $val['office_fax']; + $userstatic->user_mobile = $val['user_mobile']; + $userstatic->job = $val['job']; + $userstatic->gender = $val['gender']; + //print '
': + print ($nbofsalesrepresentative < 2) ? $userstatic->getNomUrl(-1, '', 0, 0, 12) : $userstatic->getNomUrl(-2); + $j++; + if ($j < $nbofsalesrepresentative) { + print ' '; + } + //print '
'; } - //print '
'; + } + //else print $langs->trans("NoSalesRepresentativeAffected"); + } else { + print ' '; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Total buying or cost price + if (!empty($arrayfields['total_pa']['checked'])) { + print ''.price($marginInfo['pa_total']).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total margin + if (!empty($arrayfields['total_margin']['checked'])) { + print ''.price($marginInfo['total_margin']).''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_margin'; + } + $totalarray['val']['total_margin'] = $total_margin; + } + // Total margin rate + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print ''.(($marginInfo['total_margin_rate'] == '') ? '' : price($marginInfo['total_margin_rate'], null, null, null, null, 2).'%').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total mark rate + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print ''.(($marginInfo['total_mark_rate'] == '') ? '' : price($marginInfo['total_mark_rate'], null, null, null, null, 2).'%').''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; + } + if ($i >= $imaxinloop - 1) { + if (!empty($total_ht)) { + $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); + } else { + $totalarray['val']['total_mark_rate'] = ''; } } - //else print $langs->trans("NoSalesRepresentativeAffected"); - } else { - print ' '; } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Total buying or cost price - if (!empty($arrayfields['total_pa']['checked'])) { - print ''.price($marginInfo['pa_total']).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Total margin - if (!empty($arrayfields['total_margin']['checked'])) { - print ''.price($marginInfo['total_margin']).''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'total_margin'; - } - $totalarray['val']['total_margin'] = $total_margin; - } - // Total margin rate - if (!empty($arrayfields['total_margin_rate']['checked'])) { - print ''.(($marginInfo['total_margin_rate'] == '') ? '' : price($marginInfo['total_margin_rate'], null, null, null, null, 2).'%').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Total mark rate - if (!empty($arrayfields['total_mark_rate']['checked'])) { - print ''.(($marginInfo['total_mark_rate'] == '') ? '' : price($marginInfo['total_mark_rate'], null, null, null, null, 2).'%').''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; - } - if ($i >= $imaxinloop - 1) { - if (!empty($total_ht)) { - $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); - } else { - $totalarray['val']['total_mark_rate'] = ''; + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, '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; + // Date creation + if (!empty($arrayfields['p.datec']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; } } - } - - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, '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; - // Date creation - if (!empty($arrayfields['p.datec']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['p.tms']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date cloture - if (!empty($arrayfields['p.date_cloture']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_cloture), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Note public - if (!empty($arrayfields['p.note_public']['checked'])) { - print ''; - print dol_string_nohtmltag($obj->note_public); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Note private - if (!empty($arrayfields['p.note_private']['checked'])) { - print ''; - print dol_string_nohtmltag($obj->note_private); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status - if (!empty($arrayfields['p.fk_statut']['checked'])) { - print ''.$objectstatic->getLibStatut(5).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Action column - if (empty($conf->global->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->rowid, $arrayofselected)) { - $selected = 1; + // Date modification + if (!empty($arrayfields['p.tms']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; } - print ''; - if (!$i) { - $totalarray['nbfield']++; + // Date cloture + if (!empty($arrayfields['p.date_cloture']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_cloture), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } + // Note public + if (!empty($arrayfields['p.note_public']['checked'])) { + print ''; + print dol_string_nohtmltag($obj->note_public); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Note private + if (!empty($arrayfields['p.note_private']['checked'])) { + print ''; + print dol_string_nohtmltag($obj->note_private); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status + if (!empty($arrayfields['p.fk_statut']['checked'])) { + print ''.$objectstatic->getLibStatut(5).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Action column + if (empty($conf->global->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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + + print ''."\n"; } - - print ''."\n"; - $i++; } From ce556d56c02ebe7e2ea001cd3540e1965d222405 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 11:32:21 +0100 Subject: [PATCH 427/816] Fix rounding --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 391657135b8..475690e9dba 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7723,7 +7723,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__AMOUNT_TEXT__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, '', true) : ''; $substitutionarray['__AMOUNT_TEXTCURRENCY__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, $conf->currency, true) : ''; - $substitutionarray['__AMOUNT_REMAIN__'] = is_object($object) ? $object->total_ttc - $already_payed_all : ''; + $substitutionarray['__AMOUNT_REMAIN__'] = is_object($object) ? price2num($object->total_ttc - $already_payed_all) : ''; $substitutionarray['__AMOUNT_VAT__'] = is_object($object) ? (isset($object->total_vat) ? $object->total_vat : $object->total_tva) : ''; $substitutionarray['__AMOUNT_VAT_TEXT__'] = is_object($object) ? (isset($object->total_vat) ? dol_convertToWord($object->total_vat, $outputlangs, '', true) : dol_convertToWord($object->total_tva, $outputlangs, '', true)) : ''; From 2da8c1d9bc2fc9d0e7205d87688eb6957fc56c6f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 11:32:21 +0100 Subject: [PATCH 428/816] Fix rounding --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 391657135b8..f9adc7bcf40 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7723,7 +7723,7 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__AMOUNT_TEXT__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, '', true) : ''; $substitutionarray['__AMOUNT_TEXTCURRENCY__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, $conf->currency, true) : ''; - $substitutionarray['__AMOUNT_REMAIN__'] = is_object($object) ? $object->total_ttc - $already_payed_all : ''; + $substitutionarray['__AMOUNT_REMAIN__'] = is_object($object) ? price2num($object->total_ttc - $already_payed_all, 'MT') : ''; $substitutionarray['__AMOUNT_VAT__'] = is_object($object) ? (isset($object->total_vat) ? $object->total_vat : $object->total_tva) : ''; $substitutionarray['__AMOUNT_VAT_TEXT__'] = is_object($object) ? (isset($object->total_vat) ? dol_convertToWord($object->total_vat, $outputlangs, '', true) : dol_convertToWord($object->total_tva, $outputlangs, '', true)) : ''; From 9a249bcbb8b58f6576193604540ec2962543f895 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 10 Jan 2023 12:10:43 +0100 Subject: [PATCH 429/816] kanban mode for list of proposal supplier --- .../class/supplier_proposal.class.php | 36 ++ htdocs/supplier_proposal/list.php | 576 +++++++++--------- 2 files changed, 336 insertions(+), 276 deletions(-) diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index f283295aeb5..53e78b06f84 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -2723,6 +2723,42 @@ class SupplierProposal extends CommonObject return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables); } + + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + //$return .= ''; // Can be image + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + if (property_exists($this, 'socid')) { + $return .= ' | '.$this->socid.''; + } + if (property_exists($this, 'delivery_date')) { + $return .= '
'.$langs->trans("DateEnd").' : '.dol_print_date($this->delivery_date).''; + } + if (property_exists($this, 'total_ttc')) { + $return .='
'.$langs->trans("AmountHT").' : '.price($this->total_ttc).''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/supplier_proposal/list.php b/htdocs/supplier_proposal/list.php index add084e91ab..b4426ec84d8 100644 --- a/htdocs/supplier_proposal/list.php +++ b/htdocs/supplier_proposal/list.php @@ -57,6 +57,7 @@ $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'supplierproposallist'; +$mode = GETPOST('mode', 'alpha'); $search_user = GETPOST('search_user', 'int'); $search_sale = GETPOST('search_sale', 'int'); @@ -510,6 +511,9 @@ if ($resql) { } $param = ''; + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -630,7 +634,10 @@ if ($resql) { if (!empty($socid)) { $url .= '&socid='.$socid; } - $newcardbutton = dolGetButtonTitle($langs->trans('NewAskPrice'), '', 'fa fa-plus-circle', $url, '', $user->rights->supplier_proposal->creer); + $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')); + $newcardbutton .= dolGetButtonTitle($langs->trans('NewAskPrice'), '', 'fa fa-plus-circle', $url, '', $user->rights->supplier_proposal->creer); // Fields title search print ''; @@ -642,6 +649,7 @@ if ($resql) { print ''; print ''; print ''; + print ''; print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'supplier_proposal', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -973,288 +981,304 @@ if ($resql) { $companystatic->client = $obj->client; $companystatic->code_client = $obj->code_client; - print ''; - // 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->rowid, $arrayofselected)) { - $selected = 1; - } - print ''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } - print ''; - } - if (!empty($arrayfields['sp.ref']['checked'])) { - print ''; - - print ''; - // Picto + Ref - print ''; - // Warning - $warnornote = ''; - //if ($obj->fk_statut == 1 && $db->jdate($obj->date_valid) < ($now - $conf->supplier_proposal->warning_delay)) $warnornote .= img_warning($langs->trans("Late")); - if ($warnornote) { - print ''; + } + } else { + print ''; + // Action column + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; } - // Other picto tool - print '
'; - print $objectstatic->getNomUrl(1, '', '', 0, -1, 1); - print ''; - print $warnornote; + // Output Kanban + $userstatic->fetch($obj->fk_user_author); + $objectstatic->socid = $companystatic->getNomUrl(1); + $objectstatic->user_author_id = $userstatic->getNomUrl(1); + $objectstatic->delivery_date = $obj->dp; + print $objectstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } print ''; - $filename = dol_sanitizeFileName($obj->ref); - $filedir = $conf->supplier_proposal->dir_output.'/'.dol_sanitizeFileName($obj->ref); - $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; - print $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); - print '
'; + if (!empty($arrayfields['sp.ref']['checked'])) { + print ''; - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Thirdparty - if (!empty($arrayfields['s.nom']['checked'])) { - print ''; - print $companystatic->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Alias - if (!empty($arrayfields['s.name_alias']['checked'])) { - print ''; - print $companystatic->name_alias; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Town - if (!empty($arrayfields['s.town']['checked'])) { - print ''; - print $obj->town; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Zip - if (!empty($arrayfields['s.zip']['checked'])) { - print ''; - print $obj->zip; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['state.nom']['checked'])) { - print "".$obj->state_name."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['country.code_iso']['checked'])) { - print ''; - $tmparray = getCountry($obj->fk_pays, 'all'); - print $tmparray['label']; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Type ent - if (!empty($arrayfields['typent.code']['checked'])) { - print ''; - if (empty($typenArray) || !is_array($typenArray) || count($typenArray) == 0) { - $typenArray = $formcompany->typent_array(1); - } - print $typenArray[$obj->typent_code]; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date proposal - if (!empty($arrayfields['sp.date_valid']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_valid), 'day'); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date delivery - if (!empty($arrayfields['sp.date_livraison']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->dp), 'day'); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Amount HT - if (!empty($arrayfields['sp.total_ht']['checked'])) { - print ''.price($obj->total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'sp.total_ht'; - } - $totalarray['val']['sp.total_ht'] += $obj->total_ht; - } - // Amount VAT - if (!empty($arrayfields['sp.total_tva']['checked'])) { - print ''.price($obj->total_tva)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'sp.total_tva'; - } - $totalarray['val']['sp.total_tva'] += $obj->total_tva; - } - // Amount TTC - if (!empty($arrayfields['sp.total_ttc']['checked'])) { - print ''.price($obj->total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'sp.total_ttc'; - } - $totalarray['val']['sp.total_ttc'] += $obj->total_ttc; - } - - // Currency - if (!empty($arrayfields['sp.multicurrency_code']['checked'])) { - print ''.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Currency rate - if (!empty($arrayfields['sp.multicurrency_tx']['checked'])) { - print ''; - $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount HT - if (!empty($arrayfields['sp.multicurrency_total_ht']['checked'])) { - print ''.price($obj->multicurrency_total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount VAT - if (!empty($arrayfields['sp.multicurrency_total_vat']['checked'])) { - print ''.price($obj->multicurrency_total_vat)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount TTC - if (!empty($arrayfields['sp.multicurrency_total_ttc']['checked'])) { - print ''.price($obj->multicurrency_total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - $userstatic->id = $obj->fk_user_author; - $userstatic->login = $obj->login; - $userstatic->status = $obj->ustatus; - $userstatic->lastname = $obj->name; - $userstatic->firstname = $obj->firstname; - $userstatic->photo = $obj->photo; - $userstatic->admin = $obj->admin; - $userstatic->ref = $obj->fk_user_author; - $userstatic->employee = $obj->employee; - $userstatic->email = $obj->uemail; - - // Author - if (!empty($arrayfields['u.login']['checked'])) { - print ''; - if ($userstatic->id > 0) { - print $userstatic->getNomUrl(-1, '', 0, 0, 24, 1, 'login', '', 1); - } else { - print ' '; - } - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - // Date creation - if (!empty($arrayfields['sp.datec']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['sp.tms']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status - if (!empty($arrayfields['sp.fk_statut']['checked'])) { - print ''.$objectstatic->getLibStatut(5)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // 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->rowid, $arrayofselected)) { - $selected = 1; + print ''; + // Picto + Ref + print ''; + // Warning + $warnornote = ''; + //if ($obj->fk_statut == 1 && $db->jdate($obj->date_valid) < ($now - $conf->supplier_proposal->warning_delay)) $warnornote .= img_warning($langs->trans("Late")); + if ($warnornote) { + print ''; + } + // Other picto tool + print '
'; + print $objectstatic->getNomUrl(1, '', '', 0, -1, 1); + print ''; + print $warnornote; + print ''; + $filename = dol_sanitizeFileName($obj->ref); + $filedir = $conf->supplier_proposal->dir_output.'/'.dol_sanitizeFileName($obj->ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; + print $formfile->getDocumentsLink($objectstatic->element, $filename, $filedir); + print '
'; + + print "\n"; + if (!$i) { + $totalarray['nbfield']++; } - print ''; } - print ''; + + // Thirdparty + if (!empty($arrayfields['s.nom']['checked'])) { + print ''; + print $companystatic->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print $companystatic->name_alias; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Town + if (!empty($arrayfields['s.town']['checked'])) { + print ''; + print $obj->town; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Zip + if (!empty($arrayfields['s.zip']['checked'])) { + print ''; + print $obj->zip; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['state.nom']['checked'])) { + print "".$obj->state_name."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['country.code_iso']['checked'])) { + print ''; + $tmparray = getCountry($obj->fk_pays, 'all'); + print $tmparray['label']; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Type ent + if (!empty($arrayfields['typent.code']['checked'])) { + print ''; + if (empty($typenArray) || !is_array($typenArray) || count($typenArray) == 0) { + $typenArray = $formcompany->typent_array(1); + } + print $typenArray[$obj->typent_code]; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date proposal + if (!empty($arrayfields['sp.date_valid']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_valid), 'day'); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date delivery + if (!empty($arrayfields['sp.date_livraison']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->dp), 'day'); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Amount HT + if (!empty($arrayfields['sp.total_ht']['checked'])) { + print ''.price($obj->total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'sp.total_ht'; + } + $totalarray['val']['sp.total_ht'] += $obj->total_ht; + } + // Amount VAT + if (!empty($arrayfields['sp.total_tva']['checked'])) { + print ''.price($obj->total_tva)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'sp.total_tva'; + } + $totalarray['val']['sp.total_tva'] += $obj->total_tva; + } + // Amount TTC + if (!empty($arrayfields['sp.total_ttc']['checked'])) { + print ''.price($obj->total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'sp.total_ttc'; + } + $totalarray['val']['sp.total_ttc'] += $obj->total_ttc; + } + + // Currency + if (!empty($arrayfields['sp.multicurrency_code']['checked'])) { + print ''.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Currency rate + if (!empty($arrayfields['sp.multicurrency_tx']['checked'])) { + print ''; + $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['sp.multicurrency_total_ht']['checked'])) { + print ''.price($obj->multicurrency_total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount VAT + if (!empty($arrayfields['sp.multicurrency_total_vat']['checked'])) { + print ''.price($obj->multicurrency_total_vat)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount TTC + if (!empty($arrayfields['sp.multicurrency_total_ttc']['checked'])) { + print ''.price($obj->multicurrency_total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + $userstatic->id = $obj->fk_user_author; + $userstatic->login = $obj->login; + $userstatic->status = $obj->ustatus; + $userstatic->lastname = $obj->name; + $userstatic->firstname = $obj->firstname; + $userstatic->photo = $obj->photo; + $userstatic->admin = $obj->admin; + $userstatic->ref = $obj->fk_user_author; + $userstatic->employee = $obj->employee; + $userstatic->email = $obj->uemail; + + // Author + if (!empty($arrayfields['u.login']['checked'])) { + print ''; + if ($userstatic->id > 0) { + print $userstatic->getNomUrl(-1, '', 0, 0, 24, 1, 'login', '', 1); + } else { + print ' '; + } + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Date creation + if (!empty($arrayfields['sp.datec']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['sp.tms']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status + if (!empty($arrayfields['sp.fk_statut']['checked'])) { + print ''.$objectstatic->getLibStatut(5)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + + print "\n"; + + $total += $obj->total_ht; + $subtotal += $obj->total_ht; } - if (!$i) { - $totalarray['nbfield']++; - } - - print "\n"; - - $total += $obj->total_ht; - $subtotal += $obj->total_ht; - $i++; } From c52247e6ac0212b906a3184372e4a05dfd7c57f3 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 10 Jan 2023 12:43:55 +0100 Subject: [PATCH 430/816] kanban mode for list of client invoice --- htdocs/compta/facture/class/facture.class.php | 31 + htdocs/compta/facture/list.php | 1225 +++++++++-------- 2 files changed, 655 insertions(+), 601 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 87914eac38e..4905ec3d99a 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -5732,6 +5732,37 @@ class Facture extends CommonInvoice dol_print_error($this->db); } } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + //$return .= ''; // Can be image + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'socid')) { + $return .= '
'.$this->socid.''; + } + if (property_exists($this, 'fk_user_author')) { + $return .= '
'.$this->fk_user_author.''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } /** diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index afc31d7efe3..a23b736b562 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -75,6 +75,7 @@ $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $optioncss = GETPOST('optioncss', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'invoicelist'; +$mode = GETPOST('mode', 'alpha'); if ($contextpage == 'poslist') { $optioncss = 'print'; @@ -974,6 +975,9 @@ if ($resql) { } $param = '&socid='.urlencode($socid); + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -1185,6 +1189,9 @@ if ($resql) { if (!empty($socid)) { $url .= '&socid='.$socid; } + $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')); $newcardbutton = dolGetButtonTitle($langs->trans('NewBill'), '', 'fa fa-plus-circle', $url, '', $user->hasRight("facture", "creer")); } @@ -1204,6 +1211,7 @@ if ($resql) { print ''; print ''; print ''; + print ''; print_barre_liste($langs->trans('BillsCustomers').' '.($socid > 0 ? ' '.$soc->name : ''), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'bill', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -1894,645 +1902,660 @@ if ($resql) { $total_margin += $marginInfo['total_margin']; } - print 'ref)); - print 'parent.place=\''.$place.'\''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } - print '});"'; - } - print '>'; - - - // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; - if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->id, $arrayofselected)) { - $selected = 1; + // Output Kanban + $facturestatic->socid = $companystatic->getNomUrl(1, 'company', 15); + $userstatic->fetch($obj->fk_user_author); + $facturestatic->fk_user_author = $userstatic->getNomUrl(1); + print $facturestatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + print 'ref)); + print 'parent.place=\''.$place.'\''; } - print ''; + print '});"'; } - print ''; - } + print '>'; - // No - if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { - print ''.(($offset * $limit) + $i).''; - } - // Ref - if (!empty($arrayfields['f.ref']['checked'])) { - print ''; - - print ''; - - print ''; - print ''; - print '
'; - if ($contextpage == 'poslist') { - print dol_escape_htmltag($obj->ref); - } else { - print $facturestatic->getNomUrl(1, '', 200, 0, '', 0, 1); - } - - $filename = dol_sanitizeFileName($obj->ref); - $filedir = $conf->facture->dir_output.'/'.dol_sanitizeFileName($obj->ref); - $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->id; - print $formfile->getDocumentsLink($facturestatic->element, $filename, $filedir); - print '
'; - - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Customer ref - if (!empty($arrayfields['f.ref_client']['checked'])) { - print ''; - print dol_escape_htmltag($obj->ref_client); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Type - if (!empty($arrayfields['f.type']['checked'])) { - print ''; - print $facturestatic->getLibType(2); - print ""; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date - if (!empty($arrayfields['f.datef']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->datef), 'day'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date - if (!empty($arrayfields['f.date_valid']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_valid), 'day'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date limit - if (!empty($arrayfields['f.date_lim_reglement']['checked'])) { - print ''.dol_print_date($datelimit, 'day'); - if ($facturestatic->hasDelay()) { - print img_warning($langs->trans('Alert').' - '.$langs->trans('Late')); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Project ref - if (!empty($arrayfields['p.ref']['checked'])) { - print ''; - if ($obj->project_id > 0) { - print $projectstatic->getNomUrl(1); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Project title - if (!empty($arrayfields['p.title']['checked'])) { - print ''; - if ($obj->project_id > 0) { - print dol_escape_htmltag($projectstatic->title); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Third party - if (!empty($arrayfields['s.nom']['checked'])) { - print ''; - if ($contextpage == 'poslist') { - print dol_escape_htmltag($companystatic->name); - } else { - print $companystatic->getNomUrl(1, 'customer', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Alias - if (!empty($arrayfields['s.name_alias']['checked'])) { - print ''; - print dol_escape_htmltag($companystatic->name_alias); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Parent company - if (!empty($arrayfields['s2.nom']['checked'])) { - print ''; - if ($obj->fk_parent > 0) { - if (!isset($company_url_list[$obj->fk_parent])) { - $companyparent = new Societe($db); - $res = $companyparent->fetch($obj->fk_parent); - if ($res > 0) { - $company_url_list[$obj->fk_parent] = $companyparent->getNomUrl(1); + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->id, $arrayofselected)) { + $selected = 1; } + print ''; } - if (isset($company_url_list[$obj->fk_parent])) { - print $company_url_list[$obj->fk_parent]; + print ''; + } + + // No + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { + print ''.(($offset * $limit) + $i).''; + } + + // Ref + if (!empty($arrayfields['f.ref']['checked'])) { + print ''; + + print ''; + + print ''; + print ''; + print '
'; + if ($contextpage == 'poslist') { + print dol_escape_htmltag($obj->ref); + } else { + print $facturestatic->getNomUrl(1, '', 200, 0, '', 0, 1); + } + + $filename = dol_sanitizeFileName($obj->ref); + $filedir = $conf->facture->dir_output.'/'.dol_sanitizeFileName($obj->ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->id; + print $formfile->getDocumentsLink($facturestatic->element, $filename, $filedir); + print '
'; + + print "\n"; + if (!$i) { + $totalarray['nbfield']++; } } - print ""; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Town - if (!empty($arrayfields['s.town']['checked'])) { - print ''; - print dol_escape_htmltag($obj->town); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Zip - if (!empty($arrayfields['s.zip']['checked'])) { - print ''; - print dol_escape_htmltag($obj->zip); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['state.nom']['checked'])) { - print "".dol_escape_htmltag($obj->state_name)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['country.code_iso']['checked'])) { - print ''; - $tmparray = getCountry($obj->fk_pays, 'all'); - print $tmparray['label']; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Type ent - if (!empty($arrayfields['typent.code']['checked'])) { - print ''; - if (!is_array($typenArray) || count($typenArray) == 0) { - $typenArray = $formcompany->typent_array(1); - } - print $typenArray[$obj->typent_code]; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Staff - if (!empty($arrayfields['staff.code']['checked'])) { - print ''; - if (!is_array($conf->cache['staff']) || count($conf->cache['staff']) == 0) { - $conf->cache['staff'] = $formcompany->effectif_array(1); - } - print $conf->cache['staff'][$obj->staff_code]; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Payment mode - if (!empty($arrayfields['f.fk_mode_reglement']['checked'])) { - $s = $form->form_modes_reglement($_SERVER['PHP_SELF'], $obj->fk_mode_reglement, 'none', '', -1, 0, '', 1); - print ''; - print $s; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Payment terms - if (!empty($arrayfields['f.fk_cond_reglement']['checked'])) { - $s = $form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 0, '', -1, -1, 1); - print ''; - print $s; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Module Source - if (!empty($arrayfields['f.module_source']['checked'])) { - print ''; - print dol_escape_htmltag($obj->module_source); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // POS Terminal - if (!empty($arrayfields['f.pos_source']['checked'])) { - print ''; - print dol_escape_htmltag($obj->pos_source); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Amount HT - if (!empty($arrayfields['f.total_ht']['checked'])) { - print ''.price($obj->total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_ht'; - } - $totalarray['val']['f.total_ht'] += $obj->total_ht; - } - // Amount VAT - if (!empty($arrayfields['f.total_tva']['checked'])) { - print ''.price($obj->total_tva)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_tva'; - } - $totalarray['val']['f.total_tva'] += $obj->total_tva; - } - // Amount LocalTax1 - if (!empty($arrayfields['f.total_localtax1']['checked'])) { - print ''.price($obj->total_localtax1)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_localtax1'; - } - $totalarray['val']['f.total_localtax1'] += $obj->total_localtax1; - } - // Amount LocalTax2 - if (!empty($arrayfields['f.total_localtax2']['checked'])) { - print ''.price($obj->total_localtax2)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_localtax2'; - } - $totalarray['val']['f.total_localtax2'] += $obj->total_localtax2; - } - // Amount TTC - if (!empty($arrayfields['f.total_ttc']['checked'])) { - print ''.price($obj->total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_ttc'; - } - $totalarray['val']['f.total_ttc'] += $obj->total_ttc; - } - - $userstatic->id = $obj->fk_user_author; - $userstatic->login = $obj->login; - $userstatic->lastname = $obj->lastname; - $userstatic->firstname = $obj->firstname; - $userstatic->email = $obj->user_email; - $userstatic->statut = $obj->user_statut; - $userstatic->entity = $obj->entity; - $userstatic->photo = $obj->photo; - $userstatic->office_phone = $obj->office_phone; - $userstatic->office_fax = $obj->office_fax; - $userstatic->user_mobile = $obj->user_mobile; - $userstatic->job = $obj->job; - $userstatic->gender = $obj->gender; - - // Author - if (!empty($arrayfields['u.login']['checked'])) { - print ''; - if ($userstatic->id) { - print $userstatic->getNomUrl(-1); - } else { - print ' '; - } - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - if (!empty($arrayfields['sale_representative']['checked'])) { - // Sales representatives - print ''; - if ($obj->socid > 0) { - $listsalesrepresentatives = $companystatic->getSalesRepresentatives($user); - if ($listsalesrepresentatives < 0) { - dol_print_error($db); + // Customer ref + if (!empty($arrayfields['f.ref_client']['checked'])) { + print ''; + print dol_escape_htmltag($obj->ref_client); + print ''; + if (!$i) { + $totalarray['nbfield']++; } - $nbofsalesrepresentative = count($listsalesrepresentatives); - if ($nbofsalesrepresentative > 6) { - // We print only number - print $nbofsalesrepresentative; - } elseif ($nbofsalesrepresentative > 0) { - $j = 0; - foreach ($listsalesrepresentatives as $val) { - $userstatic->id = $val['id']; - $userstatic->lastname = $val['lastname']; - $userstatic->firstname = $val['firstname']; - $userstatic->email = $val['email']; - $userstatic->statut = $val['statut']; - $userstatic->entity = $val['entity']; - $userstatic->photo = $val['photo']; - $userstatic->login = $val['login']; - $userstatic->office_phone = $val['office_phone']; - $userstatic->office_fax = $val['office_fax']; - $userstatic->user_mobile = $val['user_mobile']; - $userstatic->job = $val['job']; - $userstatic->gender = $val['gender']; - //print '
': - print ($nbofsalesrepresentative < 2) ? $userstatic->getNomUrl(-1, '', 0, 0, 12) : $userstatic->getNomUrl(-2); - $j++; - if ($j < $nbofsalesrepresentative) { - print ' '; + } + + // Type + if (!empty($arrayfields['f.type']['checked'])) { + print ''; + print $facturestatic->getLibType(2); + print ""; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date + if (!empty($arrayfields['f.datef']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->datef), 'day'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date + if (!empty($arrayfields['f.date_valid']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_valid), 'day'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date limit + if (!empty($arrayfields['f.date_lim_reglement']['checked'])) { + print ''.dol_print_date($datelimit, 'day'); + if ($facturestatic->hasDelay()) { + print img_warning($langs->trans('Alert').' - '.$langs->trans('Late')); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Project ref + if (!empty($arrayfields['p.ref']['checked'])) { + print ''; + if ($obj->project_id > 0) { + print $projectstatic->getNomUrl(1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Project title + if (!empty($arrayfields['p.title']['checked'])) { + print ''; + if ($obj->project_id > 0) { + print dol_escape_htmltag($projectstatic->title); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Third party + if (!empty($arrayfields['s.nom']['checked'])) { + print ''; + if ($contextpage == 'poslist') { + print dol_escape_htmltag($companystatic->name); + } else { + print $companystatic->getNomUrl(1, 'customer', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print dol_escape_htmltag($companystatic->name_alias); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Parent company + if (!empty($arrayfields['s2.nom']['checked'])) { + print ''; + if ($obj->fk_parent > 0) { + if (!isset($company_url_list[$obj->fk_parent])) { + $companyparent = new Societe($db); + $res = $companyparent->fetch($obj->fk_parent); + if ($res > 0) { + $company_url_list[$obj->fk_parent] = $companyparent->getNomUrl(1); } - //print '
'; + } + if (isset($company_url_list[$obj->fk_parent])) { + print $company_url_list[$obj->fk_parent]; } } - //else print $langs->trans("NoSalesRepresentativeAffected"); - } else { - print ' '; + print ""; + if (!$i) { + $totalarray['nbfield']++; + } } - print ''; - if (!$i) { - $totalarray['nbfield']++; + // Town + if (!empty($arrayfields['s.town']['checked'])) { + print ''; + print dol_escape_htmltag($obj->town); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Zip + if (!empty($arrayfields['s.zip']['checked'])) { + print ''; + print dol_escape_htmltag($obj->zip); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['state.nom']['checked'])) { + print "".dol_escape_htmltag($obj->state_name)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['country.code_iso']['checked'])) { + print ''; + $tmparray = getCountry($obj->fk_pays, 'all'); + print $tmparray['label']; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Type ent + if (!empty($arrayfields['typent.code']['checked'])) { + print ''; + if (!is_array($typenArray) || count($typenArray) == 0) { + $typenArray = $formcompany->typent_array(1); + } + print $typenArray[$obj->typent_code]; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Staff + if (!empty($arrayfields['staff.code']['checked'])) { + print ''; + if (!is_array($conf->cache['staff']) || count($conf->cache['staff']) == 0) { + $conf->cache['staff'] = $formcompany->effectif_array(1); + } + print $conf->cache['staff'][$obj->staff_code]; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - } - if (!empty($arrayfields['f.retained_warranty']['checked'])) { - print ''.(!empty($obj->retained_warranty) ? price($obj->retained_warranty).'%' : ' ').''; - } + // Payment mode + if (!empty($arrayfields['f.fk_mode_reglement']['checked'])) { + $s = $form->form_modes_reglement($_SERVER['PHP_SELF'], $obj->fk_mode_reglement, 'none', '', -1, 0, '', 1); + print ''; + print $s; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } - if (!empty($arrayfields['dynamount_payed']['checked'])) { - print ''.(!empty($totalpay) ? price($totalpay, 0, $langs) : ' ').''; // TODO Use a denormalized field - if (!$i) { - $totalarray['nbfield']++; + // Payment terms + if (!empty($arrayfields['f.fk_cond_reglement']['checked'])) { + $s = $form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 0, '', -1, -1, 1); + print ''; + print $s; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'totalam'; - } - $totalarray['val']['totalam'] += $totalpay; - } - // Pending amount - if (!empty($arrayfields['rtp']['checked'])) { - print ''; - print (!empty($remaintopay) ? price($remaintopay, 0, $langs) : ' '); - print ''; // TODO Use a denormalized field - if (!$i) { - $totalarray['nbfield']++; + // Module Source + if (!empty($arrayfields['f.module_source']['checked'])) { + print ''; + print dol_escape_htmltag($obj->module_source); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'rtp'; - } - $totalarray['val']['rtp'] += $remaintopay; - } + // POS Terminal + if (!empty($arrayfields['f.pos_source']['checked'])) { + print ''; + print dol_escape_htmltag($obj->pos_source); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } - // Currency - if (!empty($arrayfields['f.multicurrency_code']['checked'])) { - print ''; - if (empty($conf->global->MAIN_SHOW_ONLY_CODE_MULTICURRENCY)) { - print $langs->transnoentitiesnoconv('Currency'.$obj->multicurrency_code); - } else { - print dol_escape_htmltag($obj->multicurrency_code); + // Amount HT + if (!empty($arrayfields['f.total_ht']['checked'])) { + print ''.price($obj->total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_ht'; + } + $totalarray['val']['f.total_ht'] += $obj->total_ht; } - print "\n"; - if (!$i) { - $totalarray['nbfield']++; + // Amount VAT + if (!empty($arrayfields['f.total_tva']['checked'])) { + print ''.price($obj->total_tva)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_tva'; + } + $totalarray['val']['f.total_tva'] += $obj->total_tva; + } + // Amount LocalTax1 + if (!empty($arrayfields['f.total_localtax1']['checked'])) { + print ''.price($obj->total_localtax1)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_localtax1'; + } + $totalarray['val']['f.total_localtax1'] += $obj->total_localtax1; + } + // Amount LocalTax2 + if (!empty($arrayfields['f.total_localtax2']['checked'])) { + print ''.price($obj->total_localtax2)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_localtax2'; + } + $totalarray['val']['f.total_localtax2'] += $obj->total_localtax2; + } + // Amount TTC + if (!empty($arrayfields['f.total_ttc']['checked'])) { + print ''.price($obj->total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_ttc'; + } + $totalarray['val']['f.total_ttc'] += $obj->total_ttc; } - } - // Currency rate - if (!empty($arrayfields['f.multicurrency_tx']['checked'])) { - print ''; - $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount HT - if (!empty($arrayfields['f.multicurrency_total_ht']['checked'])) { - print ''.price($obj->multicurrency_total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount VAT - if (!empty($arrayfields['f.multicurrency_total_vat']['checked'])) { - print ''.price($obj->multicurrency_total_vat)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount TTC - if (!empty($arrayfields['f.multicurrency_total_ttc']['checked'])) { - print ''.price($obj->multicurrency_total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['multicurrency_dynamount_payed']['checked'])) { - print ''.(!empty($multicurrency_totalpay) ?price($multicurrency_totalpay, 0, $langs) : ' ').''; // TODO Use a denormalized field - if (!$i) { - $totalarray['nbfield']++; - } - } + $userstatic->id = $obj->fk_user_author; + $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->email = $obj->user_email; + $userstatic->statut = $obj->user_statut; + $userstatic->entity = $obj->entity; + $userstatic->photo = $obj->photo; + $userstatic->office_phone = $obj->office_phone; + $userstatic->office_fax = $obj->office_fax; + $userstatic->user_mobile = $obj->user_mobile; + $userstatic->job = $obj->job; + $userstatic->gender = $obj->gender; - // Pending amount - if (!empty($arrayfields['multicurrency_rtp']['checked'])) { - print ''; - print (!empty($multicurrency_remaintopay) ? price($multicurrency_remaintopay, 0, $langs) : ' '); - print ''; // TODO Use a denormalized field - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Total buying or cost price - if (!empty($arrayfields['total_pa']['checked'])) { - print ''.price($marginInfo['pa_total']).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Total margin - if (!empty($arrayfields['total_margin']['checked'])) { - print ''.price($marginInfo['total_margin']).''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'total_margin'; - } - $totalarray['val']['total_margin'] += $marginInfo['total_margin']; - } - // Total margin rate - if (!empty($arrayfields['total_margin_rate']['checked'])) { - print ''.(($marginInfo['total_margin_rate'] == '') ? '' : price($marginInfo['total_margin_rate'], null, null, null, null, 2).'%').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Total mark rate - if (!empty($arrayfields['total_mark_rate']['checked'])) { - print ''.(($marginInfo['total_mark_rate'] == '') ? '' : price($marginInfo['total_mark_rate'], null, null, null, null, 2).'%').''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; - } - if ($i >= $imaxinloop - 1) { - if (!empty($total_ht)) { - $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); + // Author + if (!empty($arrayfields['u.login']['checked'])) { + print ''; + if ($userstatic->id) { + print $userstatic->getNomUrl(-1); } else { - $totalarray['val']['total_mark_rate'] = ''; + print ' '; + } + print "\n"; + if (!$i) { + $totalarray['nbfield']++; } } - } - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, '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; - // Date creation - if (!empty($arrayfields['f.datec']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['f.tms']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date closing - if (!empty($arrayfields['f.date_closing']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_closing), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Note public - if (!empty($arrayfields['f.note_public']['checked'])) { - print ''; - print dol_string_nohtmltag($obj->note_public); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Note private - if (!empty($arrayfields['f.note_private']['checked'])) { - print ''; - print dol_string_nohtmltag($obj->note_private); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Template Invoice - if (!empty($arrayfields['f.fk_fac_rec_source']['checked'])) { - print ''; - if (!empty($obj->fk_fac_rec_source)) { - $facrec = new FactureRec($db); - $result = $facrec->fetch($obj->fk_fac_rec_source); - if ($result < 0) { - setEventMessages($facrec->error, $facrec->errors, 'errors'); + if (!empty($arrayfields['sale_representative']['checked'])) { + // Sales representatives + print ''; + if ($obj->socid > 0) { + $listsalesrepresentatives = $companystatic->getSalesRepresentatives($user); + if ($listsalesrepresentatives < 0) { + dol_print_error($db); + } + $nbofsalesrepresentative = count($listsalesrepresentatives); + if ($nbofsalesrepresentative > 6) { + // We print only number + print $nbofsalesrepresentative; + } elseif ($nbofsalesrepresentative > 0) { + $j = 0; + foreach ($listsalesrepresentatives as $val) { + $userstatic->id = $val['id']; + $userstatic->lastname = $val['lastname']; + $userstatic->firstname = $val['firstname']; + $userstatic->email = $val['email']; + $userstatic->statut = $val['statut']; + $userstatic->entity = $val['entity']; + $userstatic->photo = $val['photo']; + $userstatic->login = $val['login']; + $userstatic->office_phone = $val['office_phone']; + $userstatic->office_fax = $val['office_fax']; + $userstatic->user_mobile = $val['user_mobile']; + $userstatic->job = $val['job']; + $userstatic->gender = $val['gender']; + //print '
': + print ($nbofsalesrepresentative < 2) ? $userstatic->getNomUrl(-1, '', 0, 0, 12) : $userstatic->getNomUrl(-2); + $j++; + if ($j < $nbofsalesrepresentative) { + print ' '; + } + //print '
'; + } + } + //else print $langs->trans("NoSalesRepresentativeAffected"); } else { - print $facrec->getNomUrl(); + print ' '; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; } } - print ''; + + if (!empty($arrayfields['f.retained_warranty']['checked'])) { + print ''.(!empty($obj->retained_warranty) ? price($obj->retained_warranty).'%' : ' ').''; + } + + if (!empty($arrayfields['dynamount_payed']['checked'])) { + print ''.(!empty($totalpay) ? price($totalpay, 0, $langs) : ' ').''; // TODO Use a denormalized field + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'totalam'; + } + $totalarray['val']['totalam'] += $totalpay; + } + + // Pending amount + if (!empty($arrayfields['rtp']['checked'])) { + print ''; + print (!empty($remaintopay) ? price($remaintopay, 0, $langs) : ' '); + print ''; // TODO Use a denormalized field + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'rtp'; + } + $totalarray['val']['rtp'] += $remaintopay; + } + + + // Currency + if (!empty($arrayfields['f.multicurrency_code']['checked'])) { + print ''; + if (empty($conf->global->MAIN_SHOW_ONLY_CODE_MULTICURRENCY)) { + print $langs->transnoentitiesnoconv('Currency'.$obj->multicurrency_code); + } else { + print dol_escape_htmltag($obj->multicurrency_code); + } + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Currency rate + if (!empty($arrayfields['f.multicurrency_tx']['checked'])) { + print ''; + $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['f.multicurrency_total_ht']['checked'])) { + print ''.price($obj->multicurrency_total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount VAT + if (!empty($arrayfields['f.multicurrency_total_vat']['checked'])) { + print ''.price($obj->multicurrency_total_vat)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount TTC + if (!empty($arrayfields['f.multicurrency_total_ttc']['checked'])) { + print ''.price($obj->multicurrency_total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['multicurrency_dynamount_payed']['checked'])) { + print ''.(!empty($multicurrency_totalpay) ?price($multicurrency_totalpay, 0, $langs) : ' ').''; // TODO Use a denormalized field + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Pending amount + if (!empty($arrayfields['multicurrency_rtp']['checked'])) { + print ''; + print (!empty($multicurrency_remaintopay) ? price($multicurrency_remaintopay, 0, $langs) : ' '); + print ''; // TODO Use a denormalized field + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Total buying or cost price + if (!empty($arrayfields['total_pa']['checked'])) { + print ''.price($marginInfo['pa_total']).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total margin + if (!empty($arrayfields['total_margin']['checked'])) { + print ''.price($marginInfo['total_margin']).''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_margin'; + } + $totalarray['val']['total_margin'] += $marginInfo['total_margin']; + } + // Total margin rate + if (!empty($arrayfields['total_margin_rate']['checked'])) { + print ''.(($marginInfo['total_margin_rate'] == '') ? '' : price($marginInfo['total_margin_rate'], null, null, null, null, 2).'%').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Total mark rate + if (!empty($arrayfields['total_mark_rate']['checked'])) { + print ''.(($marginInfo['total_mark_rate'] == '') ? '' : price($marginInfo['total_mark_rate'], null, null, null, null, 2).'%').''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; + } + if ($i >= $imaxinloop - 1) { + if (!empty($total_ht)) { + $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); + } else { + $totalarray['val']['total_mark_rate'] = ''; + } + } + } + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, '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; + // Date creation + if (!empty($arrayfields['f.datec']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['f.tms']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date closing + if (!empty($arrayfields['f.date_closing']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_closing), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Note public + if (!empty($arrayfields['f.note_public']['checked'])) { + print ''; + print dol_string_nohtmltag($obj->note_public); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Note private + if (!empty($arrayfields['f.note_private']['checked'])) { + print ''; + print dol_string_nohtmltag($obj->note_private); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Template Invoice + if (!empty($arrayfields['f.fk_fac_rec_source']['checked'])) { + print ''; + if (!empty($obj->fk_fac_rec_source)) { + $facrec = new FactureRec($db); + $result = $facrec->fetch($obj->fk_fac_rec_source); + if ($result < 0) { + setEventMessages($facrec->error, $facrec->errors, 'errors'); + } else { + print $facrec->getNomUrl(); + } + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status + if (!empty($arrayfields['f.fk_statut']['checked'])) { + print ''; + print $facturestatic->getLibStatut(5, $paiement); + print ""; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Action column (Show the massaction button only when this page is not opend from the Extended POS) + + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($obj->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + } if (!$i) { $totalarray['nbfield']++; } + print "\n"; } - // Status - if (!empty($arrayfields['f.fk_statut']['checked'])) { - print ''; - print $facturestatic->getLibStatut(5, $paiement); - print ""; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Action column (Show the massaction button only when this page is not opend from the Extended POS) - - if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { - print ''; - if (($massactionbutton || $massaction) && $contextpage != 'poslist') { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined - $selected = 0; - if (in_array($obj->id, $arrayofselected)) { - $selected = 1; - } - print ''; - } - print ''; - } - if (!$i) { - $totalarray['nbfield']++; - } - print "\n"; - $i++; } From 130e9d8df2a931ae4da54e339699922f08e9201a Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 10 Jan 2023 13:29:46 +0100 Subject: [PATCH 431/816] kanban for list of suppliers invoices --- .../fourn/class/fournisseur.facture.class.php | 37 + htdocs/fourn/facture/list.php | 810 +++++++++--------- 2 files changed, 452 insertions(+), 395 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index de012c86a58..93a8fc0d1ef 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -3225,6 +3225,43 @@ class FactureFournisseur extends CommonInvoice return $isUsed; } + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'socid')) { + $return .= ' | '.$this->socid.''; + } + if (property_exists($this, 'date_echeance') && property_exists($this, 'date')) { + if (!empty($this->date_echeance)) { + $return .= '
'.dol_print_date($this->date_echeance).''; + } else { + $return .= '
'.dol_print_date($this->date).''; + } + } + if (property_exists($this, 'total_ht')) { + $return .= '
'.$langs->trans("AmountHT").' : '.price($this->total_ht).''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index be215e891eb..3c4dfb32b15 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -766,6 +766,9 @@ if ($socid) { } $param = '&socid='.$socid; +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -918,7 +921,10 @@ $url = DOL_URL_ROOT.'/fourn/facture/card.php?action=create'; if (!empty($socid)) { $url .= '&socid='.urlencode($socid); } -$newcardbutton = dolGetButtonTitle($langs->trans('NewBill'), '', 'fa fa-plus-circle', $url, '', ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer)); +$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')); +$newcardbutton .= dolGetButtonTitle($langs->trans('NewBill'), '', 'fa fa-plus-circle', $url, '', ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer)); $i = 0; print ''."\n"; @@ -1430,409 +1436,423 @@ if ($num > 0) { $remaintopay = -$facturestatic->getSumFromThisCreditNotesNotUsed(); } } - - print ''; - // 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->facid, $arrayofselected)) { - $selected = 1; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban + $facturestatic->socid = $thirdparty->getNomUrl(1, 'supplier', 3); + $facturestatic->total_ht = $obj->total_ht; + $facturestatic->date = $obj->datef; + print $facturestatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + print ''; + // 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->facid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print ''; } - print ''; - } - if (!empty($arrayfields['f.ref']['checked'])) { - print ''; + if (!empty($arrayfields['f.ref']['checked'])) { + print ''; - print ''; - // Picto + Ref - print '
'; - print $facturestatic->getNomUrl(1, '', 0, 0, '', 0, -1, 1); + print ''; + // Picto + Ref + print '
'; + print $facturestatic->getNomUrl(1, '', 0, 0, '', 0, -1, 1); - $filename = dol_sanitizeFileName($obj->ref); - $filedir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($obj->facid, 2, 0, 0, $facturestatic, 'invoice_supplier').dol_sanitizeFileName($obj->ref); - $subdir = get_exdir($obj->facid, 2, 0, 0, $facturestatic, 'invoice_supplier').dol_sanitizeFileName($obj->ref); - print $formfile->getDocumentsLink('facture_fournisseur', $subdir, $filedir); - print '
'; + $filename = dol_sanitizeFileName($obj->ref); + $filedir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($obj->facid, 2, 0, 0, $facturestatic, 'invoice_supplier').dol_sanitizeFileName($obj->ref); + $subdir = get_exdir($obj->facid, 2, 0, 0, $facturestatic, 'invoice_supplier').dol_sanitizeFileName($obj->ref); + print $formfile->getDocumentsLink('facture_fournisseur', $subdir, $filedir); + print '
'; - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Supplier ref - if (!empty($arrayfields['f.ref_supplier']['checked'])) { - print ''; - print $obj->ref_supplier; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Type - if (!empty($arrayfields['f.type']['checked'])) { - print ''; - print $facturestatic->getLibType(); - print ""; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Label - if (!empty($arrayfields['f.label']['checked'])) { - print ''; - print $obj->label; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date - if (!empty($arrayfields['f.datef']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->datef), 'day'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date limit - if (!empty($arrayfields['f.date_lim_reglement']['checked'])) { - print ''.dol_print_date($datelimit, 'day'); - if ($facturestatic->hasDelay()) { - print img_warning($langs->trans('Alert').' - '.$langs->trans('Late')); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Project - if (!empty($arrayfields['p.ref']['checked'])) { - print ''; - if ($obj->project_id > 0) { - $projectstatic->id = $obj->project_id; - $projectstatic->ref = $obj->project_ref; - $projectstatic->title = $obj->project_label; - print $projectstatic->getNomUrl(1); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Third party - if (!empty($arrayfields['s.nom']['checked'])) { - print ''; - print $thirdparty->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Alias - if (!empty($arrayfields['s.name_alias']['checked'])) { - print ''; - print $thirdparty->name_alias; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Town - if (!empty($arrayfields['s.town']['checked'])) { - print ''; - print $obj->town; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Zip - if (!empty($arrayfields['s.zip']['checked'])) { - print ''; - print dol_escape_htmltag($obj->zip); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // State - if (!empty($arrayfields['state.nom']['checked'])) { - print "".$obj->state_name."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Country - if (!empty($arrayfields['country.code_iso']['checked'])) { - print ''; - $tmparray = getCountry($obj->fk_pays, 'all'); - print $tmparray['label']; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Type ent - if (!empty($arrayfields['typent.code']['checked'])) { - print ''; - if (empty($typenArray)) { - $typenArray = $formcompany->typent_array(1); - } - print $typenArray[$obj->typent_code]; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Payment condition - if (!empty($arrayfields['f.fk_cond_reglement']['checked'])) { - $s = $form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 1, '', -1, -1, 1); - print ''; - print dol_escape_htmltag($s); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Payment mode - if (!empty($arrayfields['f.fk_mode_reglement']['checked'])) { - $s = $form->form_modes_reglement($_SERVER['PHP_SELF'], $obj->fk_mode_reglement, 'none', '', -1, 0, '', 1); - print ''; - print dol_escape_htmltag($s); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Amount HT - if (!empty($arrayfields['f.total_ht']['checked'])) { - print ''.price($obj->total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_ht'; - } - $totalarray['val']['f.total_ht'] += $obj->total_ht; - } - // Amount VAT - if (!empty($arrayfields['f.total_vat']['checked'])) { - print ''.price($obj->total_vat)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_vat'; - } - $totalarray['val']['f.total_vat'] += $obj->total_vat; - } - // Amount LocalTax1 - if (!empty($arrayfields['f.total_localtax1']['checked'])) { - print ''.price($obj->total_localtax1)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_localtax1'; - } - $totalarray['val']['f.total_localtax1'] += $obj->total_localtax1; - } - // Amount LocalTax2 - if (!empty($arrayfields['f.total_localtax2']['checked'])) { - print ''.price($obj->total_localtax2)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_localtax2'; - } - $totalarray['val']['f.total_localtax2'] += $obj->total_localtax2; - } - // Amount TTC - if (!empty($arrayfields['f.total_ttc']['checked'])) { - print ''.price($obj->total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'f.total_ttc'; - } - $totalarray['val']['f.total_ttc'] += $obj->total_ttc; - } - - $userstatic->id = $obj->fk_user_author; - $userstatic->login = $obj->login; - $userstatic->lastname = $obj->lastname; - $userstatic->firstname = $obj->firstname; - $userstatic->email = $obj->user_email; - $userstatic->statut = $obj->user_statut; - $userstatic->entity = $obj->entity; - $userstatic->photo = $obj->photo; - $userstatic->office_phone = $obj->office_phone; - $userstatic->office_fax = $obj->office_fax; - $userstatic->user_mobile = $obj->user_mobile; - $userstatic->job = $obj->job; - $userstatic->gender = $obj->gender; - - // Author - if (!empty($arrayfields['u.login']['checked'])) { - print ''; - if ($userstatic->id) { - print $userstatic->getLoginUrl(-1); - } else { - print ' '; - } - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - if (!empty($arrayfields['dynamount_payed']['checked'])) { - print ''.(!empty($totalpay) ?price($totalpay, 0, $langs) : '').''; // TODO Use a denormalized field - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'totalam'; - } - $totalarray['val']['totalam'] += $totalpay; - } - - if (!empty($arrayfields['rtp']['checked'])) { - print ''.(!empty($remaintopay) ?price($remaintopay, 0, $langs) : ' ').''; // TODO Use a denormalized field - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'rtp'; - } - $totalarray['val']['rtp'] += $remaintopay; - } - - // Currency - if (!empty($arrayfields['f.multicurrency_code']['checked'])) { - print ''.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Currency rate - if (!empty($arrayfields['f.multicurrency_tx']['checked'])) { - print ''; - $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); - print "\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount HT - if (!empty($arrayfields['f.multicurrency_total_ht']['checked'])) { - print ''.price($obj->multicurrency_total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount VAT - if (!empty($arrayfields['f.multicurrency_total_vat']['checked'])) { - print ''.price($obj->multicurrency_total_vat)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount TTC - if (!empty($arrayfields['f.multicurrency_total_ttc']['checked'])) { - print ''.price($obj->multicurrency_total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['multicurrency_dynamount_payed']['checked'])) { - print ''.(!empty($multicurrency_totalpay) ?price($multicurrency_totalpay, 0, $langs) : '').''; // TODO Use a denormalized field - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Pending amount - if (!empty($arrayfields['multicurrency_rtp']['checked'])) { - print ''; - print (!empty($multicurrency_remaintopay) ? price($multicurrency_remaintopay, 0, $langs) : ''); - print ''; // TODO Use a denormalized field - if (!$i) { - $totalarray['nbfield']++; - } - } - - - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, '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; - - // Date creation - if (!empty($arrayfields['f.datec']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['f.tms']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status - if (!empty($arrayfields['f.fk_statut']['checked'])) { - print ''; - print $facturestatic->LibStatut($obj->paye, $obj->fk_statut, 5, $paiement, $obj->type); - print ""; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // 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->facid, $arrayofselected)) { - $selected = 1; + print "\n"; + if (!$i) { + $totalarray['nbfield']++; } - print ''; } - print ''; - } - if (!$i) { - $totalarray['nbfield']++; - } - print "\n"; + // Supplier ref + if (!empty($arrayfields['f.ref_supplier']['checked'])) { + print ''; + print $obj->ref_supplier; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Type + if (!empty($arrayfields['f.type']['checked'])) { + print ''; + print $facturestatic->getLibType(); + print ""; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Label + if (!empty($arrayfields['f.label']['checked'])) { + print ''; + print $obj->label; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date + if (!empty($arrayfields['f.datef']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->datef), 'day'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date limit + if (!empty($arrayfields['f.date_lim_reglement']['checked'])) { + print ''.dol_print_date($datelimit, 'day'); + if ($facturestatic->hasDelay()) { + print img_warning($langs->trans('Alert').' - '.$langs->trans('Late')); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Project + if (!empty($arrayfields['p.ref']['checked'])) { + print ''; + if ($obj->project_id > 0) { + $projectstatic->id = $obj->project_id; + $projectstatic->ref = $obj->project_ref; + $projectstatic->title = $obj->project_label; + print $projectstatic->getNomUrl(1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Third party + if (!empty($arrayfields['s.nom']['checked'])) { + print ''; + print $thirdparty->getNomUrl(1, 'supplier', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) { + print ''; + print $thirdparty->name_alias; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Town + if (!empty($arrayfields['s.town']['checked'])) { + print ''; + print $obj->town; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Zip + if (!empty($arrayfields['s.zip']['checked'])) { + print ''; + print dol_escape_htmltag($obj->zip); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // State + if (!empty($arrayfields['state.nom']['checked'])) { + print "".$obj->state_name."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Country + if (!empty($arrayfields['country.code_iso']['checked'])) { + print ''; + $tmparray = getCountry($obj->fk_pays, 'all'); + print $tmparray['label']; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Type ent + if (!empty($arrayfields['typent.code']['checked'])) { + print ''; + if (empty($typenArray)) { + $typenArray = $formcompany->typent_array(1); + } + print $typenArray[$obj->typent_code]; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Payment condition + if (!empty($arrayfields['f.fk_cond_reglement']['checked'])) { + $s = $form->form_conditions_reglement($_SERVER['PHP_SELF'], $obj->fk_cond_reglement, 'none', 1, '', -1, -1, 1); + print ''; + print dol_escape_htmltag($s); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Payment mode + if (!empty($arrayfields['f.fk_mode_reglement']['checked'])) { + $s = $form->form_modes_reglement($_SERVER['PHP_SELF'], $obj->fk_mode_reglement, 'none', '', -1, 0, '', 1); + print ''; + print dol_escape_htmltag($s); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Amount HT + if (!empty($arrayfields['f.total_ht']['checked'])) { + print ''.price($obj->total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_ht'; + } + $totalarray['val']['f.total_ht'] += $obj->total_ht; + } + // Amount VAT + if (!empty($arrayfields['f.total_vat']['checked'])) { + print ''.price($obj->total_vat)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_vat'; + } + $totalarray['val']['f.total_vat'] += $obj->total_vat; + } + // Amount LocalTax1 + if (!empty($arrayfields['f.total_localtax1']['checked'])) { + print ''.price($obj->total_localtax1)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_localtax1'; + } + $totalarray['val']['f.total_localtax1'] += $obj->total_localtax1; + } + // Amount LocalTax2 + if (!empty($arrayfields['f.total_localtax2']['checked'])) { + print ''.price($obj->total_localtax2)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_localtax2'; + } + $totalarray['val']['f.total_localtax2'] += $obj->total_localtax2; + } + // Amount TTC + if (!empty($arrayfields['f.total_ttc']['checked'])) { + print ''.price($obj->total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'f.total_ttc'; + } + $totalarray['val']['f.total_ttc'] += $obj->total_ttc; + } + + $userstatic->id = $obj->fk_user_author; + $userstatic->login = $obj->login; + $userstatic->lastname = $obj->lastname; + $userstatic->firstname = $obj->firstname; + $userstatic->email = $obj->user_email; + $userstatic->statut = $obj->user_statut; + $userstatic->entity = $obj->entity; + $userstatic->photo = $obj->photo; + $userstatic->office_phone = $obj->office_phone; + $userstatic->office_fax = $obj->office_fax; + $userstatic->user_mobile = $obj->user_mobile; + $userstatic->job = $obj->job; + $userstatic->gender = $obj->gender; + + // Author + if (!empty($arrayfields['u.login']['checked'])) { + print ''; + if ($userstatic->id) { + print $userstatic->getLoginUrl(-1); + } else { + print ' '; + } + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + if (!empty($arrayfields['dynamount_payed']['checked'])) { + print ''.(!empty($totalpay) ?price($totalpay, 0, $langs) : '').''; // TODO Use a denormalized field + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'totalam'; + } + $totalarray['val']['totalam'] += $totalpay; + } + + if (!empty($arrayfields['rtp']['checked'])) { + print ''.(!empty($remaintopay) ?price($remaintopay, 0, $langs) : ' ').''; // TODO Use a denormalized field + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'rtp'; + } + $totalarray['val']['rtp'] += $remaintopay; + } + + // Currency + if (!empty($arrayfields['f.multicurrency_code']['checked'])) { + print ''.$obj->multicurrency_code.' - '.$langs->trans('Currency'.$obj->multicurrency_code)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Currency rate + if (!empty($arrayfields['f.multicurrency_tx']['checked'])) { + print ''; + $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$obj->rowid, $obj->multicurrency_tx, 'none', $obj->multicurrency_code); + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['f.multicurrency_total_ht']['checked'])) { + print ''.price($obj->multicurrency_total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount VAT + if (!empty($arrayfields['f.multicurrency_total_vat']['checked'])) { + print ''.price($obj->multicurrency_total_vat)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount TTC + if (!empty($arrayfields['f.multicurrency_total_ttc']['checked'])) { + print ''.price($obj->multicurrency_total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['multicurrency_dynamount_payed']['checked'])) { + print ''.(!empty($multicurrency_totalpay) ?price($multicurrency_totalpay, 0, $langs) : '').''; // TODO Use a denormalized field + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Pending amount + if (!empty($arrayfields['multicurrency_rtp']['checked'])) { + print ''; + print (!empty($multicurrency_remaintopay) ? price($multicurrency_remaintopay, 0, $langs) : ''); + print ''; // TODO Use a denormalized field + if (!$i) { + $totalarray['nbfield']++; + } + } + + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, '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; + + // Date creation + if (!empty($arrayfields['f.datec']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['f.tms']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status + if (!empty($arrayfields['f.fk_statut']['checked'])) { + print ''; + print $facturestatic->LibStatut($obj->paye, $obj->fk_statut, 5, $paiement, $obj->type); + print ""; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // 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->facid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + + print "\n"; + } $i++; } From 7f96c642f1c610df3f7578bc60bc2da00e079ee8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 14:09:20 +0100 Subject: [PATCH 432/816] Doc --- .../mysql/tables/llx_societe_account.sql | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_societe_account.sql b/htdocs/install/mysql/tables/llx_societe_account.sql index b200d4f3854..56eb4eb1985 100644 --- a/htdocs/install/mysql/tables/llx_societe_account.sql +++ b/htdocs/install/mysql/tables/llx_societe_account.sql @@ -1,4 +1,4 @@ --- Copyright (C) 2016 Laurent Destailleur +-- Copyright (C) 2016-2022 Laurent Destailleur -- -- 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 @@ -19,16 +19,17 @@ CREATE TABLE llx_societe_account( -- BEGIN MODULEBUILDER FIELDS rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, - entity integer DEFAULT 1, - login varchar(128) NOT NULL, + entity integer DEFAULT 1, + + login varchar(128) NOT NULL, -- a login string into website or external system pass_encoding varchar(24), - pass_crypted varchar(128), + pass_crypted varchar(128), -- the hashed password pass_temp varchar(128), -- temporary password when asked for forget password - fk_soc integer, - fk_website integer, -- id of local web site - site varchar(128), -- name of external web site - site_account varchar(128), -- a key to identify the account on external web site - key_account varchar(128), -- the id of third party in external web site (for site_account if site_account defined) + fk_soc integer, -- if entry is linked to a thirdparty + fk_website integer, -- id of local web site (if dk_website is filled, site is empty) + site varchar(128), -- name of external web site (if site is filled, fk_website is empty) + site_account varchar(128), -- a key to identify the account on external web site (for example: 'stripe', 'paypal', 'myextapp') + key_account varchar(128), -- the id of an account in external web site (for site_account if site_account defined. some sites needs both an account name and a login that is different) note_private text, date_last_login datetime, date_previous_login datetime, From 0601db1c7a3d5973c8c84dfa17c270d1256c49ed Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 14:19:12 +0100 Subject: [PATCH 433/816] Doc --- htdocs/societe/societecontact.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/societecontact.php b/htdocs/societe/societecontact.php index 1767973a001..f626139abcb 100644 --- a/htdocs/societe/societecontact.php +++ b/htdocs/societe/societecontact.php @@ -23,7 +23,7 @@ /** * \file htdocs/societe/societecontact.php * \ingroup societe - * \brief Onglet de gestion des contacts additionnel d'une société + * \brief Tab to manage differently contact. Used when unstable feature MAIN_SUPPORT_SHARED_CONTACT_BETWEEN_THIRDPARTIES is on. */ From 7dea3cca50681f5d96d9a942d96166c1a931487c Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 10 Jan 2023 14:40:06 +0100 Subject: [PATCH 434/816] kanban for list of Donnation --- htdocs/don/class/don.class.php | 35 ++++++++++++ htdocs/don/list.php | 97 +++++++++++++++++++++++----------- 2 files changed, 101 insertions(+), 31 deletions(-) diff --git a/htdocs/don/class/don.class.php b/htdocs/don/class/don.class.php index 333f9673175..9c80cb85dad 100644 --- a/htdocs/don/class/don.class.php +++ b/htdocs/don/class/don.class.php @@ -1141,4 +1141,39 @@ class Don extends CommonObject return (float) $this->amount - $sum_amount; } } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'date')) { + $return .= ' | '.$langs->trans("Date").' : '.dol_print_date($this->date).''; + } + if (property_exists($this, 'societe') && !empty($this->societe)) { + $return .= '
'.$langs->trans("Company").' : '.$this->societe.''; + } + if (property_exists($this, 'amount')) { + $return .= '
'.$langs->trans("Amount").' : '.price($this->amount).''; + } + if (method_exists($this, 'LibStatut')) { + $return .= '
'.$this->LibStatut($this->labelStatus, 5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/don/list.php b/htdocs/don/list.php index ac704571daa..469ebbef6a9 100644 --- a/htdocs/don/list.php +++ b/htdocs/don/list.php @@ -42,6 +42,7 @@ $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); $type = GETPOST('type', 'aZ'); +$mode = GETPOST('mode', 'alpha'); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 @@ -153,6 +154,9 @@ if ($resql) { $i = 0; $param = ''; + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -179,6 +183,8 @@ if ($resql) { } $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->rights->don->creer) { $newcardbutton .= dolGetButtonTitle($langs->trans('NewDonation'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/don/card.php?action=create'); } @@ -193,6 +199,9 @@ if ($resql) { print ''; print ''; print ''; + print ''; + + print_barre_liste($langs->trans("Donations"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'object_donation', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -267,44 +276,70 @@ if ($resql) { while ($i < min($num, $limit)) { $objp = $db->fetch_object($resql); + $donationstatic->setVarsFromFetchObj($objp); + $company = new Societe($db); + $result = $company->fetch($objp->socid); + + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban + $donationstatic->amount = $objp->amount; + $donationstatic->date = $objp->datedon; + $donationstatic->labelStatus = $objp->status; + $donationstatic->id = $objp->rowid; + $donationstatic->ref = $objp->rowid; - print ''; - $donationstatic->id = $objp->rowid; - $donationstatic->ref = $objp->rowid; - $donationstatic->lastname = $objp->lastname; - $donationstatic->firstname = $objp->firstname; - print "".$donationstatic->getNomUrl(1).""; - if (!empty($conf->global->DONATION_USE_THIRDPARTIES)) { - $company = new Societe($db); - $result = $company->fetch($objp->socid); if (!empty($objp->socid) && $company->id > 0) { - print "".$company->getNomUrl(1).""; + $donationstatic->societe = $company->getNomUrl(1); + } else { + $donationstatic->societe = $objp->societe; + } + + print $donationstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + print ''; + $donationstatic->id = $objp->rowid; + $donationstatic->ref = $objp->rowid; + $donationstatic->lastname = $objp->lastname; + $donationstatic->firstname = $objp->firstname; + print "".$donationstatic->getNomUrl(1).""; + if (!empty($conf->global->DONATION_USE_THIRDPARTIES)) { + if (!empty($objp->socid) && $company->id > 0) { + print "".$company->getNomUrl(1).""; + } else { + print "".$objp->societe.""; + } } else { print "".$objp->societe.""; } - } else { - print "".$objp->societe.""; - } - print "".$donationstatic->getFullName($langs).""; - print ''.dol_print_date($db->jdate($objp->datedon), 'day').''; - if (isModEnabled('project')) { - print ""; - if ($objp->pid) { - $projectstatic->id = $objp->pid; - $projectstatic->ref = $objp->ref; - $projectstatic->id = $objp->pid; - $projectstatic->public = $objp->public; - $projectstatic->title = $objp->title; - print $projectstatic->getNomUrl(1); - } else { - print ' '; + print "".$donationstatic->getFullName($langs).""; + print ''.dol_print_date($db->jdate($objp->datedon), 'day').''; + if (isModEnabled('project')) { + print ""; + if ($objp->pid) { + $projectstatic->id = $objp->pid; + $projectstatic->ref = $objp->ref; + $projectstatic->id = $objp->pid; + $projectstatic->public = $objp->public; + $projectstatic->title = $objp->title; + print $projectstatic->getNomUrl(1); + } else { + print ' '; + } + print "\n"; } - print "\n"; + print ''.price($objp->amount).''; + print ''.$donationstatic->LibStatut($objp->status, 5).''; + print ''; + print ""; } - print ''.price($objp->amount).''; - print ''.$donationstatic->LibStatut($objp->status, 5).''; - print ''; - print ""; $i++; } print ""; From 8e53013bd97062dbc334032402e563d36ccb6679 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 10 Jan 2023 15:36:14 +0100 Subject: [PATCH 435/816] kanban mode for list of TVA --- htdocs/compta/tva/class/tva.class.php | 35 +++++ htdocs/compta/tva/list.php | 209 ++++++++++++++------------ 2 files changed, 152 insertions(+), 92 deletions(-) diff --git a/htdocs/compta/tva/class/tva.class.php b/htdocs/compta/tva/class/tva.class.php index dffba34d59b..78fb178ff27 100644 --- a/htdocs/compta/tva/class/tva.class.php +++ b/htdocs/compta/tva/class/tva.class.php @@ -906,4 +906,39 @@ class Tva extends CommonObject return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + //$return .= ''; // Can be image + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'amount')) { + $return .= ' | '.$langs->trans("Amount").' : '.price($this->amount).''; + } + if (property_exists($this, 'type_payment')) { + $return .= '
'.$langs->trans("Payement").' : '.$this->type_payment.''; + } + if (property_exists($this, 'datev')) { + $return .= '
'.$langs->trans("DateEnd").' : '.dol_print_date($this->datev).''; + } + if (method_exists($this, 'LibStatut')) { + $return .= '
'.$this->LibStatut($this->paiementtype, 5, $this->alreadypaid).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/compta/tva/list.php b/htdocs/compta/tva/list.php index 1c70cf93c22..e0d5e094c35 100644 --- a/htdocs/compta/tva/list.php +++ b/htdocs/compta/tva/list.php @@ -44,6 +44,7 @@ $massaction = GETPOST('massaction', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); $optioncss = GETPOST('optioncss', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'salestaxeslist'; +$mode = GETPOST('mode', 'alpha'); $search_ref = GETPOST('search_ref', 'alpha'); $search_label = GETPOST('search_label', 'alpha'); @@ -230,6 +231,9 @@ if (!$resql) { $num = $db->num_rows($resql); $param = ''; +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} if (!empty($contextpage) && $contextpage != $_SERVER['PHP_SELF']) { $param .= '&contextpage='.$contextpage; } @@ -317,7 +321,10 @@ $url = DOL_URL_ROOT.'/compta/tva/card.php?action=create'; if (!empty($socid)) { $url .= '&socid='.$socid; } -$newcardbutton = dolGetButtonTitle($langs->trans('NewVATPayment'), '', 'fa fa-plus-circle', $url, '', $user->rights->tax->charges->creer); +$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')); +$newcardbutton .= dolGetButtonTitle($langs->trans('NewVATPayment'), '', 'fa fa-plus-circle', $url, '', $user->rights->tax->charges->creer); print_barre_liste($langs->trans("VATDeclarations"), $page, $_SERVER['PHP_SELF'], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1); $varpage = empty($contextpage) ? $_SERVER['PHP_SELF'] : $contextpage; @@ -461,116 +468,134 @@ while ($i < min($num, $limit)) { $tva_static->id = $obj->rowid; $tva_static->ref = $obj->rowid; $tva_static->label = $obj->label; + $tva_static->paiementtype = $obj->paye; + $tva_static->type_payment = $obj->payment_code; + $tva_static->datev = $obj->datev; + $tva_static->amount = $obj->amount; - print ''; - - // No - if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { - print ''.(($offset * $limit) + $i).''; - if (!$i) { - $totalarray['nbfield']++; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } - } + // Output Kanban - // Ref - if (!empty($arrayfields['t.rowid']['checked'])) { - print ''; - print $tva_static->getNomUrl(1); - $filename = dol_sanitizeFileName($tva_static->ref); - $filedir = $conf->tax->dir_output.'/vat/'.dol_sanitizeFileName($tva_static->ref); - $urlsource = $_SERVER['PHP_SELF'].'?id='.$tva_static->id; - print $formfile->getDocumentsLink($tva_static->element, $filename, $filedir, '', 'valignmiddle paddingleft2imp'); - print ''; - if (!$i) { - $totalarray['nbfield']++; + print $tva_static->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; } - } + } else { + print ''; - // Label - if (!empty($arrayfields['t.label']['checked'])) { - print ''.dol_trunc($obj->label, 40).''; - if (!$i) { - $totalarray['nbfield']++; + // No + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { + print ''.(($offset * $limit) + $i).''; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Date end period - if (!empty($arrayfields['t.datev']['checked'])) { - print ''.dol_print_date($db->jdate($obj->datev), 'day').''; - if (!$i) { - $totalarray['nbfield']++; + // Ref + if (!empty($arrayfields['t.rowid']['checked'])) { + print ''; + print $tva_static->getNomUrl(1); + $filename = dol_sanitizeFileName($tva_static->ref); + $filedir = $conf->tax->dir_output.'/vat/'.dol_sanitizeFileName($tva_static->ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$tva_static->id; + print $formfile->getDocumentsLink($tva_static->element, $filename, $filedir, '', 'valignmiddle paddingleft2imp'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Date payment - /*if (!empty($arrayfields['t.datep']['checked'])) { - print ''.dol_print_date($db->jdate($obj->datep), 'day').''; - if (!$i) $totalarray['nbfield']++; - }*/ - - // Type - if (!empty($arrayfields['t.fk_typepayment']['checked'])) { - print ''; - if (!empty($obj->payment_code)) print $langs->trans("PaymentTypeShort".$obj->payment_code); - print ''; - if (!$i) { - $totalarray['nbfield']++; + // Label + if (!empty($arrayfields['t.label']['checked'])) { + print ''.dol_trunc($obj->label, 40).''; + if (!$i) { + $totalarray['nbfield']++; + } } - } - // Account - if (!empty($arrayfields['t.fk_account']['checked'])) { - print ''; - if ($obj->fk_account > 0) { - $bankstatic->id = $obj->fk_account; - $bankstatic->ref = $obj->bref; - $bankstatic->number = $obj->bnumber; - $bankstatic->iban = $obj->iban; - $bankstatic->bic = $obj->bic; - $bankstatic->currency_code = $langs->trans("Currency".$obj->currency_code); - $bankstatic->account_number = $obj->account_number; - $bankstatic->clos = $obj->clos; - - //$accountingjournal->fetch($obj->fk_accountancy_journal); - //$bankstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); - - $bankstatic->label = $obj->blabel; - print $bankstatic->getNomUrl(1); + // Date end period + if (!empty($arrayfields['t.datev']['checked'])) { + print ''.dol_print_date($db->jdate($obj->datev), 'day').''; + if (!$i) { + $totalarray['nbfield']++; + } } - print ''; - if (!$i) $totalarray['nbfield']++; - } - // Amount - if (!empty($arrayfields['t.amount']['checked'])) { - $total = $total + $obj->amount; - print '' . price($obj->amount) . ''; - if (!$i) { - $totalarray['nbfield']++; - } - $totalarray['pos'][$totalarray['nbfield']] = 'amount'; - if (empty($totalarray['val']['amount'])) { - $totalarray['val']['amount'] = $obj->amount; - } else { - $totalarray['val']['amount'] += $obj->amount; - } - } + // Date payment + /*if (!empty($arrayfields['t.datep']['checked'])) { + print ''.dol_print_date($db->jdate($obj->datep), 'day').''; + if (!$i) $totalarray['nbfield']++; + }*/ - if (!empty($arrayfields['t.status']['checked'])) { - print '' . $tva_static->LibStatut($obj->paye, 5, $obj->alreadypayed) . ''; - if (!$i) { - $totalarray['nbfield']++; + // Type + if (!empty($arrayfields['t.fk_typepayment']['checked'])) { + print ''; + if (!empty($obj->payment_code)) print $langs->trans("PaymentTypeShort".$obj->payment_code); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } } + + // Account + if (!empty($arrayfields['t.fk_account']['checked'])) { + print ''; + if ($obj->fk_account > 0) { + $bankstatic->id = $obj->fk_account; + $bankstatic->ref = $obj->bref; + $bankstatic->number = $obj->bnumber; + $bankstatic->iban = $obj->iban; + $bankstatic->bic = $obj->bic; + $bankstatic->currency_code = $langs->trans("Currency".$obj->currency_code); + $bankstatic->account_number = $obj->account_number; + $bankstatic->clos = $obj->clos; + + //$accountingjournal->fetch($obj->fk_accountancy_journal); + //$bankstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + + $bankstatic->label = $obj->blabel; + print $bankstatic->getNomUrl(1); + } + print ''; + if (!$i) $totalarray['nbfield']++; + } + + // Amount if (!empty($arrayfields['t.amount']['checked'])) { - $totalarray['pos'][$totalarray['nbfield']] = ''; + $total = $total + $obj->amount; + print '' . price($obj->amount) . ''; + if (!$i) { + $totalarray['nbfield']++; + } + $totalarray['pos'][$totalarray['nbfield']] = 'amount'; + if (empty($totalarray['val']['amount'])) { + $totalarray['val']['amount'] = $obj->amount; + } else { + $totalarray['val']['amount'] += $obj->amount; + } } + + if (!empty($arrayfields['t.status']['checked'])) { + print '' . $tva_static->LibStatut($obj->paye, 5, $obj->alreadypayed) . ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!empty($arrayfields['t.amount']['checked'])) { + $totalarray['pos'][$totalarray['nbfield']] = ''; + } + } + + // Buttons + print ''; + + print ''; } - // Buttons - print ''; - - print ''; - $i++; } From 8238d1df97fa3ef054798f3e97baa3e6887b0697 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 10 Jan 2023 16:17:16 +0100 Subject: [PATCH 436/816] kanban mode for list charge social --- .../sociales/class/chargesociales.class.php | 34 ++ htdocs/compta/sociales/list.php | 306 ++++++++++-------- 2 files changed, 200 insertions(+), 140 deletions(-) diff --git a/htdocs/compta/sociales/class/chargesociales.class.php b/htdocs/compta/sociales/class/chargesociales.class.php index 37b3540a0f5..b5e98b3b62e 100644 --- a/htdocs/compta/sociales/class/chargesociales.class.php +++ b/htdocs/compta/sociales/class/chargesociales.class.php @@ -749,4 +749,38 @@ class ChargeSociales extends CommonObject $this->type = 1; $this->type_label = 'Type of social contribution'; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'fk_project') && !empty($this->fk_project)) { + $return .= ' | '.$this->fk_project.''; + } + if (property_exists($this, 'date_ech')) { + $return .= '
'.$langs->trans("DateEnd").':'.dol_print_date($this->date_ech).''; + } + if (property_exists($this, 'amount')) { + $return .= '
'.$langs->trans("Amount").' : '.price($this->amount).''; + } + if (method_exists($this, 'LibStatut')) { + $return .= '
'.$this->LibStatut($this->paye, 5, $this->alreadypaid).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/compta/sociales/list.php b/htdocs/compta/sociales/list.php index f70ed44de0c..18a67ff9e29 100644 --- a/htdocs/compta/sociales/list.php +++ b/htdocs/compta/sociales/list.php @@ -47,6 +47,8 @@ $massaction = GETPOST('massaction', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); $optioncss = GETPOST('optioncss', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'sclist'; +$mode = GETPOST('mode', 'alpha'); + $search_ref = GETPOST('search_ref', 'int'); $search_label = GETPOST('search_label', 'alpha'); @@ -294,6 +296,9 @@ $num = $db->num_rows($resql); $i = 0; $param = ''; +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -367,6 +372,8 @@ if ($search_date_limit_endyear) { } $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->rights->tax->charges->creer) { $newcardbutton .= dolGetButtonTitle($langs->trans('MenuNewSocialContribution'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/compta/sociales/card.php?action=create'); } @@ -382,6 +389,8 @@ print ''; print ''; print ''; print ''; +print ''; + $center = ''; @@ -576,162 +585,179 @@ while ($i < min($num, $limit)) { $chargesociale_static->ref = $obj->rowid; $chargesociale_static->label = $obj->label; $chargesociale_static->type_label = $obj->type_label; + $chargesociale_static->amount = $obj->amount; + $chargesociale_static->paye = $obj->paye; + $chargesociale_static->date_ech = $obj->date_ech; + if (isModEnabled('project')) { $projectstatic->id = $obj->project_id; $projectstatic->ref = $obj->project_ref; $projectstatic->title = $obj->project_label; } - - print ''; - - // Line number - if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { - print ''.(($offset * $limit) + $i).''; - if (!$i) { - $totalarray['nbfield']++; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } - } + // Output Kanban - // Ref - if (!empty($arrayfields['cs.rowid']['checked'])) { - print ''.$chargesociale_static->getNomUrl(1, '20').''; - if (!$i) { - $totalarray['nbfield']++; + $chargesociale_static->fk_project = $projectstatic->getNomUrl(); + print $chargesociale_static->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; } - } + } else { + print ''; - // Label - if (!empty($arrayfields['cs.libelle']['checked'])) { - print ''.dol_escape_htmltag($obj->label).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Type - if (!empty($arrayfields['cs.fk_type']['checked'])) { - $typelabeltoshow = $obj->type_label; - $typelabelpopup = $obj->type_label; - if (isModEnabled('accounting')) { - $typelabelpopup .= ' - '.$langs->trans("AccountancyCode").': '.$obj->type_accountancy_code; - } - print ''.dol_escape_htmltag($typelabeltoshow).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date - if (!empty($arrayfields['cs.date_ech']['checked'])) { - print ''.dol_print_date($db->jdate($obj->date_ech), 'day').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Date end period - if (!empty($arrayfields['cs.periode']['checked'])) { - print ''.dol_print_date($db->jdate($obj->periode), 'day').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Project ref - if (!empty($arrayfields['p.ref']['checked'])) { - print ''; - if ($obj->project_id > 0) { - print $projectstatic->getNomUrl(1); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - if (!empty($arrayfields['cs.fk_user']['checked'])) { - // Employee - print ''; - if (!empty($obj->fk_user)) { - if (!empty($TLoadedUsers[$obj->fk_user])) { - $ustatic = $TLoadedUsers[$obj->fk_user]; - } else { - $ustatic = new User($db); - $ustatic->fetch($obj->fk_user); - $TLoadedUsers[$obj->fk_user] = $ustatic; + // Line number + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { + print ''.(($offset * $limit) + $i).''; + if (!$i) { + $totalarray['nbfield']++; } - print $ustatic->getNomUrl(-1); } - print "\n"; + + // Ref + if (!empty($arrayfields['cs.rowid']['checked'])) { + print ''.$chargesociale_static->getNomUrl(1, '20').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Label + if (!empty($arrayfields['cs.libelle']['checked'])) { + print ''.dol_escape_htmltag($obj->label).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Type + if (!empty($arrayfields['cs.fk_type']['checked'])) { + $typelabeltoshow = $obj->type_label; + $typelabelpopup = $obj->type_label; + if (isModEnabled('accounting')) { + $typelabelpopup .= ' - '.$langs->trans("AccountancyCode").': '.$obj->type_accountancy_code; + } + print ''.dol_escape_htmltag($typelabeltoshow).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date + if (!empty($arrayfields['cs.date_ech']['checked'])) { + print ''.dol_print_date($db->jdate($obj->date_ech), 'day').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date end period + if (!empty($arrayfields['cs.periode']['checked'])) { + print ''.dol_print_date($db->jdate($obj->periode), 'day').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Project ref + if (!empty($arrayfields['p.ref']['checked'])) { + print ''; + if ($obj->project_id > 0) { + print $projectstatic->getNomUrl(1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + if (!empty($arrayfields['cs.fk_user']['checked'])) { + // Employee + print ''; + if (!empty($obj->fk_user)) { + if (!empty($TLoadedUsers[$obj->fk_user])) { + $ustatic = $TLoadedUsers[$obj->fk_user]; + } else { + $ustatic = new User($db); + $ustatic->fetch($obj->fk_user); + $TLoadedUsers[$obj->fk_user] = $ustatic; + } + print $ustatic->getNomUrl(-1); + } + print "\n"; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Type + if (!empty($arrayfields['cs.fk_mode_reglement']['checked'])) { + print 'payment_code)).'">'; + if (!empty($obj->payment_code)) { + print $langs->trans("PaymentTypeShort".$obj->payment_code); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Account + if (!empty($arrayfields['cs.fk_account']['checked'])) { + print ''; + if ($obj->fk_account > 0) { + $bankstatic->id = $obj->fk_account; + $bankstatic->ref = $obj->bref; + $bankstatic->number = $obj->bnumber; + $bankstatic->iban = $obj->iban; + $bankstatic->bic = $obj->bic; + $bankstatic->currency_code = $langs->trans("Currency".$obj->currency_code); + $bankstatic->account_number = $obj->account_number; + $bankstatic->clos = $obj->clos; + + //$accountingjournal->fetch($obj->fk_accountancy_journal); + //$bankstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + + $bankstatic->label = $obj->blabel; + print $bankstatic->getNomUrl(1); + } + print ''; + if (!$i) $totalarray['nbfield']++; + } + + // Amount + if (!empty($arrayfields['cs.amount']['checked'])) { + print ''.price($obj->amount).''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; + } + $totalarray['val']['totalttcfield'] += $obj->amount; + } + + // Status + if (!empty($arrayfields['cs.paye']['checked'])) { + print ''.$chargesociale_static->LibStatut($obj->paye, 5, $obj->alreadypayed).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Buttons + print ''; if (!$i) { $totalarray['nbfield']++; } + + print ''."\n"; } - - // Type - if (!empty($arrayfields['cs.fk_mode_reglement']['checked'])) { - print 'payment_code)).'">'; - if (!empty($obj->payment_code)) { - print $langs->trans("PaymentTypeShort".$obj->payment_code); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Account - if (!empty($arrayfields['cs.fk_account']['checked'])) { - print ''; - if ($obj->fk_account > 0) { - $bankstatic->id = $obj->fk_account; - $bankstatic->ref = $obj->bref; - $bankstatic->number = $obj->bnumber; - $bankstatic->iban = $obj->iban; - $bankstatic->bic = $obj->bic; - $bankstatic->currency_code = $langs->trans("Currency".$obj->currency_code); - $bankstatic->account_number = $obj->account_number; - $bankstatic->clos = $obj->clos; - - //$accountingjournal->fetch($obj->fk_accountancy_journal); - //$bankstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); - - $bankstatic->label = $obj->blabel; - print $bankstatic->getNomUrl(1); - } - print ''; - if (!$i) $totalarray['nbfield']++; - } - - // Amount - if (!empty($arrayfields['cs.amount']['checked'])) { - print ''.price($obj->amount).''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; - } - $totalarray['val']['totalttcfield'] += $obj->amount; - } - - // Status - if (!empty($arrayfields['cs.paye']['checked'])) { - print ''.$chargesociale_static->LibStatut($obj->paye, 5, $obj->alreadypayed).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Buttons - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - - print ''."\n"; - $i++; } From d1e7e527ba63d2edea7b50689e5090dad2b8bfa4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 16:31:12 +0100 Subject: [PATCH 437/816] Debug virtual card --- htdocs/core/class/vcard.class.php | 226 ++++++++++++++++++++---------- htdocs/public/users/view.php | 106 +++++++++----- htdocs/user/virtualcard.php | 8 ++ 3 files changed, 230 insertions(+), 110 deletions(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index 8a62c0aea5e..0e9372360e6 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -117,22 +117,25 @@ class vCard if ($type != "") { $key .= ";".$type; } - $key .= ";".$this->encoding; - $this->properties[$key] = 'VALUE=uri:tel:'.encode($number); + $key .= ";VALUE=uri"; + //$key .= ";".$this->encoding; + $this->properties[$key] = 'tel:'.$number; } /** * mise en forme de la photo * warning NON TESTE ! * - * @param string $type Type 'image/gif' + * @param string $type Type 'image/jpeg' or 'JPEG' * @param string $photo Photo * @return void */ public function setPhoto($type, $photo) { // $type = "GIF" | "JPEG" - $this->properties["PHOTO;MEDIATYPE=$type;ENCODING=BASE64"] = base64_encode($photo); + //$this->properties["PHOTO;MEDIATYPE=$type;ENCODING=BASE64"] = base64_encode($photo); + $this->properties["PHOTO;MEDIATYPE=$type"] = $photo; // must be url of photo + //$this->properties["PHOTO;TYPE=$type;ENCODING=BASE64"] = base64_encode($photo); // must be content of image } /** @@ -152,13 +155,14 @@ class vCard * @param string $family Family name * @param string $first First name * @param string $additional Additional (e.g. second name, nick name) - * @param string $prefix Prefix (e.g. "Mr.", "Ms.", "Prof.") + * @param string $prefix Title prefix (e.g. "Mr.", "Ms.", "Prof.") * @param string $suffix Suffix (e.g. "sen." for senior, "jun." for junior) * @return void */ public function setName($family = "", $first = "", $additional = "", $prefix = "", $suffix = "") { - $this->properties["N;".$this->encoding] = encode($family).";".encode($first).";".encode($additional).";".encode($prefix).";".encode($suffix); + //$this->properties["N;".$this->encoding] = encode($family).";".encode($first).";".encode($additional).";".encode($prefix).";".encode($suffix); + $this->properties["N"] = encode($family).";".encode($first).";".encode($additional).";".encode($prefix).";".encode($suffix); $this->filename = "$first%20$family.vcf"; if (empty($this->properties["FN"])) { $this->setFormattedName(trim("$prefix $first $additional $family $suffix")); @@ -173,8 +177,9 @@ class vCard */ public function setBirthday($date) { - // $date format is YYYY-MM-DD - RFC 2425 and RFC 2426 - $this->properties["BDAY"] = dol_print_date($date, 'dayrfc'); + // $date format is YYYY-MM-DD - RFC 2425 and RFC 2426 for vcard v3 + // $date format is YYYYMMDD or ISO8601 for vcard v4 + $this->properties["BDAY"] = dol_print_date($date, 'dayxcard'); } /** @@ -309,7 +314,7 @@ class vCard */ public function setProdId($prodid) { - $this->properties["PRODID;".$this->encoding] = encode($prodid); + $this->properties["PRODID"] = encode($prodid); } @@ -321,7 +326,7 @@ class vCard */ public function setUID($uid) { - $this->properties["UID;".$this->encoding] = encode($uid); + $this->properties["UID"] = encode($uid); } @@ -355,7 +360,7 @@ class vCard foreach ($this->properties as $key => $value) { $text .= $key.":".$value."\r\n"; } - $text .= "REV:".date("Y-m-d")."T".date("H:i:s")."Z\r\n"; + $text .= "REV:".date("Ymd")."T".date("His")."Z\r\n"; //$text .= "MAILER: Dolibarr\r\n"; $text .= "END:VCARD\r\n"; return $text; @@ -374,12 +379,13 @@ class vCard /** * Return a VCARD string * - * @param Object $object Object (User, Contact) - * @param Societe $company Company - * @param Translate $langs Lang object - * @return string String + * @param Object $object Object (User or Contact) + * @param Societe|null $company Company. May be null + * @param Translate $langs Lang object + * @param string $urlphoto Full public URL of photo + * @return string String */ - public function buildVCardString($object, $company, $langs) + public function buildVCardString($object, $company, $langs, $urlphoto = '') { global $dolibarr_main_instance_unique_id; @@ -389,70 +395,136 @@ class vCard $this->setName($object->lastname, $object->firstname, "", $object->civility_code, ""); $this->setFormattedName($object->getFullName($langs, 1)); - $this->setPhoneNumber($object->office_phone, "TYPE=WORK,VOICE"); - $this->setPhoneNumber($object->personal_mobile, "TYPE=HOME,VOICE"); - $this->setPhoneNumber($object->user_mobile, "TYPE=CELL,VOICE"); - $this->setPhoneNumber($object->office_fax, "TYPE=WORK,FAX"); - - $country = $object->country_code ? $object->country : ''; - - $this->setAddress("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=WORK"); - //$this->setLabel("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=WORK"); - - $this->setEmail($object->email, "TYPE=WORK"); - $this->setNote($object->note_public); - $this->setTitle($object->job); - - // For user, type=home - // For contact, this is not defined - $this->setURL($object->url, "TYPE=HOME"); - - if (is_object($company)) { - $this->setURL($company->url, "TYPE=WORK"); - - if (!$object->office_phone) { - $this->setPhoneNumber($company->phone, "TYPE=WORK,VOICE"); - } - if (!$object->office_fax) { - $this->setPhoneNumber($company->fax, "TYPE=WORK,FAX"); - } - if (!$object->zip) { - $this->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, "TYPE=WORK"); - } - - // when company e-mail is empty, use only user e-mail - if (empty(trim($company->email))) { - // was set before, don't set twice - } elseif (empty(trim($object->email))) { - // when user e-mail is empty, use only company e-mail - $this->setEmail($company->email, "TYPE=WORK"); - } else { - $tmpuser2 = explode("@", trim($object->email)); - $tmpcompany = explode("@", trim($company->email)); - - if (strtolower(end($tmpuser2)) == strtolower(end($tmpcompany))) { - // when e-mail domain of user and company are the same, use user e-mail at first (and company e-mail at second) - $this->setEmail($object->email, "TYPE=WORK"); - - // support by Microsoft Outlook (2019 and possible earlier) - $this->setEmail($company->email, ''); - } else { - // when e-mail of user and company complete different use company e-mail at first (and user e-mail at second) - $this->setEmail($company->email, "TYPE=WORK"); - - // support by Microsoft Outlook (2019 and possible earlier) - $this->setEmail($object->email, ''); - } - } - - // Si user lie a un tiers non de type "particulier" - if ($company->typent_code != 'TE_PRIVATE') { - $this->setOrg($company->name); + if ($urlphoto) { + $mimetype = dol_mimetype($urlphoto); + if ($mimetype) { + $this->setPhoto($mimetype, $urlphoto); } } - // Personal informations - $this->setPhoneNumber($object->personal_mobile, "TYPE=HOME,VOICE"); + if ($object->office_phone) { + $this->setPhoneNumber($object->office_phone, "TYPE=WORK,VOICE"); + } + /* disabled + if ($object->personal_mobile) { + $this->setPhoneNumber($object->personal_mobile, "TYPE=CELL,VOICE"); + }*/ + if ($object->user_mobile) { + $this->setPhoneNumber($object->user_mobile, "TYPE=CELL,VOICE"); + } + if ($object->office_fax) { + $this->setPhoneNumber($object->office_fax, "TYPE=WORK,FAX"); + } + + if (!empty($object->socialnetworks)) { + foreach ($object->socialnetworks as $key => $val) { + $urlsn = ''; + if ($key == 'linkedin') { + if (!preg_match('/^http/', $val)) { + $urlsn = 'https://www.'.$key.'.com/company/'.urlencode($val); + } else { + $urlsn = $val; + } + } elseif ($key == 'youtube') { + if (!preg_match('/^http/', $val)) { + $urlsn = 'https://www.'.$key.'.com/user/'.urlencode($val); + } else { + $urlsn = $val; + } + } else { + if (!preg_match('/^http/', $val)) { + $urlsn = 'https://www.'.$key.'.com/'.urlencode($val); + } else { + $urlsn = $val; + } + } + if ($urlsn) { + $this->properties["socialProfile;type=".$key] = $urlsn; + } + } + } + + $country = $object->country_code ? $object->country : ''; + + if ($object->address || $object->town || $object->state || $object->zip || $object->country) { + $this->setAddress("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=WORK"); + //$this->setLabel("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=HOME"); + } + + if ($object->email) { + $this->setEmail($object->email, "TYPE=WORK"); + } + /* disabled + if ($object->personal_email) { + $this->setEmail($object->personal_email, "TYPE=HOME"); + } */ + if ($object->note_public) { + $this->setNote($object->note_public); + } + if ($object->job) { + $this->setTitle($object->job); + } + + // For user, type=home + // For contact, $object->url is not defined + if ($object->url) { + $this->setURL($object->url, ""); + } + + if (is_object($company)) { + // Si user linked to a thirdparty and not a physical people + if ($company->typent_code != 'TE_PRIVATE') { + $this->setOrg($company->name); + } + + $this->setURL($company->url, ""); + + if ($company->phone && $company->phone != $object->office_phone) { + $this->setPhoneNumber($company->phone, "TYPE=WORK,VOICE"); + } + if ($company->fax && $company->fax != $object->office_fax) { + $this->setPhoneNumber($company->fax, "TYPE=WORK,FAX"); + } + if ($company->address || $company->town || $company->state || $company->zip || $company->country) { + $this->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, "TYPE=WORK"); + } + + if ($company->email && $company->email != $object->email) { + $this->setEmail($company->email, "TYPE=WORK"); + } + + /* + if (!empty($company->socialnetworks)) { + foreach ($company->socialnetworks as $key => $val) { + $urlsn = ''; + if ($key == 'linkedin') { + if (!preg_match('/^http/', $val)) { + $urlsn = 'https://www.'.$key.'.com/company/'.urlencode($val); + } else { + $urlsn = $val; + } + } elseif ($key == 'youtube') { + if (!preg_match('/^http/', $val)) { + $urlsn = 'https://www.'.$key.'.com/user/'.urlencode($val); + } else { + $urlsn = $val; + } + } else { + if (!preg_match('/^http/', $val)) { + $urlsn = 'https://www.'.$key.'.com/'.urlencode($val); + } else { + $urlsn = $val; + } + } + if ($urlsn) { + $this->properties["socialProfile;type=".$key] = $urlsn; + } + } + } + */ + } + + // Birthday if ($object->birth) { $this->setBirthday($object->birth); } diff --git a/htdocs/public/users/view.php b/htdocs/public/users/view.php index ba1a6dd0908..ec5f53377c2 100644 --- a/htdocs/public/users/view.php +++ b/htdocs/public/users/view.php @@ -91,13 +91,79 @@ if ($cancel) { */ $form = new Form($db); +$v = new vCard(); + $company = $mysoc; -if ($mode == 'vcard') { - // We create VCard - $v = new vCard(); +$modulepart = 'userphotopublic'; +$dir = $conf->user->dir_output; - $output = $v->buildVCardString($object, $company, $langs); +// Show logo (search order: logo defined by ONLINE_SIGN_LOGO_suffix, then ONLINE_SIGN_LOGO_, then small company logo, large company logo, theme logo, common logo) +// Define logo and logosmall +$logo = ''; +$logosmall = ''; +if (!empty($object->photo)) { + if (dolIsAllowedForPreview($object->photo)) { + $logosmall = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.getImageFileNameForSize($object->photo, '_small'); + $logo = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.$object->photo; + //$originalfile = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.$object->photo; + } +} +//print ''."\n"; +// Define urllogo +$urllogo = ''; +$urllogofull = ''; +if (!empty($logosmall) && is_readable($dir.'/'.$logosmall)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logosmall); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logosmall); +} elseif (!empty($logo) && is_readable($dir.'/'.$logo)) { + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logo); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logo); +} + +// Clean data we don't want on public page +if (getDolUserInt('USER_PUBLIC_HIDE_PHOTO', 0, $object)) { + $logo = ''; + $logosmall = ''; + $urllogo = ''; + $urllogofull = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_JOBPOSITION', 0, $object)) { + $object->job = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_EMAIL', 0, $object)) { + $object->email = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_EMAIL', 0, $object)) { + $object->job = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_OFFICE_PHONE', 0, $object)) { + $object->office_phone = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_OFFICE_FAX', 0, $object)) { + $object->office_fax = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_USER_MOBILE', 0, $object)) { + $object->user_mobile = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_BIRTH', 0, $object)) { + $object->birth = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_SOCIALNETWORKS', 0, $object)) { + $object->socialnetworks = ''; +} +if (getDolUserInt('USER_PUBLIC_HIDE_COMPANY', 0, $object)) { + $company = null; +} + + +// Output vcard +if ($mode == 'vcard') { + // Reset data no selected for public VCard + + + // We create VCard + $output = $v->buildVCardString($object, $company, $langs, $urllogofull); $filename = trim(urldecode($v->getFileName())); // "Nom prenom.vcf" $filenameurlencoded = dol_sanitizeFileName(urlencode($filename)); @@ -147,34 +213,6 @@ print ''; print "\n"; print ''."\n"; -$modulepart = 'userphotopublic'; -$imagesize = 'small'; -$dir = $conf->user->dir_output; -$email = $object->email; - -// Show logo (search order: logo defined by ONLINE_SIGN_LOGO_suffix, then ONLINE_SIGN_LOGO_, then small company logo, large company logo, theme logo, common logo) -// Define logo and logosmall -$logo = ''; -$logosmall = ''; -if (!empty($object->photo)) { - if (dolIsAllowedForPreview($object->photo)) { - $logosmall = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.getImageFileNameForSize($object->photo, '_small'); - $logo = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.$object->photo; - //$originalfile = get_exdir(0, 0, 0, 0, $object, 'user').'photos/'.$object->photo; - } -} -//print ''."\n"; -// Define urllogo -$urllogo = ''; -$urllogofull = ''; -if (!empty($logosmall) && is_readable($conf->user->dir_output.'/'.$logosmall)) { - $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logosmall); - $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logosmall); -} elseif (!empty($logo) && is_readable($conf->user->dir_output.'/'.$logo)) { - $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logo); - $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logo); -} - // Output html code for logo print '
'; print '
'; @@ -211,9 +249,11 @@ $socialnetworksdict = getArrayOfSocialNetworks(); // Show barcode $showbarcode = GETPOST('nobarcode') ? 0 : 1; if ($showbarcode) { + $qrcodecontent = $output = $v->buildVCardString($object, $company, $langs); + print '
'; print '
'; - print ''; + print ''; print '
'; print '
'; } diff --git a/htdocs/user/virtualcard.php b/htdocs/user/virtualcard.php index 8d023c2c9a9..c2de7e17b06 100644 --- a/htdocs/user/virtualcard.php +++ b/htdocs/user/virtualcard.php @@ -73,6 +73,7 @@ if ($action == 'update') { $tmparray['USER_PUBLIC_HIDE_OFFICE_PHONE'] = (GETPOST('USER_PUBLIC_HIDE_OFFICE_PHONE') ? 1 : 0); $tmparray['USER_PUBLIC_HIDE_OFFICE_FAX'] = (GETPOST('USER_PUBLIC_HIDE_OFFICE_FAX') ? 1 : 0); $tmparray['USER_PUBLIC_HIDE_USER_MOBILE'] = (GETPOST('USER_PUBLIC_HIDE_USER_MOBILE') ? 1 : 0); + $tmparray['USER_PUBLIC_HIDE_BIRTH'] = (GETPOST('USER_PUBLIC_HIDE_BIRTH') ? 1 : 0); $tmparray['USER_PUBLIC_HIDE_SOCIALNETWORKS'] = (GETPOST('USER_PUBLIC_HIDE_SOCIALNETWORKS') ? 1 : 0); $tmparray['USER_PUBLIC_HIDE_COMPANY'] = (GETPOST('USER_PUBLIC_HIDE_COMPANY') ? 1 : 0); $tmparray['USER_PUBLIC_MORE'] = (GETPOST('USER_PUBLIC_MORE') ? GETPOST('USER_PUBLIC_MORE') : ''); @@ -230,6 +231,13 @@ if (getDolUserInt('USER_ENABLE_PUBLIC', 0, $object)) { print $form->selectyesno("USER_PUBLIC_HIDE_USER_MOBILE", (getDolUserInt('USER_PUBLIC_HIDE_USER_MOBILE', 0, $object) ? getDolUserInt('USER_PUBLIC_HIDE_USER_MOBILE', 0, $object) : 0), 1); print "\n"; + // User mobile + print ''; + print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("Birthdate")); + print ''; + print $form->selectyesno("USER_PUBLIC_HIDE_BIRTH", (getDolUserInt('USER_PUBLIC_HIDE_BIRTH', 0, $object) ? getDolUserInt('USER_PUBLIC_HIDE_BIRTH', 0, $object) : 0), 1); + print "\n"; + // Social networks print ''; print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("SocialNetworks")); From ac5a07fee803d9f9712f7c2f76c38a6e244f3ea8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 17:27:19 +0100 Subject: [PATCH 438/816] Debug v17 --- htdocs/comm/propal/card.php | 2 +- htdocs/commande/card.php | 2 +- htdocs/compta/facture/card.php | 2 +- htdocs/supplier_proposal/card.php | 2 -- .../supplier_proposal/class/supplier_proposal.class.php | 9 +++++++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 7953691f11b..84e4e1bfb5e 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -938,7 +938,7 @@ if (empty($reshook)) { $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09'); if ($prod_entry_mode == 'free') { $idprod = 0; - $tva_tx = (GETPOST('tva_tx', 'alpha') ? price2num(preg_replace('/\s*\(.*\)/', '', GETPOST('tva_tx', 'alpha'))) : 0); + $tva_tx = (GETPOSTISSET('tva_tx') ? GETPOST('tva_tx', 'alpha') : 0); } else { $idprod = GETPOST('idprod', 'int'); $tva_tx = ''; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 135c6fc9ab9..0510f089045 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -676,7 +676,7 @@ if (empty($reshook)) { $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09'); if ($prod_entry_mode == 'free') { $idprod = 0; - $tva_tx = (GETPOST('tva_tx', 'alpha') ? price2num(preg_replace('/\s*\(.*\)/', '', GETPOST('tva_tx', 'alpha'))) : 0); + $tva_tx = (GETPOSTISSET('tva_tx') ? GETPOST('tva_tx', 'alpha') : 0); } else { $idprod = GETPOST('idprod', 'int'); $tva_tx = ''; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index d8e235193b5..287d99fc1fb 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2038,7 +2038,7 @@ if (empty($reshook)) { $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09'); if ($prod_entry_mode == 'free') { $idprod = 0; - $tva_tx = (GETPOST('tva_tx', 'alpha') ? price2num(preg_replace('/\s*\(.*\)/', '', GETPOST('tva_tx', 'alpha'))) : 0); + $tva_tx = (GETPOSTISSET('tva_tx') ? GETPOST('tva_tx', 'alpha') : 0); } else { $idprod = GETPOST('idprod', 'int'); $tva_tx = ''; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 4b898a75645..c9dc776c9c5 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -591,10 +591,8 @@ if (empty($reshook)) { $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09'); if ($prod_entry_mode == 'free') { $idprod = 0; - $tva_tx = (GETPOST('tva_tx', 'alpha') ? price2num(preg_replace('/\s*\(.*\)/', '', GETPOST('tva_tx', 'alpha'))) : 0); } else { $idprod = GETPOST('idprod', 'int'); - $tva_tx = ''; } $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); // Can be '1.2' or '1.2 (CODE)' diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 1f95e3de5fd..16211e7a027 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -2584,7 +2584,7 @@ class SupplierProposal extends CommonObject // For other object, here we call fetch_lines. But fetch_lines does not exists on supplier proposal $sql = 'SELECT pt.rowid, pt.label as custom_label, pt.description, pt.fk_product, pt.fk_remise_except,'; - $sql .= ' pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, pt.info_bits,'; + $sql .= ' pt.qty, pt.tva_tx, pt.vat_src_code, pt.remise_percent, pt.subprice, pt.info_bits,'; $sql .= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code, pt.localtax1_tx, pt.localtax2_tx,'; $sql .= ' pt.product_type, pt.rang, pt.fk_parent_line,'; $sql .= ' p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid,'; @@ -2620,6 +2620,7 @@ class SupplierProposal extends CommonObject $this->lines[$i]->fk_remise_except = $obj->fk_remise_except; $this->lines[$i]->remise_percent = $obj->remise_percent; $this->lines[$i]->tva_tx = $obj->tva_tx; + $this->lines[$i]->vat_src_code = $obj->vat_src_code; $this->lines[$i]->info_bits = $obj->info_bits; $this->lines[$i]->total_ht = $obj->total_ht; $this->lines[$i]->total_tva = $obj->total_tva; @@ -2988,6 +2989,9 @@ class SupplierProposalLine extends CommonObjectLine if (empty($this->tva_tx)) { $this->tva_tx = 0; } + if (empty($this->vat_src_code)) { + $this->vat_src_code = ''; + } if (empty($this->localtax1_tx)) { $this->localtax1_tx = 0; } @@ -3056,7 +3060,7 @@ class SupplierProposalLine extends CommonObjectLine $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'supplier_proposaldet'; $sql .= ' (fk_supplier_proposal, fk_parent_line, label, description, fk_product, product_type,'; $sql .= ' date_start, date_end,'; - $sql .= ' fk_remise_except, qty, tva_tx, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,'; + $sql .= ' fk_remise_except, qty, tva_tx, vat_src_code, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type,'; $sql .= ' subprice, remise_percent, '; $sql .= ' info_bits, '; $sql .= ' total_ht, total_tva, total_localtax1, total_localtax2, total_ttc, fk_product_fournisseur_price, buy_price_ht, special_code, rang,'; @@ -3073,6 +3077,7 @@ class SupplierProposalLine extends CommonObjectLine $sql .= " ".($this->fk_remise_except ? ((int) $this->fk_remise_except) : "null").","; $sql .= " ".price2num($this->qty, 'MS').","; $sql .= " ".price2num($this->tva_tx).","; + $sql .= " '".$this->db->escape($this->vat_src_code)."',"; $sql .= " ".price2num($this->localtax1_tx).","; $sql .= " ".price2num($this->localtax2_tx).","; $sql .= " '".$this->db->escape($this->localtax1_type)."',"; From 83bb95f318c5039eaa584b76e2d853b76b7d617b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 18:50:01 +0100 Subject: [PATCH 439/816] Fix warning php8 --- htdocs/core/modules/propale/doc/pdf_azur.modules.php | 12 ++++++++++-- 1 file changed, 10 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 eac6e0261ee..5f637373507 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -675,10 +675,18 @@ class pdf_azur extends ModelePDFPropales // retrieve global local tax if ($localtax1_type && $localtax1ligne != 0) { - $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; + if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) { + $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne; + } else { + $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; + } } if ($localtax2_type && $localtax2ligne != 0) { - $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; + if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) { + $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne; + } else { + $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; + } } if (($object->lines[$i]->info_bits & 0x01) == 0x01) { From 153a91335e69ca058ff77bf2f3c9ab9074d28c26 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 10 Jan 2023 20:05:40 +0100 Subject: [PATCH 440/816] Update ChangeLog --- ChangeLog | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ec9fb4525a..f752894b4d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -96,18 +96,18 @@ NEW: can sort and preselected best supplier price NEW: Can use products categories to make inventory NEW: Change filter type on tickets list into a multiselect combo NEW: conf TIMESPENT_ALWAYS_UPDATE_THM, when it's on we always check current thm of user to update it in task time line -NEW: constant PROPAL_NEW_AS_SIGNED NEW: show date delivery planned on orders linked to company and product NEW: Default values in extrafields are not more limited to 255 char. NEW: display currency in takepos menu NEW: Enable online signature for interventions NEW: Encrypt all sensitive constants in llx_const -NEW: extrafield price with currency NEW: filter on reception dates (from / to) in cheque paiement card NEW: Contracts: Default template of contract is not mandatory NEW: Contracts: Manage Position (Rank) on Contract Lines NEW: EMail-Collector: add IMAP port setting NEW: EMail-Collector: add a button "Test collect" +NEW: Extrafields: field price with currency +NEW: Extrafields: support IP type in extrafields NEW: Members: default_lang for members NEW: Members: Table of membership types NEW: Members: add free membership amounts at the membership type level @@ -127,21 +127,17 @@ NEW: Website: can switch status of website and page from the website toolbar NEW: Website: Templates of websites are now directories and not zip into core repo NEW: Website: add 4 other templates in website module NEW: If we select another view list mode, we keep it -NEW: Init module bookcal NEW: Introduce dolEncrypt and dolDecrypt to be able to encrypt data in db NEW: Invoice - Add french mention on pdf when vat debit option is on NEW: invoice export : add accounting affectation NEW: label on products categories filter NEW: The link "add to bookmark" is always on top in the bookmark popup -NEW: MAIN_SEARCH_CATEGORY_PRODUCT_ON_LISTS const to show category customer filter NEW: Make module WebservicesClient deprecated. Use module WebHook instead. NEW: manage no email with thirdparties (better for GDPR) NEW: Manage VAT on all lines on purchases cycle NEW: manage virtual stock at a future date NEW: On a bank reconciled line, we can modify the bank receipt NEW: On a form to send an email, we show all emails of all contacts of object -NEW: Option PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT showing wh on PDF -NEW: Option PRODUIT_DESC_IN_FORM accept (desktop only or +smartphone) NEW: Page for mass stock transfer can be used with no source stock NEW: parent company column and filter in invoice and order list NEW: Add show "Sales rep" option for PDF @@ -168,19 +164,25 @@ NEW: skip accept/refuse process for proposals (option PROPAL_SKIP_ACCEPT_REFUSE) NEW: experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP) NEW: can substitue project title in mail template NEW: Supplier order list - Add column private and public note -NEW: Support IP type in extrafields NEW: The purge of files can purge only if older than a number of seconds NEW: Update ActionComm type_code on email message ticket NEW: VAT - Admin - Add information on deadline day for submission of VAT declaration NEW: expand/collapse permissions on user permission page NEW: Add the target to select attendees of event for emailings + Option / Const for System: +NEW: Option PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT showing warehouse on PDF +NEW: Option PRODUIT_DESC_IN_FORM accept (desktop only or +smartphone) +NEW: MAIN_SEARCH_CATEGORY_PRODUCT_ON_LISTS const to show category customer filter +NEW: constant PROPAL_NEW_AS_SIGNED + Localisation: NEW: adding JAPAN Chart-of-Account and regions/departments NEW: adding NIF verification for Algeria Modules NEW: Experimental module Asset +NEW: Init module bookcal For developers or integrators: @@ -190,20 +192,26 @@ NEW: ModuleBuilder can generate code of class from an existing SQL table NEW: #20912 Add trigger to record the event of sending an email from a project NEW: #21750 Added "Get lines and Post lines from BOM" at the REST Service NEW: #22370 Modulebuilder supports 'alwayseditable' (like extrafields) -NEW: Removed completely the need for the library adodbtime -NEW: hook on agenda pages -NEW: hook to complete payment in TakePOS -NEW: hook "changeHelpURL" to modify target of the help button -NEW: hook formConfirm on action comm card -NEW: hook to modify supplier product html select -NEW: Add new hook for show virtual stock details on product stock card -NEW: Add new hooks for actioncomm NEW: conf->global->SYSLOG_FILE_ONEPERSESSION accept a string -NEW: translate for contact type API, setup/ticket API, shipping method API NEW: All ajax pages have now a top_httphead() -NEW: support multilang in Civilities API + + API: NEW: Add API for the partnership module NEW: Add "Get lines and Post lines from BOM" in the API +NEW: translate for contact type API, setup/ticket API, shipping method API +NEW: support multilang in Civilities API + + Hooks: +NEW: Actioncomm - add new hooks for actioncomm +NEW: Actioncomm - hook formConfirm on action comm card +NEW: Agenda - hook on agenda pages +NEW: Help - hook "changeHelpURL" to modify target of the help button +NEW: Product - add hook to show virtual stock details on product stock card +NEW: Product - add hook to modify supplier product html select +NEW: TakePOS - add hook to complete payment in TakePOS + + +NEW: Removed completely the need for the library adodbtime NEW: Replace fk_categories_product with categories_product in inventory NEW: Rewrite of SQL request. Removed the join on category (for filter on categ), replaced with a EXISTS/NOT From f52f18fb95da1558f516e72d0d035227418e18f2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 21:27:56 +0100 Subject: [PATCH 441/816] Fix picto edit must not be visilbe in edit mode --- htdocs/core/tpl/objectline_title.tpl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/objectline_title.tpl.php b/htdocs/core/tpl/objectline_title.tpl.php index 7fe63613ea1..4640d710705 100644 --- a/htdocs/core/tpl/objectline_title.tpl.php +++ b/htdocs/core/tpl/objectline_title.tpl.php @@ -71,7 +71,7 @@ if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) || !empty($conf->global->FA if (in_array($object->element, array('propal', 'commande', 'facture', 'supplier_proposal', 'order_supplier', 'invoice_supplier')) && $object->status == $object::STATUS_DRAFT) { global $mysoc; - if (empty($disableedit)) { + if (empty($disableedit) && GETPOST('mode', 'aZ09') != 'vatforalllines') { print 'id.'">'.img_edit($langs->trans("UpdateForAllLines"), 0, 'class="clickvatforalllines opacitymedium paddingleft cursorpointer"').''; } //print ''; @@ -111,7 +111,7 @@ print $langs->trans('ReductionShort'); if (in_array($object->element, array('propal', 'commande', 'facture')) && $object->status == $object::STATUS_DRAFT) { global $mysoc; - if (empty($disableedit)) { + if (empty($disableedit) && GETPOST('mode', 'aZ09') != 'remiseforalllines') { print 'id.'">'.img_edit($langs->trans("UpdateForAllLines"), 0, 'class="clickvatforalllines opacitymedium paddingleft cursorpointer"').''; } //print ''; From 2f2c710a33b116f7ef0b86a73d062fde8f468e02 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 21:34:59 +0100 Subject: [PATCH 442/816] Fix reposition when adding a contract line --- htdocs/contrat/card.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 79897cdc16d..12f53b49390 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -2046,11 +2046,12 @@ if ($action == 'create') { $dateSelector = 1; print "\n"; - print ' + print ' + '; print '
'; From 3769861a8adb54fd99306bf3f55f0508a4e3a921 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 21:46:11 +0100 Subject: [PATCH 443/816] NEW VAT can be modified during add of line --- htdocs/comm/propal/card.php | 27 +++++++------ htdocs/commande/card.php | 8 ++-- htdocs/compta/facture/card.php | 9 ++--- htdocs/contrat/card.php | 11 +++--- htdocs/core/class/html.form.class.php | 7 +--- htdocs/core/tpl/objectline_create.tpl.php | 35 ++++++++++++++++- htdocs/product/ajax/products.php | 48 ++++++++++++++--------- 7 files changed, 91 insertions(+), 54 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 5fb464a6e8e..c2dcd19eb9b 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -938,12 +938,12 @@ if (empty($reshook)) { $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09'); if ($prod_entry_mode == 'free') { $idprod = 0; - $tva_tx = (GETPOST('tva_tx', 'alpha') ? price2num(preg_replace('/\s*\(.*\)/', '', GETPOST('tva_tx', 'alpha'))) : 0); } else { $idprod = GETPOST('idprod', 'int'); - $tva_tx = ''; } + $tva_tx = GETPOST('tva_tx', 'alpha'); + $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2); $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0); if (empty($remise_percent)) { @@ -992,6 +992,8 @@ if (empty($reshook)) { if (!$error && ($qty >= 0) && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) { $pu_ht = 0; $pu_ttc = 0; + $pu_ht_devise = 0; + $pu_ttc_devise = 0; $price_min = 0; $price_min_ttc = 0; $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT'); @@ -1002,7 +1004,6 @@ if (empty($reshook)) { // Ecrase $pu par celui du produit // Ecrase $desc par celui du produit - // Ecrase $tva_tx par celui du produit // Replaces $fk_unit with the product unit if (!empty($idprod) && $idprod > 0) { $prod = new Product($db); @@ -1011,11 +1012,11 @@ if (empty($reshook)) { $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : ''); // Update if prices fields are defined - $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); + /*$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id); if (empty($tva_tx)) { $tva_npr = 0; - } + }*/ // Price unique per product $pu_ht = $prod->price; @@ -1056,14 +1057,14 @@ if (empty($reshook)) { $price_min = price($prodcustprice->lines[0]->price_min); $price_min_ttc = price($prodcustprice->lines[0]->price_min_ttc); $price_base_type = $prodcustprice->lines[0]->price_base_type; - $tva_tx = ($prodcustprice->lines[0]->default_vat_code ? $prodcustprice->lines[0]->tva_tx.' ('.$prodcustprice->lines[0]->default_vat_code.' )' : $prodcustprice->lines[0]->tva_tx); + /*$tva_tx = ($prodcustprice->lines[0]->default_vat_code ? $prodcustprice->lines[0]->tva_tx.' ('.$prodcustprice->lines[0]->default_vat_code.' )' : $prodcustprice->lines[0]->tva_tx); if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) { $tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')'; } $tva_npr = $prodcustprice->lines[0]->recuperableonly; if (empty($tva_tx)) { $tva_npr = 0; - } + }*/ } } } elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) { @@ -1114,12 +1115,12 @@ if (empty($reshook)) { $tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx)); // Set unit price to use - if (!empty($price_ht) || $price_ht === '0') { + if (!empty($price_ht) || (string) $price_ht === '0') { $pu_ht = price2num($price_ht, 'MU'); - $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU'); - } elseif (!empty($price_ttc) || $price_ttc === '0') { + $pu_ttc = price2num($pu_ht * (1 + ((float) $tmpvat / 100)), 'MU'); + } elseif (!empty($price_ttc) || (string) $price_ttc === '0') { $pu_ttc = price2num($price_ttc, 'MU'); - $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU'); + $pu_ht = price2num($pu_ttc / (1 + ((float) $tmpvat / 100)), 'MU'); } elseif ($tmpvat != $tmpprodvat) { // Is this still used ? if ($price_base_type != 'HT') { @@ -1416,12 +1417,12 @@ if (empty($reshook)) { //var_dump(price2num($price_min_ttc)); var_dump(price2num($pu_ttc)); var_dump($remise_percent);exit; if ($usermustrespectpricemin) { - if ($pu_equivalent && $price_min && ((price2num($pu_equivalent) * (1 - $remise_percent / 100)) < price2num($price_min))) { + if ($pu_equivalent && $price_min && ((price2num($pu_equivalent) * (1 - (float) $remise_percent / 100)) < price2num($price_min))) { $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)); setEventMessages($mesg, null, 'errors'); $error++; $action = 'editline'; - } elseif ($pu_equivalent_ttc && $price_min_ttc && ((price2num($pu_equivalent_ttc) * (1 - $remise_percent / 100)) < price2num($price_min_ttc))) { + } elseif ($pu_equivalent_ttc && $price_min_ttc && ((price2num($pu_equivalent_ttc) * (1 - (float) $remise_percent / 100)) < price2num($price_min_ttc))) { $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min_ttc, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)); setEventMessages($mesg, null, 'errors'); $error++; diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index ccf706c9ac7..c2ab4fcd3bc 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -676,12 +676,11 @@ if (empty($reshook)) { $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09'); if ($prod_entry_mode == 'free') { $idprod = 0; - $tva_tx = (GETPOST('tva_tx', 'alpha') ? price2num(preg_replace('/\s*\(.*\)/', '', GETPOST('tva_tx', 'alpha'))) : 0); } else { $idprod = GETPOST('idprod', 'int'); - $tva_tx = ''; } + $tva_tx = GETPOST('tva_tx', 'alpha'); // Prepare a price equivalent for minimum price check $pu_equivalent = $pu_ht; @@ -762,7 +761,6 @@ if (empty($reshook)) { // Ecrase $pu par celui du produit // Ecrase $desc par celui du produit - // Ecrase $tva_tx par celui du produit // Ecrase $base_price_type par celui du produit if (!empty($idprod) && $idprod > 0) { $prod = new Product($db); @@ -771,11 +769,11 @@ if (empty($reshook)) { $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : ''); // Update if prices fields are defined - $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); + /*$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id); if (empty($tva_tx)) { $tva_npr = 0; - } + }*/ $pu_ht = $prod->price; $pu_ttc = $prod->price_ttc; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index cc6b92f72cb..5f24ca87830 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2038,12 +2038,12 @@ if (empty($reshook)) { $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09'); if ($prod_entry_mode == 'free') { $idprod = 0; - $tva_tx = (GETPOST('tva_tx', 'alpha') ? price2num(preg_replace('/\s*\(.*\)/', '', GETPOST('tva_tx', 'alpha'))) : 0); } else { $idprod = GETPOST('idprod', 'int'); - $tva_tx = ''; } + $tva_tx = GETPOST('tva_tx', 'alpha'); + $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2); $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha'), '', 2) : 0); if (empty($remise_percent)) { @@ -2137,7 +2137,6 @@ if (empty($reshook)) { // Ecrase $pu par celui du produit // Ecrase $desc par celui du produit - // Ecrase $tva_tx par celui du produit // Ecrase $base_price_type par celui du produit // Replaces $fk_unit with the product's if (!empty($idprod) && $idprod > 0) { @@ -2157,8 +2156,8 @@ if (empty($reshook)) { $price_min_ttc = $datapriceofproduct['price_min_ttc']; $price_base_type = $datapriceofproduct['price_base_type']; - $tva_tx = $datapriceofproduct['tva_tx']; - $tva_npr = $datapriceofproduct['tva_npr']; + //$tva_tx = $datapriceofproduct['tva_tx']; + //$tva_npr = $datapriceofproduct['tva_npr']; $tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx)); $tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx)); diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 12f53b49390..123366fd630 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -427,6 +427,7 @@ if (empty($reshook)) { } else { $idprod = GETPOST('idprod', 'int'); } + $tva_tx = GETPOST('tva_tx', 'alpha'); $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS'); @@ -474,11 +475,11 @@ if (empty($reshook)) { $prod->fetch($idprod); // Update if prices fields are defined - $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); + /*$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id); if (empty($tva_tx)) { $tva_npr = 0; - } + }*/ $price_min = $prod->price_min; $price_min_ttc = $prod->price_min_ttc; @@ -500,14 +501,14 @@ if (empty($reshook)) { if (count($prodcustprice->lines) > 0) { $price_min = price($prodcustprice->lines[0]->price_min); $price_min_ttc = price($prodcustprice->lines[0]->price_min_ttc); - $tva_tx = $prodcustprice->lines[0]->tva_tx; + /*$tva_tx = $prodcustprice->lines[0]->tva_tx; if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) { $tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')'; } $tva_npr = $prodcustprice->lines[0]->recuperableonly; if (empty($tva_tx)) { $tva_npr = 0; - } + }*/ } } } @@ -699,7 +700,7 @@ if (empty($reshook)) { $date_end_real_update = $objectline->date_end_real; } - $vat_rate = GETPOST('eltva_tx'); + $vat_rate = GETPOST('eltva_tx', 'alpha'); // Define info_bits $info_bits = 0; if (preg_match('/\*/', $vat_rate)) { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 1c54df24e06..369deba4455 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2344,11 +2344,7 @@ class Form } } // mode=1 means customers products - $urloption = 'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&status_purchase='.$status_purchase.'&finished='.$finished.'&hidepriceinlabel='.$hidepriceinlabel.'&warehousestatus='.$warehouseStatus; - //Price by customer - if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { - $urloption .= '&socid='.$socid; - } + $urloption = ($socid > 0 ? 'socid='.$socid.'&' : '').'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&status_purchase='.$status_purchase.'&finished='.$finished.'&hidepriceinlabel='.$hidepriceinlabel.'&warehousestatus='.$warehouseStatus; $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions); if (isModEnabled('variants') && is_array($selected_combinations)) { @@ -3247,6 +3243,7 @@ class Form // mode=2 means suppliers products $urloption = ($socid > 0 ? 'socid='.$socid.'&' : '').'htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=2&status='.$status.'&finished='.$finished.'&alsoproductwithnosupplierprice='.$alsoproductwithnosupplierprice; print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions); + print ($hidelabel ? '' : $langs->trans("RefOrLabel").' : ').''; } else { print $this->select_produits_fournisseurs_list($socid, $selected, $htmlname, $filtertype, $filtre, '', $status, 0, 0, $alsoproductwithnosupplierprice, $morecss, 0, $placeholder); diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 32a9f1cdaae..52761509890 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -40,6 +40,7 @@ if (empty($object) || !is_object($object)) { print "Error: this template page cannot be called directly as an URL"; exit; } + $usemargins = 0; if (isModEnabled('margin') && !empty($object->element) && in_array($object->element, array('facture', 'facturerec', 'propal', 'commande'))) { $usemargins = 1; @@ -48,6 +49,7 @@ if (!isset($dateSelector)) { global $dateSelector; // Take global var only if not already defined into function calling (for example formAddObjectLine) } global $forceall, $forcetoshowtitlelines, $senderissupplier, $inputalsopricewithtax; +global $mysoc; if (!isset($dateSelector)) { $dateSelector = 1; // For backward compatibility @@ -776,6 +778,35 @@ if (!empty($usemargins) && $user->rights->margins->creer) { var stringforvatrateselection = tva_tx; if (typeof default_vat_code != 'undefined' && default_vat_code != null && default_vat_code != '') { stringforvatrateselection = stringforvatrateselection+' ('+default_vat_code+')'; + + console.log("MAIN_SALETAX_AUTOSWITCH_I_CS_FOR_INDIA is on so we check if we need to autoswith the vat code"); + console.log("mysoc->country_code=country_code; ?> thirdparty->country_code=thirdparty->country_code; ?>"); + new_default_vat_code = default_vat_code; + country_code == 'IN' && !empty($object->thirdparty) && $object->thirdparty->country_code == 'IN' && $mysoc->state_code == $object->thirdparty->state_code) { + // We are in India and states are same, we revert the vat code "I-x" into "CS-x" + ?> + console.log("Countries are both IN and states are same, so we revert I into CS in default_vat_code="+default_vat_code); + new_default_vat_code = default_vat_code.replace(/^I\-/, 'C+S-'); + country_code == 'IN' && !empty($object->thirdparty) && $object->thirdparty->country_code == 'IN' && $mysoc->state_code != $object->thirdparty->state_code) { + // We are in India and states differs, we revert the vat code "CS-x" into "I-x" + ?> + console.log("Countries are both IN and states differs, so we revert CS into I in default_vat_code="+default_vat_code); + new_default_vat_code = default_vat_code.replace(/^C\+S\-/, 'I-'); + + if (new_default_vat_code != default_vat_code && jQuery('#tva_tx option:contains("'+new_default_vat_code+'")').val()) { + console.log("We found en entry into VAT with new default_vat_code, we will use it"); + stringforvatrateselection = jQuery('#tva_tx option:contains("'+new_default_vat_code+'")').val(); + } + } // Set vat rate if field is an input box $('#tva_tx').val(tva_tx); @@ -1113,7 +1144,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) { }); - /* Function to set fields from choice */ + /* Function to set fields visibility after selecting a free product */ function setforfree() { console.log("objectline_create.tpl::setforfree. We show most fields"); jQuery("#idprodfournprice").val('0'); // Set cursor on not selected product @@ -1148,7 +1179,7 @@ if (!empty($usemargins) && $user->rights->margins->creer) { jQuery("#multicurrency_price_ttc").val('').hide(); jQuery("#title_up_ttc, #title_up_ttc_currency").hide(); - jQuery("#tva_tx, #title_vat").hide(); + /* jQuery("#tva_tx, #title_vat").hide(); */ /* jQuery("#title_fourn_ref").hide(); */ jQuery("#np_marginRate, #np_markRate, .np_marginRate, .np_markRate, #units, #title_units").hide(); jQuery("#buying_price").show(); diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index f61e92c56f3..e07aa4ab5c5 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -103,26 +103,36 @@ if ($action == 'fetch' && !empty($id)) { $price_level = 1; if ($socid > 0) { - $thirdpartytemp = new Societe($db); - $thirdpartytemp->fetch($socid); - - //Load translation description and label - if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { - $newlang = $thirdpartytemp->default_lang; - - if (!empty($newlang)) { - $outputlangs = new Translate("", $conf); - $outputlangs->setDefaultLang($newlang); - $outdesc_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["description"])) ? $object->multilangs[$outputlangs->defaultlang]["description"] : $object->description; - $outlabel_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["label"])) ? $object->multilangs[$outputlangs->defaultlang]["label"] : $object->label; - } else { - $outdesc_trans = $object->description; - $outlabel_trans = $object->label; - } + $needchangeaccordingtothirdparty = 0; + if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) { + $needchangeaccordingtothirdparty = 1; } + if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { + $needchangeaccordingtothirdparty = 1; + } + if ($needchangeaccordingtothirdparty) { + $thirdpartytemp = new Societe($db); + $thirdpartytemp->fetch($socid); - if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) { - $price_level = $thirdpartytemp->price_level; + //Load translation description and label according to thirdparty language + if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) { + $newlang = $thirdpartytemp->default_lang; + + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + $outdesc_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["description"])) ? $object->multilangs[$outputlangs->defaultlang]["description"] : $object->description; + $outlabel_trans = (!empty($object->multilangs[$outputlangs->defaultlang]["label"])) ? $object->multilangs[$outputlangs->defaultlang]["label"] : $object->label; + } else { + $outdesc_trans = $object->description; + $outlabel_trans = $object->label; + } + } + + //Set price level according to thirdparty + if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { + $price_level = $thirdpartytemp->price_level; + } } } @@ -185,7 +195,7 @@ if ($action == 'fetch' && !empty($id)) { } // Price by customer - if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) { + if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') && !empty($socid)) { require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php'; $prodcustprice = new Productcustomerprice($db); From 098e6c40759172bbb7e0d51305f246ad901ff3fb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 21:49:51 +0100 Subject: [PATCH 444/816] Fix look and feel v17 --- htdocs/commande/list.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 98d2b59d6a3..9ef9072d16a 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1526,16 +1526,16 @@ if ($resql) { } // Town if (!empty($arrayfields['s.town']['checked'])) { - print ''; + print ''; } // Zip if (!empty($arrayfields['s.zip']['checked'])) { - print ''; + print ''; } // State if (!empty($arrayfields['state.nom']['checked'])) { print ''; - print ''; + print ''; print ''; } // Country @@ -1723,18 +1723,18 @@ if ($resql) { } // Status billed if (!empty($arrayfields['c.facture']['checked'])) { - print ''; + print ''; print $form->selectyesno('search_billed', $search_billed, 1, 0, 1, 1); print ''; } // Import key if (!empty($arrayfields['c.import_key']['checked'])) { - print ''; + print ''; print ''; } // Status if (!empty($arrayfields['c.fk_statut']['checked'])) { - print ''; + print ''; $liststatus = array( Commande::STATUS_DRAFT=>$langs->trans("StatusOrderDraftShort"), Commande::STATUS_VALIDATED=>$langs->trans("StatusOrderValidated"), @@ -1907,7 +1907,7 @@ if ($resql) { print_liste_field_titre($arrayfields['c.import_key']['label'], $_SERVER["PHP_SELF"], "c.import_key", "", $param, '', $sortfield, $sortorder, 'center '); } if (!empty($arrayfields['c.fk_statut']['checked'])) { - print_liste_field_titre($arrayfields['c.fk_statut']['label'], $_SERVER["PHP_SELF"], "c.fk_statut", "", $param, '', $sortfield, $sortorder, 'center '); + print_liste_field_titre($arrayfields['c.fk_statut']['label'], $_SERVER["PHP_SELF"], "c.fk_statut", "", $param, '', $sortfield, $sortorder, 'right '); } if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); @@ -2631,7 +2631,7 @@ if ($resql) { // Status if (!empty($arrayfields['c.fk_statut']['checked'])) { - print ''.$generic_commande->LibStatut($obj->fk_statut, $obj->billed, 5, 1).''; + print ''.$generic_commande->LibStatut($obj->fk_statut, $obj->billed, 5, 1).''; if (!$i) { $totalarray['nbfield']++; } From c78ad19186f8c410b01a85678dc74db776fb6366 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 18:50:01 +0100 Subject: [PATCH 445/816] Fix warning php8 --- htdocs/core/modules/propale/doc/pdf_azur.modules.php | 12 ++++++++++-- 1 file changed, 10 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 e1afcc0c7a0..db076cd97b9 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -675,10 +675,18 @@ class pdf_azur extends ModelePDFPropales // retrieve global local tax if ($localtax1_type && $localtax1ligne != 0) { - $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; + if (empty($this->localtax1[$localtax1_type][$localtax1_rate])) { + $this->localtax1[$localtax1_type][$localtax1_rate] = $localtax1ligne; + } else { + $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; + } } if ($localtax2_type && $localtax2ligne != 0) { - $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; + if (empty($this->localtax2[$localtax2_type][$localtax2_rate])) { + $this->localtax2[$localtax2_type][$localtax2_rate] = $localtax2ligne; + } else { + $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; + } } if (($object->lines[$i]->info_bits & 0x01) == 0x01) { From 09a2028522f069acc032f36ee80d93b9dad8dc9f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 21:27:56 +0100 Subject: [PATCH 446/816] Fix picto edit must not be visilbe in edit mode --- htdocs/core/tpl/objectline_title.tpl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/objectline_title.tpl.php b/htdocs/core/tpl/objectline_title.tpl.php index 7fe63613ea1..4640d710705 100644 --- a/htdocs/core/tpl/objectline_title.tpl.php +++ b/htdocs/core/tpl/objectline_title.tpl.php @@ -71,7 +71,7 @@ if (!empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) || !empty($conf->global->FA if (in_array($object->element, array('propal', 'commande', 'facture', 'supplier_proposal', 'order_supplier', 'invoice_supplier')) && $object->status == $object::STATUS_DRAFT) { global $mysoc; - if (empty($disableedit)) { + if (empty($disableedit) && GETPOST('mode', 'aZ09') != 'vatforalllines') { print 'id.'">'.img_edit($langs->trans("UpdateForAllLines"), 0, 'class="clickvatforalllines opacitymedium paddingleft cursorpointer"').''; } //print ''; @@ -111,7 +111,7 @@ print $langs->trans('ReductionShort'); if (in_array($object->element, array('propal', 'commande', 'facture')) && $object->status == $object::STATUS_DRAFT) { global $mysoc; - if (empty($disableedit)) { + if (empty($disableedit) && GETPOST('mode', 'aZ09') != 'remiseforalllines') { print 'id.'">'.img_edit($langs->trans("UpdateForAllLines"), 0, 'class="clickvatforalllines opacitymedium paddingleft cursorpointer"').''; } //print ''; From 00fce7eccd17d09074d1a6abb306d914b2b6217c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 21:34:59 +0100 Subject: [PATCH 447/816] Fix reposition when adding a contract line --- htdocs/contrat/card.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 38efdb3cca9..8af35072b93 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -2046,11 +2046,12 @@ if ($action == 'create') { $dateSelector = 1; print "\n"; - print ' + print ' + '; print '
'; From 3c169ae09a96653be9c5d9bbf5c45c36b30810d4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 21:49:51 +0100 Subject: [PATCH 448/816] Fix look and feel v17 --- htdocs/commande/list.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 42b71b14c86..93a0d302fbf 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -1515,16 +1515,16 @@ if ($resql) { } // Town if (!empty($arrayfields['s.town']['checked'])) { - print ''; + print ''; } // Zip if (!empty($arrayfields['s.zip']['checked'])) { - print ''; + print ''; } // State if (!empty($arrayfields['state.nom']['checked'])) { print ''; - print ''; + print ''; print ''; } // Country @@ -1712,18 +1712,18 @@ if ($resql) { } // Status billed if (!empty($arrayfields['c.facture']['checked'])) { - print ''; + print ''; print $form->selectyesno('search_billed', $search_billed, 1, 0, 1, 1); print ''; } // Import key if (!empty($arrayfields['c.import_key']['checked'])) { - print ''; + print ''; print ''; } // Status if (!empty($arrayfields['c.fk_statut']['checked'])) { - print ''; + print ''; $liststatus = array( Commande::STATUS_DRAFT=>$langs->trans("StatusOrderDraftShort"), Commande::STATUS_VALIDATED=>$langs->trans("StatusOrderValidated"), @@ -1896,7 +1896,7 @@ if ($resql) { print_liste_field_titre($arrayfields['c.import_key']['label'], $_SERVER["PHP_SELF"], "c.import_key", "", $param, '', $sortfield, $sortorder, 'center '); } if (!empty($arrayfields['c.fk_statut']['checked'])) { - print_liste_field_titre($arrayfields['c.fk_statut']['label'], $_SERVER["PHP_SELF"], "c.fk_statut", "", $param, '', $sortfield, $sortorder, 'center '); + print_liste_field_titre($arrayfields['c.fk_statut']['label'], $_SERVER["PHP_SELF"], "c.fk_statut", "", $param, '', $sortfield, $sortorder, 'right '); } if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'maxwidthsearch center '); @@ -2604,7 +2604,7 @@ if ($resql) { // Status if (!empty($arrayfields['c.fk_statut']['checked'])) { - print ''.$generic_commande->LibStatut($obj->fk_statut, $obj->billed, 5, 1).''; + print ''.$generic_commande->LibStatut($obj->fk_statut, $obj->billed, 5, 1).''; if (!$i) { $totalarray['nbfield']++; } From 313adba8f45382df6873c7749bb292192dd91d69 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 22:06:03 +0100 Subject: [PATCH 449/816] Fix set job recruitement back to draft --- htdocs/recruitment/recruitmentjobposition_card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/recruitment/recruitmentjobposition_card.php b/htdocs/recruitment/recruitmentjobposition_card.php index d1ca4ef2db1..34365e05792 100644 --- a/htdocs/recruitment/recruitmentjobposition_card.php +++ b/htdocs/recruitment/recruitmentjobposition_card.php @@ -401,7 +401,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Back to draft if ($object->status == $object::STATUS_VALIDATED) { if ($permissiontoadd) { - print ''.$langs->trans("SetToDraft").''; + print ''.$langs->trans("SetToDraft").''; } } From 3e4da8a1c587dea5feb861ea23dc2f7caa94f125 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 22:25:41 +0100 Subject: [PATCH 450/816] Fix standardize code --- .../recruitmentjobposition_card.php | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/htdocs/recruitment/recruitmentjobposition_card.php b/htdocs/recruitment/recruitmentjobposition_card.php index 34365e05792..b33ce55808e 100644 --- a/htdocs/recruitment/recruitmentjobposition_card.php +++ b/htdocs/recruitment/recruitmentjobposition_card.php @@ -108,7 +108,7 @@ if (empty($reshook)) { if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { $backtopage = $backurlforlist; } else { - $backtopage = dol_buildpath('/recruitment/recruitmentjobposition_card.php', 1).'?id='.($id > 0 ? $id : '__ID__'); + $backtopage = dol_buildpath('/recruitment/recruitmentjobposition_card.php', 1).'?id='.((!empty($id) && $id > 0) ? $id : '__ID__'); } } } @@ -130,7 +130,7 @@ if (empty($reshook)) { include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; if ($action == 'set_thirdparty' && $permissiontoadd) { - $object->setValueFrom('fk_soc', GETPOST('fk_soc', 'int'), '', '', 'date', '', $user, 'RECRUITMENTJOBPOSITION_MODIFY'); + $object->setValueFrom('fk_soc', GETPOST('fk_soc', 'int'), '', '', 'date', '', $user, $triggermodname); } if ($action == 'classin' && $permissiontoadd) { $object->setProject(GETPOST('projectid', 'int')); @@ -257,8 +257,6 @@ if (($id || $ref) && $action == 'edit') { // Part to show record if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { - $res = $object->fetch_optionals(); - $head = recruitmentjobpositionPrepareHead($object); print dol_get_fiche_head($head, 'card', $langs->trans("RecruitmentJobPosition"), -1, $object->picto); @@ -395,31 +393,27 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (empty($reshook)) { // Send if (empty($user->socid)) { - print ''.$langs->trans('SendMail').''."\n"; + print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init&token='.newToken().'#formmailbeforetitle'); } // Back to draft if ($object->status == $object::STATUS_VALIDATED) { if ($permissiontoadd) { - print ''.$langs->trans("SetToDraft").''; + print dolGetButtonAction('', $langs->trans('SetToDraft'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=confirm_setdraft&confirm=yes&token='.newToken(), '', $permissiontoadd); } } // Modify - if ($permissiontoadd) { - print ''.$langs->trans("Modify").''."\n"; - } else { - print ''.$langs->trans('Modify').''."\n"; - } + print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken(), '', $permissiontoadd); // Validate if ($object->status == $object::STATUS_DRAFT) { if ($permissiontoadd) { if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0)) { - print ''.$langs->trans("Validate").''; + print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=confirm_validate&confirm=yes&token='.newToken(), '', $permissiontoadd); } else { $langs->load("errors"); - print ''.$langs->trans("Validate").''; + print dolGetButtonAction($langs->trans("ErrorAddAtLeastOneLineFirst"), $langs->trans("Validate"), 'default', '#', '', 0); } } } @@ -442,9 +436,10 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea /* if ($permissiontoadd) { if ($object->status == $object::STATUS_ENABLED) { - print ''.$langs->trans("Disable").''."\n"; + print dolGetButtonAction('', $langs->trans('Disable'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=disable&token='.newToken(), '', $permissiontoadd); } else { - print ''.$langs->trans("Enable").''."\n"; + print dolGetButtonAction('', $langs->trans('Enable'), 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=enable&token='.newToken(), '', $permissiontoadd); + } } }*/ if ($permissiontoadd) { @@ -454,7 +449,8 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } // Delete - print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $permissiontodelete); + $params = array(); + print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $permissiontodelete, $params); } print '
'."\n"; } From 76d729573291eea6a7bcd1b04e1a509d5ab046b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 10 Jan 2023 23:16:28 +0100 Subject: [PATCH 451/816] fix properties --- htdocs/core/class/html.formticket.class.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index a34861e17d6..a397433979b 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -1,7 +1,7 @@ * Copyright (C) 2016 Christophe Battarel - * Copyright (C) 2019 Frédéric France + * Copyright (C) 2019-2022 Frédéric France * Copyright (C) 2021 Juanjo Menent * Copyright (C) 2021 Alexandre Spangaro * @@ -50,9 +50,15 @@ class FormTicket /** * @var string The track_id of the ticket. Used also for the $keytoavoidconflict to name session vars to upload files. + * @deprecated */ public $track_id; + /** + * @var string trackid + */ + public $trackid; + /** * @var int ID */ @@ -89,8 +95,12 @@ class FormTicket public $withusercreate; // to show name of creating user in form public $withcreatereadonly; - public $withref; // to show ref field + /** + * @var int withextrafields + */ + public $withextrafields; + public $withref; // to show ref field public $withcancel; public $type_code; From c5a83972ca9e7c1234799c8a5005b30060e33c0d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 23:47:47 +0100 Subject: [PATCH 452/816] Fix return warnings --- htdocs/core/class/stats.class.php | 2 +- htdocs/projet/class/projectstats.class.php | 12 ++++++------ htdocs/projet/class/taskstats.class.php | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/core/class/stats.class.php b/htdocs/core/class/stats.class.php index c8dbca747b9..60cdc5d5226 100644 --- a/htdocs/core/class/stats.class.php +++ b/htdocs/core/class/stats.class.php @@ -237,7 +237,7 @@ abstract class Stats /** * @param int $year year number - * @return int value + * @return array array of values */ protected abstract function getAverageByMonth($year); diff --git a/htdocs/projet/class/projectstats.class.php b/htdocs/projet/class/projectstats.class.php index 65d673a9ad2..e2b6c5129ff 100644 --- a/htdocs/projet/class/projectstats.class.php +++ b/htdocs/projet/class/projectstats.class.php @@ -298,7 +298,7 @@ class ProjectStats extends Stats * @param int $startyear End year * @param int $cachedelay Delay we accept for cache file (0=No read, no save of cache, -1=No read but save) * @param int $wonlostfilter Add a filter on status won/lost - * @return array Array of values + * @return array|int Array of values or <0 if error */ public function getWeightedAmountByMonthWithPrevYear($endyear, $startyear, $cachedelay = 0, $wonlostfilter = 1) { @@ -411,10 +411,10 @@ class ProjectStats extends Stats /** * Return amount of elements by month for several years * - * @param int $endyear End year - * @param int $startyear Start year - * @param int $cachedelay accept for cache file (0=No read, no save of cache, -1=No read but save) - * @return array of values + * @param int $endyear End year + * @param int $startyear Start year + * @param int $cachedelay accept for cache file (0=No read, no save of cache, -1=No read but save) + * @return array|int Array of values or <0 if error */ public function getTransformRateByMonthWithPrevYear($endyear, $startyear, $cachedelay = 0) { @@ -549,7 +549,7 @@ class ProjectStats extends Stats /** * Return average of entity by month * @param int $year year number - * @return int value + * @return array */ protected function getAverageByMonth($year) { diff --git a/htdocs/projet/class/taskstats.class.php b/htdocs/projet/class/taskstats.class.php index ce7c6c4f4c5..6ff56fd8132 100644 --- a/htdocs/projet/class/taskstats.class.php +++ b/htdocs/projet/class/taskstats.class.php @@ -212,7 +212,7 @@ class TaskStats extends Stats /** * Return average of entity by month * @param int $year year number - * @return int value + * @return array array of values */ protected function getAverageByMonth($year) { From e50a56290cd73811e10306ef6dadb876214252e9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 10 Jan 2023 23:49:31 +0100 Subject: [PATCH 453/816] Fix warning --- htdocs/comm/propal/class/propal.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 2b429d0e8d1..b0aa5dba54c 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2903,7 +2903,7 @@ class Propal extends CommonObject * @param int $offset For pagination * @param string $sortfield Sort criteria * @param string $sortorder Sort order - * @return int -1 if KO, array with result if OK + * @return array|int -1 if KO, array with result if OK */ public function liste_array($shortlist = 0, $draft = 0, $notcurrentuser = 0, $socid = 0, $limit = 0, $offset = 0, $sortfield = 'p.datep', $sortorder = 'DESC') { @@ -2982,8 +2982,8 @@ class Propal extends CommonObject /** * Returns an array with id and ref of related invoices * - * @param int $id Id propal - * @return array Array of invoices id + * @param int $id Id propal + * @return array|int Array of invoices id */ public function InvoiceArrayList($id) { From 52f80737f593f7e199d106a4032adc2b0844e7ea Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 00:37:00 +0100 Subject: [PATCH 454/816] css --- htdocs/theme/eldy/global.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 289f44333cc..b9e35e1e9ea 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -49,7 +49,7 @@ if (!defined('ISLOADEDBYSTEELSHEET')) { --colortextbacktab: #; --colorboxiconbg: #eee; --refidnocolor:#444; - --tableforfieldcolor:#666; + --tableforfieldcolor:#888; --amountremaintopaycolor:#880000; --amountpaymentcomplete:#008800; --amountremaintopaybackcolor:none; From 33917e97b6bf5093cdaf80390d4d2e2b26ee16ba Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 01:12:08 +0100 Subject: [PATCH 455/816] NEW Increment website counter on each page access in website module --- htdocs/core/lib/website.lib.php | 27 +++++++++++++++++++++++++++ htdocs/core/lib/website2.lib.php | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index c258e3198ce..32a6d9d962a 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -423,6 +423,33 @@ function dolWebsiteOutput($content, $contenttype = 'html', $containerid = '') print $content; } +/** + * Increase the website counter of page access. + * + * @param int $websiteid ID of website + * @param string $websitepagetype Type of page ('blogpost', 'page', ...) + * @param int $websitepageid ID of page + * @return int <0 if KO, >0 if OK + */ +function dolWebsiteIncrementCounter($websiteid, $websitepagetype, $websitepageid) +{ + if (!getDolGlobalInt('WEBSITE_PERF_DISABLE_COUNTERS')) { + //dol_syslog("dolWebsiteIncrementCounter websiteid=".$websiteid." websitepagetype=".$websitepagetype." websitepageid=".$websitepageid); + if (in_array($websitepagetype, array('blogpost', 'page'))) { + global $db; + + $sql = "UPDATE ".$db->prefix()."website SET pageviews_total = pageviews_total + 1, lastaccess = '".$db->idate(dol_now())."'"; + $sql .= " WHERE rowid = ".((int) $websiteid); + $resql = $db->query($sql); + if (! $resql) { + return -1; + } + } + } + + return 1; +} + /** * Format img tags to introduce viewimage on img src. diff --git a/htdocs/core/lib/website2.lib.php b/htdocs/core/lib/website2.lib.php index 05727a1e539..c7099e8d2ed 100644 --- a/htdocs/core/lib/website2.lib.php +++ b/htdocs/core/lib/website2.lib.php @@ -271,7 +271,7 @@ function dolSavePageContent($filetpl, Website $object, WebsitePage $objectpage, $tplcontent .= ''."\n"; $tplcontent .= 'id.');'."\n"; + $tplcontent .= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "html", '.$objectpage->id.'); dolWebsiteIncrementCounter('.$object->id.', "'.$objectpage->type_container.'", '.$objectpage->id.');'."\n"; $tplcontent .= "// END PHP ?>\n"; //var_dump($filetpl);exit; From 8f5edcab02d45dcfaa84200013d36c9fad807be9 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Wed, 11 Jan 2023 06:11:41 +0100 Subject: [PATCH 456/816] Use isModEnabled() --- htdocs/bookcal/class/booking.class.php | 2 +- htdocs/comm/propal/class/propal.class.php | 2 +- htdocs/commande/class/commande.class.php | 2 +- .../facture/class/facture-rec.class.php | 2 +- htdocs/contrat/class/contrat.class.php | 2 +- htdocs/core/menus/init_menu_auguria.sql | 42 +++++++++---------- .../class/conferenceorbooth.class.php | 2 +- .../class/conferenceorboothattendee.class.php | 2 +- htdocs/fichinter/class/fichinter.class.php | 2 +- .../class/fournisseur.commande.class.php | 2 +- .../class/fournisseur.facture-rec.class.php | 2 +- .../fourn/class/fournisseur.facture.class.php | 2 +- .../template/class/myobject.class.php | 2 +- htdocs/mrp/class/mo.class.php | 2 +- .../class/recruitmentjobposition.class.php | 2 +- htdocs/ticket/class/ticket.class.php | 2 +- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/htdocs/bookcal/class/booking.class.php b/htdocs/bookcal/class/booking.class.php index a74cb87a43d..51799fa09da 100644 --- a/htdocs/bookcal/class/booking.class.php +++ b/htdocs/bookcal/class/booking.class.php @@ -104,7 +104,7 @@ class Booking extends CommonObject public $fields=array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>1.2, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'searchall'=>1, 'validate'=>'1', 'comment'=>"Reference of object"), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'picto'=>'company', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'help'=>"LinkToThirparty", 'validate'=>'1',), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'picto'=>'company', 'enabled'=>'isModEnabled("societe")', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'help'=>"LinkToThirparty", 'validate'=>'1',), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'picto'=>'project', 'enabled'=>'$conf->project->enabled', 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'validate'=>'1',), 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3, 'validate'=>'1',), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0, 'cssview'=>'wordbreak', 'validate'=>'1',), diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 1b3df25c7d2..596e6e708aa 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -301,7 +301,7 @@ class Propal extends CommonObject 'ref' =>array('type'=>'varchar(30)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'showoncombobox'=>1, 'position'=>20), 'ref_client' =>array('type'=>'varchar(255)', 'label'=>'RefCustomer', 'enabled'=>1, 'visible'=>-1, 'position'=>22), 'ref_ext' =>array('type'=>'varchar(255)', 'label'=>'RefExt', 'enabled'=>1, 'visible'=>0, 'position'=>40), - 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'visible'=>-1, 'position'=>23), + 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'position'=>23), 'fk_projet' =>array('type'=>'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label'=>'Fk projet', 'enabled'=>"isModEnabled('project')", 'visible'=>-1, 'position'=>24), 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>25), 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>55), diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 73988594e6f..f6b304a7a52 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -306,7 +306,7 @@ class Commande extends CommonOrder 'ref' =>array('type'=>'varchar(30)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'showoncombobox'=>1, 'position'=>25), 'ref_ext' =>array('type'=>'varchar(255)', 'label'=>'RefExt', 'enabled'=>1, 'visible'=>0, 'position'=>26), 'ref_client' =>array('type'=>'varchar(255)', 'label'=>'RefCustomer', 'enabled'=>1, 'visible'=>-1, 'position'=>28), - 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'visible'=>-1, 'notnull'=>1, 'position'=>20), + 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'notnull'=>1, 'position'=>20), 'fk_projet' =>array('type'=>'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'visible'=>-1, 'position'=>25), 'date_commande' =>array('type'=>'date', 'label'=>'Date', 'enabled'=>1, 'visible'=>1, 'position'=>60), 'date_valid' =>array('type'=>'datetime', 'label'=>'DateValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>62), diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 3a586dfc3e5..6d7d2117147 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -169,7 +169,7 @@ class FactureRec extends CommonInvoice 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10), 'titre' =>array('type'=>'varchar(100)', 'label'=>'Titre', 'enabled'=>1, 'showoncombobox' => 1, 'visible'=>-1, 'position'=>15), 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>20, 'index'=>1), - 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'visible'=>-1, 'notnull'=>1, 'position'=>25), + 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'notnull'=>1, 'position'=>25), 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>30), //'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35), 'remise' =>array('type'=>'double', 'label'=>'Remise', 'enabled'=>1, 'visible'=>-1, 'position'=>40), diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 4352364452b..cc9f3319a5d 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -232,7 +232,7 @@ class Contrat extends CommonObject 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35), 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>40), 'date_contrat' =>array('type'=>'datetime', 'label'=>'Date contrat', 'enabled'=>1, 'visible'=>-1, 'position'=>45), - 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'visible'=>-1, 'notnull'=>1, 'position'=>70), + 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'notnull'=>1, 'position'=>70), 'fk_projet' =>array('type'=>'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'visible'=>-1, 'position'=>75), 'fk_commercial_signature' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'SaleRepresentative Signature', 'enabled'=>1, 'visible'=>-1, 'position'=>80), 'fk_commercial_suivi' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'SaleRepresentative follower', 'enabled'=>1, 'visible'=>-1, 'position'=>85), diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index e6fc16a62d6..0308d52f67d 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -12,7 +12,7 @@ delete from llx_menu where menu_handler=__HANDLER__ and entity=__ENTITY__; -- Top-Menu -- old: (module, enabled, rowid, ...) insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 1__+MAX_llx_menu__, '', '1', __HANDLER__, 'top', 'home', '', 0, '/index.php?mainmenu=home&leftmenu=', 'Home', -1, '', '', '', 2, 10, __ENTITY__); -insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 2__+MAX_llx_menu__, 'societe|fournisseur|supplier_order|supplier_invoice', '($conf->societe->enabled && (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) || empty($conf->global->SOCIETE_DISABLE_CUSTOMERS) || isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || $conf->supplier_order->enabled || $conf->supplier_invoice->enabled))', __HANDLER__, 'top', 'companies', '', 0, '/societe/index.php?mainmenu=companies&leftmenu=', 'ThirdParties', -1, 'companies', '$user->rights->societe->lire || $user->rights->societe->contact->lire', '', 2, 20, __ENTITY__); +insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 2__+MAX_llx_menu__, 'societe|fournisseur|supplier_order|supplier_invoice', '(isModEnabled("societe") && (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) || empty($conf->global->SOCIETE_DISABLE_CUSTOMERS) || isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || $conf->supplier_order->enabled || $conf->supplier_invoice->enabled))', __HANDLER__, 'top', 'companies', '', 0, '/societe/index.php?mainmenu=companies&leftmenu=', 'ThirdParties', -1, 'companies', '$user->rights->societe->lire || $user->rights->societe->contact->lire', '', 2, 20, __ENTITY__); insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 3__+MAX_llx_menu__, 'product|service', '$conf->product->enabled || $conf->service->enabled', __HANDLER__, 'top', 'products', '', 0, '/product/index.php?mainmenu=products&leftmenu=', 'ProductsPipeServices', -1, 'products', '$user->rights->produit->lire||$user->rights->service->lire', '', 0, 30, __ENTITY__); insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 16__+MAX_llx_menu__, 'bom|mrp', '$conf->bom->enabled || $conf->mrp->enabled', __HANDLER__, 'top', 'mrp', '', 0, '/mrp/index.php?mainmenu=mrp&leftmenu=', 'MRP', -1, 'mrp', '$user->rights->bom->read||$user->rights->mrp->read', '', 0, 31, __ENTITY__); insert into llx_menu (rowid, module, enabled, menu_handler, type, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ( 7__+MAX_llx_menu__, 'projet', '$conf->project->enabled', __HANDLER__, 'top', 'project', '', 0, '/projet/index.php?mainmenu=project&leftmenu=', 'Projects', -1, 'projects', '$user->rights->projet->lire', '', 2, 32, __ENTITY__); @@ -83,36 +83,36 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$leftmenu=="users"', __HANDLER__, 'left', 408__+MAX_llx_menu__, 'home', '', 407__+MAX_llx_menu__, '/user/group/card.php?mainmenu=home&leftmenu=users&action=create', 'NewGroup', 2, 'users', '(($conf->global->MAIN_USE_ADVANCED_PERMS?$user->rights->user->group_advance->write:$user->rights->user->user->creer) || $user->admin) && !(! empty($conf->multicompany->enabled) && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE)', '', 2, 0, __ENTITY__); -- Third parties -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 500__+MAX_llx_menu__, 'companies', 'thirdparties', 2__+MAX_llx_menu__, '/societe/index.php?mainmenu=companies&leftmenu=thirdparties', 'ThirdParty', 0, 'companies', '$user->rights->societe->lire', '', 2, 0, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 501__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&action=create', 'MenuNewThirdParty', 1, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 502__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&leftmenu=thirdparties', 'List', 1, 'companies', '$user->rights->societe->lire', '', 2, 0, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 503__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=f&leftmenu=suppliers', 'ListSuppliersShort', 1, 'suppliers', '$user->rights->societe->lire && $user->rights->fournisseur->lire', '', 2, 5, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 504__+MAX_llx_menu__, 'companies', '', 503__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=supplier&action=create&type=f', 'NewSupplier', 2, 'suppliers', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 506__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=p&leftmenu=prospects', 'ListProspectsShort', 1, 'companies', '$user->rights->societe->lire', '', 2, 3, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 507__+MAX_llx_menu__, 'companies', '', 506__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=prospects&action=create&type=p', 'MenuNewProspect', 2, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 509__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=c&leftmenu=customers', 'ListCustomersShort', 1, 'companies', '$user->rights->societe->lire', '', 2, 4, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 510__+MAX_llx_menu__, 'companies', '', 509__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=customers&action=create&type=c', 'MenuNewCustomer', 2, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 500__+MAX_llx_menu__, 'companies', 'thirdparties', 2__+MAX_llx_menu__, '/societe/index.php?mainmenu=companies&leftmenu=thirdparties', 'ThirdParty', 0, 'companies', '$user->rights->societe->lire', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 501__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&action=create', 'MenuNewThirdParty', 1, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 502__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&leftmenu=thirdparties', 'List', 1, 'companies', '$user->rights->societe->lire', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe") && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 503__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=f&leftmenu=suppliers', 'ListSuppliersShort', 1, 'suppliers', '$user->rights->societe->lire && $user->rights->fournisseur->lire', '', 2, 5, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe") && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 504__+MAX_llx_menu__, 'companies', '', 503__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=supplier&action=create&type=f', 'NewSupplier', 2, 'suppliers', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 506__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=p&leftmenu=prospects', 'ListProspectsShort', 1, 'companies', '$user->rights->societe->lire', '', 2, 3, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 507__+MAX_llx_menu__, 'companies', '', 506__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=prospects&action=create&type=p', 'MenuNewProspect', 2, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 509__+MAX_llx_menu__, 'companies', '', 500__+MAX_llx_menu__, '/societe/list.php?mainmenu=companies&type=c&leftmenu=customers', 'ListCustomersShort', 1, 'companies', '$user->rights->societe->lire', '', 2, 4, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 510__+MAX_llx_menu__, 'companies', '', 509__+MAX_llx_menu__, '/societe/card.php?mainmenu=companies&leftmenu=customers&action=create&type=c', 'MenuNewCustomer', 2, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); -- Third parties - Contacts -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 600__+MAX_llx_menu__, 'companies', 'contacts', 2__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts', 'ContactsAddresses', 0, 'companies', '$user->rights->societe->lire', '', 2, 1, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 601__+MAX_llx_menu__, 'companies', '', 600__+MAX_llx_menu__, '/contact/card.php?mainmenu=companies&leftmenu=contacts&action=create', 'NewContactAddress', 1, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 602__+MAX_llx_menu__, 'companies', '', 600__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts', 'List', 1, 'companies', '$user->rights->societe->lire', '', 2, 1, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 604__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=p', 'ThirdPartyProspects', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 1, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 605__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=c', 'ThirdPartyCustomers', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 2, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 606__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=f', 'ThirdPartySuppliers', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 3, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled', __HANDLER__, 'left', 607__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=o', 'Others', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 4, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 600__+MAX_llx_menu__, 'companies', 'contacts', 2__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts', 'ContactsAddresses', 0, 'companies', '$user->rights->societe->lire', '', 2, 1, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 601__+MAX_llx_menu__, 'companies', '', 600__+MAX_llx_menu__, '/contact/card.php?mainmenu=companies&leftmenu=contacts&action=create', 'NewContactAddress', 1, 'companies', '$user->rights->societe->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 602__+MAX_llx_menu__, 'companies', '', 600__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts', 'List', 1, 'companies', '$user->rights->societe->lire', '', 2, 1, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 604__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=p', 'ThirdPartyProspects', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 1, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 605__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=c', 'ThirdPartyCustomers', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 2, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe") && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))', __HANDLER__, 'left', 606__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=f', 'ThirdPartySuppliers', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 3, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe")', __HANDLER__, 'left', 607__+MAX_llx_menu__, 'companies', '', 602__+MAX_llx_menu__, '/contact/list.php?mainmenu=companies&leftmenu=contacts&type=o', 'Others', 2, 'companies', '$user->rights->societe->contact->lire', '', 2, 4, __ENTITY__); -- Third parties - Category customer -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && $conf->categorie->enabled', __HANDLER__, 'left', 650__+MAX_llx_menu__, 'companies', 'cat', 2__+MAX_llx_menu__, '/categories/index.php?mainmenu=companies&leftmenu=cat&type=1', 'SuppliersCategoriesShort', 0, 'categories', '$user->rights->categorie->lire', '', 2, 3, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && $conf->categorie->enabled', __HANDLER__, 'left', 651__+MAX_llx_menu__, 'companies', '', 650__+MAX_llx_menu__, '/categories/card.php?mainmenu=companies&action=create&type=1', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe") && $conf->categorie->enabled', __HANDLER__, 'left', 650__+MAX_llx_menu__, 'companies', 'cat', 2__+MAX_llx_menu__, '/categories/index.php?mainmenu=companies&leftmenu=cat&type=1', 'SuppliersCategoriesShort', 0, 'categories', '$user->rights->categorie->lire', '', 2, 3, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe") && $conf->categorie->enabled', __HANDLER__, 'left', 651__+MAX_llx_menu__, 'companies', '', 650__+MAX_llx_menu__, '/categories/card.php?mainmenu=companies&action=create&type=1', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); -- Third parties - Category supplier insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $conf->categorie->enabled', __HANDLER__, 'left', 660__+MAX_llx_menu__, 'companies', 'cat', 2__+MAX_llx_menu__, '/categories/index.php?mainmenu=companies&leftmenu=cat&type=2', 'CustomersProspectsCategoriesShort', 0, 'categories', '$user->rights->categorie->lire', '', 2, 4, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '(isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $conf->categorie->enabled', __HANDLER__, 'left', 661__+MAX_llx_menu__, 'companies', '', 660__+MAX_llx_menu__, '/categories/card.php?mainmenu=companies&action=create&type=2', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); -- Third parties - Category contact -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && $conf->categorie->enabled', __HANDLER__, 'left', 670__+MAX_llx_menu__, 'companies', 'cat', 2__+MAX_llx_menu__, '/categories/index.php?mainmenu=companies&leftmenu=cat&type=4', 'ContactCategoriesShort', 0, 'categories', '$user->rights->categorie->lire', '', 2, 3, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->societe->enabled && $conf->categorie->enabled', __HANDLER__, 'left', 671__+MAX_llx_menu__, 'companies', '', 670__+MAX_llx_menu__, '/categories/card.php?mainmenu=companies&action=create&type=4', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe") && $conf->categorie->enabled', __HANDLER__, 'left', 670__+MAX_llx_menu__, 'companies', 'cat', 2__+MAX_llx_menu__, '/categories/index.php?mainmenu=companies&leftmenu=cat&type=4', 'ContactCategoriesShort', 0, 'categories', '$user->rights->categorie->lire', '', 2, 3, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', 'isModEnabled("societe") && $conf->categorie->enabled', __HANDLER__, 'left', 671__+MAX_llx_menu__, 'companies', '', 670__+MAX_llx_menu__, '/categories/card.php?mainmenu=companies&action=create&type=4', 'NewCategory', 1, 'categories', '$user->rights->categorie->creer', '', 2, 0, __ENTITY__); -- Product - Product insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->product->enabled', __HANDLER__, 'left', 2800__+MAX_llx_menu__, 'products', 'product', 3__+MAX_llx_menu__, '/product/index.php?mainmenu=products&leftmenu=product&type=0', 'Products', 0, 'products', '$user->rights->produit->lire', '', 2, 0, __ENTITY__); diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index cdb67a2c37b..2d7d56ec65d 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -106,7 +106,7 @@ class ConferenceOrBooth extends ActionComm 'id' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), 'ref' => array('type'=>'integer', 'label'=>'Ref', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>2, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax125', 'help'=>"OrganizationEvenLabelName", 'showoncombobox'=>'1',), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500'), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:t.usage_organize_event=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'picto'=>'project', 'css'=>'tdoverflowmax150 maxwidth500'), 'note' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>1), 'fk_action' => array('type'=>'sellist:c_actioncomm:libelle:id::module LIKE (\'%@eventorganization\')', 'label'=>'Format', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>1, 'css'=>'width300'), diff --git a/htdocs/eventorganization/class/conferenceorboothattendee.class.php b/htdocs/eventorganization/class/conferenceorboothattendee.class.php index 595eaf67eeb..f1e4fe2f3d5 100644 --- a/htdocs/eventorganization/class/conferenceorboothattendee.class.php +++ b/htdocs/eventorganization/class/conferenceorboothattendee.class.php @@ -108,7 +108,7 @@ class ConferenceOrBoothAttendee extends CommonObject 'email' => array('type'=>'mail', 'label'=>'EmailAttendee', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'autofocusoncreate'=>1, 'searchall'=>1), 'firstname' => array('type'=>'varchar(100)', 'label'=>'Firstname', 'enabled'=>'1', 'position'=>31, 'notnull'=>0, 'visible'=>1, 'index'=>1, 'searchall'=>1), 'lastname' => array('type'=>'varchar(100)', 'label'=>'Lastname', 'enabled'=>'1', 'position'=>32, 'notnull'=>0, 'visible'=>1, 'index'=>1, 'searchall'=>1), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status = 1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>40, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status = 1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'position'=>40, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500'), 'email_company' => array('type'=>'mail', 'label'=>'EmailCompany', 'enabled'=>'1', 'position'=>41, 'notnull'=>0, 'visible'=>-2, 'searchall'=>1), 'date_subscription' => array('type'=>'datetime', 'label'=>'DateOfRegistration', 'enabled'=>'1', 'position'=>56, 'notnull'=>1, 'visible'=>1, 'showoncombobox'=>'1',), 'fk_invoice' => array('type'=>'integer:Facture:compta/facture/class/facture.class.php', 'label'=>'Invoice', 'enabled'=>'$conf->facture->enabled', 'position'=>57, 'notnull'=>0, 'visible'=>-1, 'index'=>0, 'picto'=>'bill', 'css'=>'tdoverflowmax150 maxwidth500'), diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index e36598d04bc..a7c3e43f599 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -38,7 +38,7 @@ class Fichinter extends CommonObject { public $fields = array( 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10), - 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'visible'=>-1, 'notnull'=>1, 'position'=>15), + 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'notnull'=>1, 'position'=>15), 'fk_projet' =>array('type'=>'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label'=>'Fk projet', 'enabled'=>'isModEnabled("project")', 'visible'=>-1, 'position'=>20), 'fk_contrat' =>array('type'=>'integer', 'label'=>'Fk contrat', 'enabled'=>'$conf->contrat->enabled', 'visible'=>-1, 'position'=>25), 'ref' =>array('type'=>'varchar(30)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'showoncombobox'=>1, 'position'=>30), diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 4fc242bdbcc..0cfff5a8297 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -254,7 +254,7 @@ class CommandeFournisseur extends CommonOrder 'multicurrency_total_tva' =>array('type'=>'double(24,8)', 'label'=>'MulticurrencyAmountVAT', 'enabled'=>'isModEnabled("multicurrency")', 'visible'=>-1, 'position'=>235), 'multicurrency_total_ttc' =>array('type'=>'double(24,8)', 'label'=>'MulticurrencyAmountTTC', 'enabled'=>'isModEnabled("multicurrency")', 'visible'=>-1, 'position'=>240), 'date_creation' =>array('type'=>'datetime', 'label'=>'Date creation', 'enabled'=>1, 'visible'=>-1, 'position'=>500), - 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'visible'=>1, 'notnull'=>1, 'position'=>46), + 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>1, 'notnull'=>1, 'position'=>46), 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>0, 'notnull'=>1, 'position'=>1000, 'index'=>1), 'tms'=>array('type'=>'datetime', 'label'=>"DateModificationShort", 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>501), 'last_main_doc' =>array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>1, 'visible'=>0, 'position'=>700), diff --git a/htdocs/fourn/class/fournisseur.facture-rec.class.php b/htdocs/fourn/class/fournisseur.facture-rec.class.php index 738e27a84e9..53066afc0b7 100644 --- a/htdocs/fourn/class/fournisseur.facture-rec.class.php +++ b/htdocs/fourn/class/fournisseur.facture-rec.class.php @@ -181,7 +181,7 @@ class FactureFournisseurRec extends CommonInvoice 'titre' =>array('type'=>'varchar(100)', 'label'=>'Titre', 'enabled'=>1, 'showoncombobox' => 1, 'visible'=>-1, 'position'=>15), 'ref_supplier' =>array('type'=>'varchar(180)', 'label'=>'RefSupplier', 'enabled'=>1, 'showoncombobox' => 1, 'visible'=>-1, 'position'=>20), 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>25, 'index'=>1), - 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'visible'=>-1, 'notnull'=>1, 'position'=>30), + 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'notnull'=>1, 'position'=>30), 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>35), 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>40), 'suspended' =>array('type'=>'integer', 'label'=>'Suspended', 'enabled'=>1, 'visible'=>-1, 'position'=>225), diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index adf9fac3bde..524b50a5061 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -275,7 +275,7 @@ class FactureFournisseur extends CommonInvoice 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>25, 'index'=>1), 'ref_ext' =>array('type'=>'varchar(255)', 'label'=>'RefExt', 'enabled'=>1, 'visible'=>0, 'position'=>30), 'type' =>array('type'=>'smallint(6)', 'label'=>'Type', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35), - 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'visible'=>-1, 'notnull'=>1, 'position'=>40), + 'fk_soc' =>array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'notnull'=>1, 'position'=>40), 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>45), 'datef' =>array('type'=>'date', 'label'=>'Date', 'enabled'=>1, 'visible'=>-1, 'position'=>50), 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>55), diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 2fe7d983513..086420ef653 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -119,7 +119,7 @@ class MyObject extends CommonObject 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1, 'css'=>'minwidth300', 'cssview'=>'wordbreak', 'help'=>'Help text', 'showoncombobox'=>2, 'validate'=>1, 'alwayseditable'=>1), 'amount' => array('type'=>'price', 'label'=>'Amount', 'enabled'=>1, 'visible'=>1, 'default'=>'null', 'position'=>40, 'searchall'=>0, 'isameasure'=>1, 'help'=>'Help text for amount', 'validate'=>1), 'qty' => array('type'=>'real', 'label'=>'Qty', 'enabled'=>1, 'visible'=>1, 'default'=>'0', 'position'=>45, 'searchall'=>0, 'isameasure'=>1, 'help'=>'Help text for quantity', 'css'=>'maxwidth75imp', 'validate'=>1), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'picto'=>'company', 'label'=>'ThirdParty', 'visible'=> 1, 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'index'=>1, 'help'=>'OrganizationEventLinkToThirdParty', 'validate'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax150'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'picto'=>'company', 'label'=>'ThirdParty', 'visible'=> 1, 'enabled'=>'isModEnabled("societe")', 'position'=>50, 'notnull'=>-1, 'index'=>1, 'help'=>'OrganizationEventLinkToThirdParty', 'validate'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax150'), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'picto'=>'project', 'enabled'=>'$conf->project->enabled', 'visible'=>-1, 'position'=>52, 'notnull'=>-1, 'index'=>1, 'validate'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'csslist'=>'tdoverflowmax150'), 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>1, 'visible'=>3, 'position'=>60, 'validate'=>1), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>61, 'validate'=>1, 'cssview'=>'wordbreak'), diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 8624713c689..1aaf51808b8 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -106,7 +106,7 @@ class Mo extends CommonObject 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php:0', 'label'=>'Product', 'enabled'=>'$conf->product->enabled', 'visible'=>1, 'position'=>35, 'notnull'=>1, 'index'=>1, 'comment'=>"Product to produce", 'css'=>'maxwidth300', 'csslist'=>'tdoverflowmax100', 'picto'=>'product'), 'qty' => array('type'=>'real', 'label'=>'QtyToProduce', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'notnull'=>1, 'comment'=>"Qty to produce", 'css'=>'width75', 'default'=>1, 'isameasure'=>1), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>42, 'notnull'=>-1, 'searchall'=>1, 'showoncombobox'=>'2', 'css'=>'maxwidth300', 'csslist'=>'tdoverflowmax200', 'alwayseditable'=>1), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1', 'label'=>'ThirdParty', 'picto'=>'company', 'enabled'=>'$conf->societe->enabled', 'visible'=>-1, 'position'=>50, 'notnull'=>-1, 'index'=>1, 'css'=>'maxwidth400', 'csslist'=>'tdoverflowmax150'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1', 'label'=>'ThirdParty', 'picto'=>'company', 'enabled'=>'isModEnabled("societe")', 'visible'=>-1, 'position'=>50, 'notnull'=>-1, 'index'=>1, 'css'=>'maxwidth400', 'csslist'=>'tdoverflowmax150'), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:fk_statut=1', 'label'=>'Project', 'picto'=>'project', 'enabled'=>'$conf->project->enabled', 'visible'=>-1, 'position'=>51, 'notnull'=>-1, 'index'=>1, 'css'=>'minwidth200 maxwidth400', 'csslist'=>'tdoverflowmax100'), 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php:0', 'label'=>'WarehouseForProduction', 'picto'=>'stock', 'enabled'=>'$conf->stock->enabled', 'visible'=>1, 'position'=>52, 'css'=>'maxwidth400', 'csslist'=>'tdoverflowmax200'), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>61, 'notnull'=>-1,), diff --git a/htdocs/recruitment/class/recruitmentjobposition.class.php b/htdocs/recruitment/class/recruitmentjobposition.class.php index 7a9d077f910..fb34e33376e 100644 --- a/htdocs/recruitment/class/recruitmentjobposition.class.php +++ b/htdocs/recruitment/class/recruitmentjobposition.class.php @@ -124,7 +124,7 @@ class RecruitmentJobPosition extends CommonObject 'email_recruiter' => array('type'=>'varchar(255)', 'label'=>'EmailRecruiter', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>-1, 'help'=>'ToUseAGenericEmail', 'picto'=>'email'), 'fk_user_supervisor' => array('type'=>'integer:User:user/class/user.class.php:t.statut = 1', 'label'=>'FutureManager', 'enabled'=>'1', 'position'=>55, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'user.rowid', 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150', 'picto'=>'user'), 'fk_establishment' => array('type'=>'integer:Establishment:hrm/class/establishment.class.php', 'label'=>'Establishment', 'enabled'=>'$conf->hrm->enabled', 'position'=>56, 'notnull'=>0, 'visible'=>-1, 'foreignkey'=>'establishment.rowid',), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'WorkPlace', 'enabled'=>'$conf->societe->enabled', 'position'=>57, 'notnull'=>-1, 'visible'=>-1, 'css'=>'maxwidth500', 'index'=>1, 'help'=>"IfJobIsLocatedAtAPartner", 'picto'=>'company'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'WorkPlace', 'enabled'=>'isModEnabled("societe")', 'position'=>57, 'notnull'=>-1, 'visible'=>-1, 'css'=>'maxwidth500', 'index'=>1, 'help'=>"IfJobIsLocatedAtAPartner", 'picto'=>'company'), 'date_planned' => array('type'=>'date', 'label'=>'DateExpected', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>1,), 'remuneration_suggested' => array('type'=>'varchar(255)', 'label'=>'Remuneration', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>1,), 'description' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>65, 'notnull'=>0, 'visible'=>3,), diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 2aacffefcd1..ac6abea95d3 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -280,7 +280,7 @@ class Ticket extends CommonObject 'type_code' => array('type'=>'varchar(32)', 'label'=>'Type', 'visible'=>1, 'enabled'=>1, 'position'=>20, 'notnull'=>-1, 'help'=>"", 'csslist'=>'maxwidth125 tdoverflowmax50'), 'category_code' => array('type'=>'varchar(32)', 'label'=>'TicketCategory', 'visible'=>-1, 'enabled'=>1, 'position'=>21, 'notnull'=>-1, 'help'=>"", 'css'=>'maxwidth100 tdoverflowmax200'), 'severity_code' => array('type'=>'varchar(32)', 'label'=>'Severity', 'visible'=>1, 'enabled'=>1, 'position'=>22, 'notnull'=>-1, 'help'=>"", 'css'=>'maxwidth100'), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'visible'=>1, 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'index'=>1, 'searchall'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'css'=>'tdoverflowmax150 maxwidth150onsmartphone'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'visible'=>1, 'enabled'=>'isModEnabled("societe")', 'position'=>50, 'notnull'=>-1, 'index'=>1, 'searchall'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'css'=>'tdoverflowmax150 maxwidth150onsmartphone'), 'notify_tiers_at_create' => array('type'=>'integer', 'label'=>'NotifyThirdparty', 'visible'=>-1, 'enabled'=>0, 'position'=>51, 'notnull'=>1, 'index'=>1), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php', 'label'=>'Project', 'visible'=>-1, 'enabled'=>'$conf->project->enabled', 'position'=>52, 'notnull'=>-1, 'index'=>1, 'help'=>"LinkToProject"), //'timing' => array('type'=>'varchar(20)', 'label'=>'Timing', 'visible'=>-1, 'enabled'=>1, 'position'=>42, 'notnull'=>-1, 'help'=>""), // what is this ? From f6cde9507ec3bccabb1dc07b0e94e0ccec2195b2 Mon Sep 17 00:00:00 2001 From: atm-lena Date: Wed, 11 Jan 2023 09:35:28 +0100 Subject: [PATCH 457/816] FIX : alias name in contact list --- htdocs/contact/list.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index da07a2b699b..a025ef81b97 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -357,6 +357,9 @@ if (!empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES) $contactstatic->loadCacheOfProspStatus(); } +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + // Select every potentiels, and note each potentiels which fit in search parameters $tab_level = array(); $sql = "SELECT code, label, sortorder"; @@ -692,9 +695,6 @@ if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && ( exit; } -$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields - $help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Módulo_Empresas'; llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist'); @@ -1377,7 +1377,7 @@ while ($i < min($num, $limit)) { if ($obj->socid) { $objsoc = new Societe($db); $objsoc->fetch($obj->socid); - print $objsoc->getNomUrl(1); + print $objsoc->getNomUrl(1, '', 100, 0, 1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1); } else { print ' '; } From c0a7bca04e173b6f4aa692f2dc2e0d2b6143bd7f Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Wed, 11 Jan 2023 10:50:58 +0100 Subject: [PATCH 458/816] Fix supplier reccurent invoice if no pdf model --- htdocs/fourn/class/fournisseur.facture-rec.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/class/fournisseur.facture-rec.class.php b/htdocs/fourn/class/fournisseur.facture-rec.class.php index 31bc37b6e1a..024f6bf3e6f 100644 --- a/htdocs/fourn/class/fournisseur.facture-rec.class.php +++ b/htdocs/fourn/class/fournisseur.facture-rec.class.php @@ -1331,7 +1331,7 @@ class FactureFournisseurRec extends CommonInvoice // We refresh the object in order to have all necessary data (like date_lim_reglement) $new_fac_fourn->fetch($new_fac_fourn->id); $result = $new_fac_fourn->generateDocument($facturerec->model_pdf, $langs); - if ($result <= 0) { + if ($result < 0) { $this->errors = $new_fac_fourn->errors; $this->error = $new_fac_fourn->error; $error++; From 7bcaae86f4b9656302a544805a316282e6591805 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 11 Jan 2023 13:33:29 +0100 Subject: [PATCH 459/816] Fix php 8 warning --- htdocs/admin/dict.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index d928931c9ab..e5c9dcb3127 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -2514,7 +2514,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') print ''; } elseif ($value == 'type_duration') { print ''; - print $form->selectTypeDuration('', $obj->{$value}, array('i','h')); + print $form->selectTypeDuration('', (!empty($obj->{$value}) ? $obj->{$value}:''), array('i','h')); print ''; } else { $fieldValue = isset($obj->{$value}) ? $obj->{$value}: ''; From e820bb91c2662002e080c3e3796a8f6f1680e19d Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Wed, 11 Jan 2023 14:18:45 +0100 Subject: [PATCH 460/816] kanban view for localtax list --- .../compta/localtax/class/localtax.class.php | 34 ++++++++++++++ htdocs/compta/localtax/list.php | 44 ++++++++++++++----- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/htdocs/compta/localtax/class/localtax.class.php b/htdocs/compta/localtax/class/localtax.class.php index ed467ec91f4..f5cb98c1199 100644 --- a/htdocs/compta/localtax/class/localtax.class.php +++ b/htdocs/compta/localtax/class/localtax.class.php @@ -629,4 +629,38 @@ class Localtax extends CommonObject return ''; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs, $db; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + if (property_exists($this, 'label')) { + $return .= ' | '.$this->label.''; + } + if (property_exists($this, 'datev')) { + $return .= '
'.$langs->trans("DateEnd").' : '.dol_print_date($db->jdate($this->datev), 'day').''; + } + if (property_exists($this, 'datep')) { + $return .= '
'.$langs->trans("DatePayment", '', '', '', '', 5).' : '.dol_print_date($db->jdate($this->datep), 'day').''; + } + if (property_exists($this, 'amount')) { + $return .= '
'.$langs->trans("Amount").' : '.price($this->amount).''; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/compta/localtax/list.php b/htdocs/compta/localtax/list.php index ee2e13e1d57..42f4d326811 100644 --- a/htdocs/compta/localtax/list.php +++ b/htdocs/compta/localtax/list.php @@ -35,7 +35,7 @@ if ($user->socid) { } $result = restrictedArea($user, 'tax', '', '', 'charges'); $ltt = GETPOST("localTaxType", 'int'); - +$mode = GETPOST('mode', 'alpha'); /* * View @@ -49,7 +49,14 @@ $url = DOL_URL_ROOT.'/compta/localtax/card.php?action=create&localTaxType='.$ltt if (!empty($socid)) { $url .= '&socid='.$socid; } -$newcardbutton = dolGetButtonTitle($langs->trans('NewLocalTaxPayment', ($ltt + 1)), '', 'fa fa-plus-circle', $url, '', $user->rights->tax->charges->creer); +$param = ''; +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} +$newcardbutton = ''; +$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?localTaxType='.$ltt.'&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"].'?localTaxType='.$ltt.'&mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition')); +$newcardbutton .= dolGetButtonTitle($langs->trans('NewLocalTaxPayment', ($ltt + 1)), '', 'fa fa-plus-circle', $url, '', $user->rights->tax->charges->creer); print load_fiche_titre($langs->transcountry($ltt == 2 ? "LT2Payments" : "LT1Payments", $mysoc->country_code), $newcardbutton, 'title_accountancy'); @@ -77,19 +84,36 @@ if ($result) { while ($i < $num) { $obj = $db->fetch_object($result); - print ''; - + $localtax_static->label = $obj->label; $localtax_static->id = $obj->rowid; $localtax_static->ref = $obj->rowid; - print "".$localtax_static->getNomUrl(1)."\n"; - print "".dol_trunc($obj->label, 40)."\n"; - print ''.dol_print_date($db->jdate($obj->datev), 'day')."\n"; - print ''.dol_print_date($db->jdate($obj->datep), 'day')."\n"; + $localtax_static->datev = $obj->datev; + $localtax_static->datep = $obj->datep; + $localtax_static->amount = $obj->amount; + $total = $total + $obj->amount; - print ''.price($obj->amount).''; - print "\n"; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban + print $localtax_static->getKanbanView(''); + if ($i == ($num - 1)) { + print '
'; + print ''; + } + } else { + print ''; + print "".$localtax_static->getNomUrl(1)."\n"; + print "".dol_trunc($obj->label, 40)."\n"; + print ''.dol_print_date($db->jdate($obj->datev), 'day')."\n"; + print ''.dol_print_date($db->jdate($obj->datep), 'day')."\n"; + print ''.price($obj->amount).''; + print "\n"; + } $i++; } print ''.$langs->trans("Total").''; From 91837dd2efc979721ed300807e827eb6d1c58da3 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Wed, 11 Jan 2023 15:03:55 +0100 Subject: [PATCH 461/816] kanban mode for list of salaries --- htdocs/salaries/class/salary.class.php | 34 ++++ htdocs/salaries/list.php | 217 ++++++++++++++----------- 2 files changed, 155 insertions(+), 96 deletions(-) diff --git a/htdocs/salaries/class/salary.class.php b/htdocs/salaries/class/salary.class.php index 25adb60382c..72a228658d8 100644 --- a/htdocs/salaries/class/salary.class.php +++ b/htdocs/salaries/class/salary.class.php @@ -707,4 +707,38 @@ class Salary extends CommonObject return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs, $db; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'fk_user')) { + $return .= ' | '.$this->fk_user.''; + } + if (property_exists($this, 'type_payment')) { + $return .= '
'.$langs->trans("PaymentMode").' : '.$this->type_payment.''; + } + if (property_exists($this, 'amount')) { + $return .= '
'.$langs->trans("Amount").' : '.price($this->amount).''; + } + if (method_exists($this, 'LibStatut')) { + $return .= '
'.$this->LibStatut($this->paye, 5, $this->alreadypaid).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/salaries/list.php b/htdocs/salaries/list.php index 361107005a6..edeafa94c6a 100644 --- a/htdocs/salaries/list.php +++ b/htdocs/salaries/list.php @@ -44,6 +44,8 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $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', 'alpha'); //for mode view + // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; @@ -315,6 +317,9 @@ llxHeader('', $title, $help_url); $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); } @@ -379,11 +384,16 @@ print ''; print ''; print ''; print ''; +print ''; + $url = DOL_URL_ROOT.'/salaries/card.php?action=create'; if (!empty($socid)) { $url .= '&socid='.$socid; } +$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')); $newcardbutton = dolGetButtonTitle($langs->trans('NewSalaryPayment'), '', 'fa fa-plus-circle', $url, '', $user->rights->salaries->write); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'salary', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -534,121 +544,136 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $salstatic->ref = $obj->rowid; $salstatic->label = $obj->label; $salstatic->paye = $obj->paye; - $salstatic->datesp = $db->jdate($obj->datesp); - $salstatic->dateep = $db->jdate($obj->dateep); + $salstatic->datesp = $obj->datesp; + $salstatic->dateep = $obj->dateep; + $salstatic->amount = $obj->amount; + $salstatic->fk_user = $userstatic->getNomUrl(1); + $salstatic->type_payment = $obj->payment_code; - // Show here line of result - print ''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban + print $salstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + // Show here line of result + print ''; - // Ref - print "".$salstatic->getNomUrl(1)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + // Ref + print "".$salstatic->getNomUrl(1)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Label payment - print ''.dol_escape_htmltag($obj->label)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + // Label payment + print ''.dol_escape_htmltag($obj->label)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Date Start - print ''.dol_print_date($db->jdate($obj->datesp), 'day')."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + // Date Start + print ''.dol_print_date($db->jdate($obj->datesp), 'day')."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Date End - print ''.dol_print_date($db->jdate($obj->dateep), 'day')."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + // Date End + print ''.dol_print_date($db->jdate($obj->dateep), 'day')."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Employee - print ''.$userstatic->getNomUrl(1)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + // Employee + print ''.$userstatic->getNomUrl(1)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Type - print ''; - if (!empty($obj->payment_code)) print $langs->trans("PaymentTypeShort".$obj->payment_code); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - - // Account - if (isModEnabled("banque")) { + // Type print ''; - if ($obj->fk_account > 0) { - //$accountstatic->fetch($obj->fk_bank); - $accountstatic->id = $obj->bid; - $accountstatic->ref = $obj->bref; - $accountstatic->label = $obj->blabel; - $accountstatic->number = $obj->bnumber; - $accountstatic->iban = $obj->iban; - $accountstatic->bic = $obj->bic; - $accountstatic->currency_code = $langs->trans("Currency".$obj->currency_code); - $accountstatic->account_number = $obj->account_number; - $accountstatic->clos = $obj->clos; + if (!empty($obj->payment_code)) print $langs->trans("PaymentTypeShort".$obj->payment_code); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } - if (isModEnabled('accounting')) { + // Account + if (isModEnabled("banque")) { + print ''; + if ($obj->fk_account > 0) { + //$accountstatic->fetch($obj->fk_bank); + $accountstatic->id = $obj->bid; + $accountstatic->ref = $obj->bref; + $accountstatic->label = $obj->blabel; + $accountstatic->number = $obj->bnumber; + $accountstatic->iban = $obj->iban; + $accountstatic->bic = $obj->bic; + $accountstatic->currency_code = $langs->trans("Currency".$obj->currency_code); $accountstatic->account_number = $obj->account_number; + $accountstatic->clos = $obj->clos; - $accountingjournal = new AccountingJournal($db); - $accountingjournal->fetch($obj->fk_accountancy_journal); + if (isModEnabled('accounting')) { + $accountstatic->account_number = $obj->account_number; - $accountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + $accountingjournal = new AccountingJournal($db); + $accountingjournal->fetch($obj->fk_accountancy_journal); + + $accountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + } + //$accountstatic->label = $obj->blabel; + print $accountstatic->getNomUrl(1); + } else { + print ' '; } - //$accountstatic->label = $obj->blabel; - print $accountstatic->getNomUrl(1); - } else { - print ' '; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // if (!$i) $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; + + // Amount + print ''.price($obj->amount).''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; + } + $totalarray['val']['totalttcfield'] += $obj->amount; + + print ''.$salstatic->LibStatut($obj->paye, 5, $obj->alreadypayed).''; + if (!$i) $totalarray['nbfield']++; + + // Extra fields + 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; + // Action 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($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; } print ''; if (!$i) { $totalarray['nbfield']++; } + + print ''."\n"; } - - // if (!$i) $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; - - // Amount - print ''.price($obj->amount).''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; - } - $totalarray['val']['totalttcfield'] += $obj->amount; - - print ''.$salstatic->LibStatut($obj->paye, 5, $obj->alreadypayed).''; - if (!$i) $totalarray['nbfield']++; - - // Extra fields - 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; - // Action 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($object->id, $arrayofselected)) { - $selected = 1; - } - print ''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - - print ''."\n"; - $i++; } From 7213595cef946f1c29b4516e2768586c710fe078 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Wed, 11 Jan 2023 15:19:21 +0100 Subject: [PATCH 462/816] modify kanban mode for list of salaries --- htdocs/salaries/class/salary.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/salaries/class/salary.class.php b/htdocs/salaries/class/salary.class.php index 72a228658d8..7f9ea31cdc9 100644 --- a/htdocs/salaries/class/salary.class.php +++ b/htdocs/salaries/class/salary.class.php @@ -716,7 +716,7 @@ class Salary extends CommonObject */ public function getKanbanView($option = '') { - global $langs, $db; + global $langs; $return = '
'; $return .= '
'; $return .= ''; From a410100496dc54a16b4c713fff44d2e098bdba9a Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Wed, 11 Jan 2023 15:23:12 +0100 Subject: [PATCH 463/816] modify variable in class localtax --- htdocs/compta/localtax/class/localtax.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/localtax/class/localtax.class.php b/htdocs/compta/localtax/class/localtax.class.php index f5cb98c1199..d2300128550 100644 --- a/htdocs/compta/localtax/class/localtax.class.php +++ b/htdocs/compta/localtax/class/localtax.class.php @@ -638,7 +638,7 @@ class Localtax extends CommonObject */ public function getKanbanView($option = '') { - global $langs, $db; + global $langs; $return = '
'; $return .= '
'; $return .= ''; @@ -650,10 +650,10 @@ class Localtax extends CommonObject $return .= ' | '.$this->label.''; } if (property_exists($this, 'datev')) { - $return .= '
'.$langs->trans("DateEnd").' : '.dol_print_date($db->jdate($this->datev), 'day').''; + $return .= '
'.$langs->trans("DateEnd").' : '.dol_print_date($this->db->jdate($this->datev), 'day').''; } if (property_exists($this, 'datep')) { - $return .= '
'.$langs->trans("DatePayment", '', '', '', '', 5).' : '.dol_print_date($db->jdate($this->datep), 'day').''; + $return .= '
'.$langs->trans("DatePayment", '', '', '', '', 5).' : '.dol_print_date($this->db->jdate($this->datep), 'day').''; } if (property_exists($this, 'amount')) { $return .= '
'.$langs->trans("Amount").' : '.price($this->amount).''; From cfb16cc9cd296553c5acf9141941b1e25901ed46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Courtier?= Date: Wed, 11 Jan 2023 16:49:59 +0100 Subject: [PATCH 464/816] FIX: ref not available after ecmFile create() --- htdocs/ecm/class/ecmfiles.class.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index a451a462ea3..d6c906527f4 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -240,12 +240,9 @@ class EcmFiles extends CommonObject } // If ref not defined - $ref = ''; - if (!empty($this->ref)) { - $ref = $this->ref; - } else { + if (empty($this->ref)) { include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; - $ref = dol_hash($this->filepath.'/'.$this->filename, 3); + $this->ref = dol_hash($this->filepath.'/'.$this->filename, 3); } $maxposition = 0; @@ -300,7 +297,7 @@ class EcmFiles extends CommonObject $sql .= 'src_object_type,'; $sql .= 'src_object_id'; $sql .= ') VALUES ('; - $sql .= " '".$this->db->escape($ref)."', "; + $sql .= " '".$this->db->escape($this->ref)."', "; $sql .= ' '.(!isset($this->label) ? 'NULL' : "'".$this->db->escape($this->label)."'").','; $sql .= ' '.(!isset($this->share) ? 'NULL' : "'".$this->db->escape($this->share)."'").','; $sql .= ' '.$this->entity.','; From 62d33484715766b6c22ef3788327cc27d2d3052d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 16:56:06 +0100 Subject: [PATCH 465/816] Make module Paybox deprecated --- htdocs/core/modules/modPaybox.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modPaybox.class.php b/htdocs/core/modules/modPaybox.class.php index cf6ef512873..3df0b8f6a1d 100644 --- a/htdocs/core/modules/modPaybox.class.php +++ b/htdocs/core/modules/modPaybox.class.php @@ -54,7 +54,7 @@ class modPayBox extends DolibarrModules // Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module) $this->description = "Module to offer an online payment page by credit card with PayBox"; // Possible values for version are: 'development', 'experimental', 'dolibarr' or version - $this->version = 'dolibarr'; + $this->version = 'dolibarr_deprecated'; // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); // Name of image file used for this module. From 2eb054a170fcc4706ab42a94c0a0e569efde6d1a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 17:06:23 +0100 Subject: [PATCH 466/816] Fix try fix function not found of qodana --- htdocs/api/index.php | 12 ++++++------ htdocs/core/class/dolgeoip.class.php | 6 ++++-- htdocs/core/class/translate.class.php | 6 ++++-- htdocs/core/lib/files.lib.php | 6 +++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/htdocs/api/index.php b/htdocs/api/index.php index ba195b82c08..4e4da2c94cc 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -389,13 +389,13 @@ if (!empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' && $usecompression = (empty($conf->global->API_DISABLE_COMPRESSION) && !empty($_SERVER['HTTP_ACCEPT_ENCODING'])); $foundonealgorithm = 0; if ($usecompression) { - if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && is_callable('brotli_compress')) { + if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && function_exists('brotli_compress')) { $foundonealgorithm++; } - if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'bz') !== false && is_callable('bzcompress')) { + if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'bz') !== false && function_exists('bzcompress')) { $foundonealgorithm++; } - if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && is_callable('gzencode')) { + if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('gzencode')) { $foundonealgorithm++; } if (!$foundonealgorithm) { @@ -413,13 +413,13 @@ $result = $api->r->handle(); if (Luracast\Restler\Defaults::$returnResponse) { // We try to compress the data received data - if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && is_callable('brotli_compress') && defined('BROTLI_TEXT')) { + if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'br') !== false && function_exists('brotli_compress') && defined('BROTLI_TEXT')) { header('Content-Encoding: br'); $result = brotli_compress($result, 11, constant('BROTLI_TEXT')); - } elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'bz') !== false && is_callable('bzcompress')) { + } elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'bz') !== false && function_exists('bzcompress')) { header('Content-Encoding: bz'); $result = bzcompress($result, 9); - } elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && is_callable('gzencode')) { + } elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('gzencode')) { header('Content-Encoding: gzip'); $result = gzencode($result, 9); } else { diff --git a/htdocs/core/class/dolgeoip.class.php b/htdocs/core/class/dolgeoip.class.php index a2eea7023d9..e5001270131 100644 --- a/htdocs/core/class/dolgeoip.class.php +++ b/htdocs/core/class/dolgeoip.class.php @@ -144,10 +144,12 @@ class DolGeoIP return ''; } } else { - if (!function_exists('geoip_country_code_by_addr_v6')) { + if (function_exists('geoip_country_code_by_addr_v6')) { + return strtolower(geoip_country_code_by_addr_v6($this->gi, $ip)); + } elseif (function_exists('geoip_country_code_by_name_v6')) { return strtolower(geoip_country_code_by_name_v6($this->gi, $ip)); } - return strtolower(geoip_country_code_by_addr_v6($this->gi, $ip)); + return ''; } } } diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index 3f2f756977d..2315428b37a 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -932,8 +932,10 @@ class Translate $fonc = 'numberwords'; if (file_exists($newdir.'/functions_'.$fonc.'.lib.php')) { include_once $newdir.'/functions_'.$fonc.'.lib.php'; - $newnumber = numberwords_getLabelFromNumber($this, $number, $isamount); - break; + if (function_exists('numberwords_getLabelFromNumber')) { + $newnumber = numberwords_getLabelFromNumber($this, $number, $isamount); + break; + } } } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index ad7d7cecfa5..207f5bafeb7 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2058,13 +2058,13 @@ function dol_compress_file($inputfile, $outputfile, $mode = "gz", &$errorstring dol_syslog("dol_compress_file mode=".$mode." inputfile=".$inputfile." outputfile=".$outputfile); $data = implode("", file(dol_osencode($inputfile))); - if ($mode == 'gz') { + if ($mode == 'gz' && function_exists('gzencode')) { $foundhandler = 1; $compressdata = gzencode($data, 9); - } elseif ($mode == 'bz') { + } elseif ($mode == 'bz' && function_exists('bzcompress')) { $foundhandler = 1; $compressdata = bzcompress($data, 9); - } elseif ($mode == 'zstd') { + } elseif ($mode == 'zstd' && function_exists('zstd_compress')) { $foundhandler = 1; $compressdata = zstd_compress($data, 9); } elseif ($mode == 'zip') { From 356923b3695bd1ef773dd7789da6c04c7ea71394 Mon Sep 17 00:00:00 2001 From: atm-florian Date: Wed, 11 Jan 2023 17:31:37 +0100 Subject: [PATCH 467/816] FIX 14.0: move splitting of module:submodule string out of the genallowed condition --- htdocs/core/class/html.formfile.class.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 6fe10788c54..c1438209d5e 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -463,6 +463,15 @@ class FormFile $titletoshow = ($title == 'none' ? '' : $title); } + $submodulepart = $modulepart; + + // modulepart = 'nameofmodule' or 'nameofmodule:NameOfObject' + $tmp = explode(':', $modulepart); + if (!empty($tmp[1])) { + $modulepart = $tmp[0]; + $submodulepart = $tmp[1]; + } + // Show table if ($genallowed) { $modellist = array(); @@ -662,15 +671,6 @@ class FormFile $modellist = ModelePDFUserGroup::liste_modeles($this->db); } } else { - $submodulepart = $modulepart; - - // modulepart = 'nameofmodule' or 'nameofmodule:NameOfObject' - $tmp = explode(':', $modulepart); - if (!empty($tmp[1])) { - $modulepart = $tmp[0]; - $submodulepart = $tmp[1]; - } - // For normalized standard modules $file = dol_buildpath('/core/modules/'.$modulepart.'/modules_'.strtolower($submodulepart).'.php', 0); if (file_exists($file)) { From 87d2e86abac222b85298746eb33cb56f227c3c81 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Wed, 11 Jan 2023 17:39:46 +0100 Subject: [PATCH 468/816] kanban mode for pyment salaries list --- htdocs/salaries/class/paymentsalary.class.php | 35 +++ htdocs/salaries/payments.php | 247 ++++++++++-------- 2 files changed, 176 insertions(+), 106 deletions(-) diff --git a/htdocs/salaries/class/paymentsalary.class.php b/htdocs/salaries/class/paymentsalary.class.php index 029e5732f9b..b855462b527 100644 --- a/htdocs/salaries/class/paymentsalary.class.php +++ b/htdocs/salaries/class/paymentsalary.class.php @@ -707,4 +707,39 @@ class PaymentSalary extends CommonObject return $result; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs, $db; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'fk_bank')) { + $return .= ' | '.$this->fk_bank.''; + } + if (property_exists($this, 'fk_user_author')) { + $return .= '
'.$this->fk_user_author.''; + } + + if (property_exists($this, 'fk_typepayment')) { + $return .= '
'.$langs->trans("PaymentMode").' : '.$this->fk_typepayment.''; + } + if (property_exists($this, 'amount')) { + $return .= '
'.$langs->trans("Amount").' : '.price($this->amount).''; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/salaries/payments.php b/htdocs/salaries/payments.php index 8fcc7183dae..6fb41b1b38a 100644 --- a/htdocs/salaries/payments.php +++ b/htdocs/salaries/payments.php @@ -45,6 +45,8 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bomlist'; // 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', 'alpha'); // mode view for result + // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; @@ -316,6 +318,9 @@ llxHeader('', $title, $help_url); $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); } @@ -385,11 +390,16 @@ print ''; print ''; print ''; print ''; +print ''; + $url = DOL_URL_ROOT.'/salaries/card.php?action=create'; if (!empty($socid)) { $url .= '&socid='.$socid; } +$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')); $newcardbutton = dolGetButtonTitle($langs->trans('NewSalaryPayment'), '', 'fa fa-plus-circle', $url, '', $user->rights->salaries->write); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_payment', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -532,8 +542,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // Store properties in $object $object->setVarsFromFetchObj($obj); - // Show here line of result - print ''; + $userstatic->id = $obj->uid; $userstatic->lastname = $obj->lastname; @@ -549,136 +558,162 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $paymentsalstatic->id = $obj->rowid; $paymentsalstatic->ref = $obj->rowid; + $paymentsalstatic->amount = $obj->amount; + $paymentsalstatic->fk_typepayment = $obj->payment_code; + $paymentsalstatic->datec = $obj->dateep; + $paymentsalstatic->datep = $obj->datep; - // Ref - print "".$paymentsalstatic->getNomUrl(1)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + $accountlinestatic->id = $obj->fk_bank; + $accountlinestatic->ref = $obj->fk_bank; + $paymentsalstatic->fk_bank = $accountlinestatic->getNomUrl(1); + $paymentsalstatic->fk_user_author = $userstatic->getNomUrl(1); - // Ref salary - print "".$salstatic->getNomUrl(1)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - // Label payment - print "".dol_trunc($obj->label, 40)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - // Date end period - print ''.dol_print_date($db->jdate($obj->dateep), 'day')."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban - // Date payment - print ''.dol_print_date($db->jdate($obj->datep), 'day')."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + print $paymentsalstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + // Show here line of result + print ''; + // Ref + print "".$paymentsalstatic->getNomUrl(1)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Date value - /*print ''.dol_print_date($db->jdate($obj->datev), 'day')."\n"; - if (!$i) $totalarray['nbfield']++;*/ + // Ref salary + print "".$salstatic->getNomUrl(1)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Employee - print "".$userstatic->getNomUrl(1)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } + // Label payment + print "".dol_trunc($obj->label, 40)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Type - print ''; - print $langs->trans("PaymentTypeShort".$obj->payment_code); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } + // Date end period + print ''.dol_print_date($db->jdate($obj->dateep), 'day')."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Chq number - print ''.$obj->num_payment.''; - if (!$i) { - $totalarray['nbfield']++; - } + // Date payment + print ''.dol_print_date($db->jdate($obj->datep), 'day')."\n"; + if (!$i) { + $totalarray['nbfield']++; + } - // Account - if (isModEnabled("banque")) { - // Bank transaction + // Date value + /*print ''.dol_print_date($db->jdate($obj->datev), 'day')."\n"; + if (!$i) $totalarray['nbfield']++;*/ + + // Employee + print "".$userstatic->getNomUrl(1)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + + // Type print ''; - $accountlinestatic->id = $obj->fk_bank; - print $accountlinestatic->getNomUrl(1); + print $langs->trans("PaymentTypeShort".$obj->payment_code); print ''; if (!$i) { $totalarray['nbfield']++; } - print ''; - if ($obj->fk_bank > 0) { - //$accountstatic->fetch($obj->fk_bank); - $accountstatic->id = $obj->bid; - $accountstatic->ref = $obj->bref; - $accountstatic->number = $obj->bnumber; - $accountstatic->iban = $obj->iban; - $accountstatic->bic = $obj->bic; - $accountstatic->currency_code = $langs->trans("Currency".$obj->currency_code); - $accountstatic->clos = $obj->clos; + // Chq number + print ''.$obj->num_payment.''; + if (!$i) { + $totalarray['nbfield']++; + } - if (isModEnabled('accounting')) { - $accountstatic->account_number = $obj->account_number; - - $accountingjournal = new AccountingJournal($db); - $accountingjournal->fetch($obj->fk_accountancy_journal); - - $accountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + // Account + if (isModEnabled("banque")) { + // Bank transaction + print ''; + $accountlinestatic->id = $obj->fk_bank; + print $accountlinestatic->getNomUrl(1); + print ''; + if (!$i) { + $totalarray['nbfield']++; } - $accountstatic->label = $obj->blabel; - if ($accountstatic->id > 0) { - print $accountstatic->getNomUrl(1); + + print ''; + if ($obj->fk_bank > 0) { + //$accountstatic->fetch($obj->fk_bank); + $accountstatic->id = $obj->bid; + $accountstatic->ref = $obj->bref; + $accountstatic->number = $obj->bnumber; + $accountstatic->iban = $obj->iban; + $accountstatic->bic = $obj->bic; + $accountstatic->currency_code = $langs->trans("Currency".$obj->currency_code); + $accountstatic->clos = $obj->clos; + + if (isModEnabled('accounting')) { + $accountstatic->account_number = $obj->account_number; + + $accountingjournal = new AccountingJournal($db); + $accountingjournal->fetch($obj->fk_accountancy_journal); + + $accountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + } + $accountstatic->label = $obj->blabel; + if ($accountstatic->id > 0) { + print $accountstatic->getNomUrl(1); + } + } else { + print ' '; } - } else { - print ' '; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Amount + print ''.price($obj->amount).''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; + } + $totalarray['val']['totalttcfield'] += $obj->amount; + + // Extra fields + 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; + // Action 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($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; } print ''; if (!$i) { $totalarray['nbfield']++; } - } - // Amount - print ''.price($obj->amount).''; - if (!$i) { - $totalarray['nbfield']++; + print ''."\n"; } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; - } - $totalarray['val']['totalttcfield'] += $obj->amount; - - // Extra fields - 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; - // Action 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($object->id, $arrayofselected)) { - $selected = 1; - } - print ''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - - print ''."\n"; - $i++; } From 45725a1e9743d1840c9589982fce04be4bf3008c Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 11 Jan 2023 17:58:26 +0100 Subject: [PATCH 469/816] fix: display True volume in PDF --- htdocs/core/modules/expedition/doc/pdf_espadon.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php index 17999e59e4c..97be43da689 100644 --- a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php @@ -832,7 +832,7 @@ class pdf_espadon extends ModelePdfExpedition $totalToShip = $tmparray['toship']; // Set trueVolume and volume_units not currently stored into database if ($object->trueWidth && $object->trueHeight && $object->trueDepth) { - $object->trueVolume = price(($object->trueWidth * $object->trueHeight * $object->trueDepth), 0, $outputlangs, 0, 0); + $object->trueVolume = $object->trueWidth * $object->trueHeight * $object->trueDepth; $object->volume_units = $object->size_units * 3; } From 0935094385db55f242302918f0964c6b735b5a33 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Wed, 11 Jan 2023 18:22:46 +0100 Subject: [PATCH 470/816] kanban mode for list of loan --- htdocs/loan/class/loan.class.php | 35 ++++++++++++++++++ htdocs/loan/list.php | 62 +++++++++++++++++++++++--------- 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/htdocs/loan/class/loan.class.php b/htdocs/loan/class/loan.class.php index 1c6913035e8..6dd0f5fe92b 100644 --- a/htdocs/loan/class/loan.class.php +++ b/htdocs/loan/class/loan.class.php @@ -721,4 +721,39 @@ class Loan extends CommonObject return -1; } } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'capital')) { + $return .= ' | '.$langs->trans("Amount").' : '.price($this->capital).''; + } + if (property_exists($this, 'datestart')) { + $return .= '
'.$langs->trans("DateStart").' : '.dol_print_date($this->db->jdate($this->datestart), 'day').''; + } + if (property_exists($this, 'dateend')) { + $return .= '
'.$langs->trans("DateEnd").' : '.dol_print_date($this->db->jdate($this->dateend), 'day').''; + } + + if (method_exists($this, 'LibStatut')) { + $return .= '
'.$this->LibStatut($this->totalpaid, 5, $this->alreadypaid).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/loan/list.php b/htdocs/loan/list.php index 1324876a98c..5acd2532bef 100644 --- a/htdocs/loan/list.php +++ b/htdocs/loan/list.php @@ -66,6 +66,8 @@ $search_amount = GETPOST('search_amount', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'loanlist'; // To manage different context of search $optioncss = GETPOST('optioncss', 'alpha'); +$mode = GETPOST('mode', 'alpha'); // mode view result + /* @@ -171,6 +173,9 @@ if ($resql) { $i = 0; $param = ''; + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -194,7 +199,10 @@ if ($resql) { if (!empty($socid)) { $url .= '&socid='.$socid; } - $newcardbutton = dolGetButtonTitle($langs->trans('NewLoan'), '', 'fa fa-plus-circle', $url, '', $user->rights->loan->write); + $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')); + $newcardbutton .= dolGetButtonTitle($langs->trans('NewLoan'), '', 'fa fa-plus-circle', $url, '', $user->rights->loan->write); print ''."\n"; if ($optioncss != '') { @@ -206,6 +214,8 @@ if ($resql) { print ''; print ''; print ''; + print ''; + print_barre_liste($langs->trans("Loans"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'money-bill-alt', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -256,31 +266,49 @@ if ($resql) { $loan_static->label = $obj->label; $loan_static->paid = $obj->paid; - print ''; - // Ref - print ''.$loan_static->getNomUrl(1).''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban + $loan_static->datestart= $obj->datestart; + $loan_static->dateend = $obj->dateend; + $loan_static->capital = $obj->capital; + $loan_static->totalpaid = $obj->paid; - // Label - print ''.dol_trunc($obj->label, 42).''; + print $loan_static->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + print ''; - // Capital - print ''.price($obj->capital).''; + // Ref + print ''.$loan_static->getNomUrl(1).''; - // Date start - print ''.dol_print_date($db->jdate($obj->datestart), 'day').''; + // Label + print ''.dol_trunc($obj->label, 42).''; - // Date end - print ''.dol_print_date($db->jdate($obj->dateend), 'day').''; + // Capital + print ''.price($obj->capital).''; - print ''; - print $loan_static->LibStatut($obj->paid, 5, $obj->alreadypaid); - print ''; + // Date start + print ''.dol_print_date($db->jdate($obj->datestart), 'day').''; - print ''; + // Date end + print ''.dol_print_date($db->jdate($obj->dateend), 'day').''; - print "\n"; + print ''; + print $loan_static->LibStatut($obj->paid, 5, $obj->alreadypaid); + print ''; + print ''; + + print "\n"; + } $i++; } From 7cd1ea4962c46a65913c210d9952da1285de559d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 20:37:29 +0100 Subject: [PATCH 471/816] Fix phpcs --- htdocs/salaries/payments.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/htdocs/salaries/payments.php b/htdocs/salaries/payments.php index 84e146c0bd2..5a5ccb08bf6 100644 --- a/htdocs/salaries/payments.php +++ b/htdocs/salaries/payments.php @@ -592,12 +592,11 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $totalarray['nbfield']++; } - // Date payment - print ''.dol_print_date($db->jdate($obj->datep), 'dayhour', 'tzuserrel')."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - + // Date payment + print ''.dol_print_date($db->jdate($obj->datep), 'dayhour', 'tzuserrel')."\n"; + if (!$i) { + $totalarray['nbfield']++; + } // Ref salary print "".$salstatic->getNomUrl(1)."\n"; From 4afc21ecb3bad84f1cddafbda7cf9cb8277693f6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 20:39:09 +0100 Subject: [PATCH 472/816] Update dict.php --- htdocs/admin/dict.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index e5c9dcb3127..1bf360dccf7 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -2510,11 +2510,11 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') print ''; } elseif ($value == 'block_if_negative') { print ''; - print $form->selectyesno("block_if_negative", (!empty($obj->{$value}) ? $obj->{$value}:''), 1); + print $form->selectyesno("block_if_negative", (empty($obj->block_if_negative) ? '' : $obj->block_if_negative), 1); print ''; } elseif ($value == 'type_duration') { print ''; - print $form->selectTypeDuration('', (!empty($obj->{$value}) ? $obj->{$value}:''), array('i','h')); + print $form->selectTypeDuration('', empty($obj->type_duration) ? '' : $obj->type_duration), array('i','h')); print ''; } else { $fieldValue = isset($obj->{$value}) ? $obj->{$value}: ''; From 71ea83d19e1886f81836d2d79c71aadcf20e5cad Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 20:40:15 +0100 Subject: [PATCH 473/816] Update dict.php --- htdocs/admin/dict.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 1bf360dccf7..4919e377c9c 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -2514,7 +2514,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') print ''; } elseif ($value == 'type_duration') { print ''; - print $form->selectTypeDuration('', empty($obj->type_duration) ? '' : $obj->type_duration), array('i','h')); + print $form->selectTypeDuration('', (empty($obj->type_duration) ? '' : $obj->type_duration), array('i','h')); print ''; } else { $fieldValue = isset($obj->{$value}) ? $obj->{$value}: ''; From 008c74a6bedadc91d0739816cef12dea3dba84a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 11 Jan 2023 20:51:33 +0100 Subject: [PATCH 474/816] Update html.formticket.class.php --- htdocs/core/class/html.formticket.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index a397433979b..be515a2abf3 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -50,7 +50,6 @@ class FormTicket /** * @var string The track_id of the ticket. Used also for the $keytoavoidconflict to name session vars to upload files. - * @deprecated */ public $track_id; From 0303dff199543c3a3b4d5083afc861213fc93a89 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 20:51:55 +0100 Subject: [PATCH 475/816] Merge --- .../class/companybankaccount.class.php | 61 +++++++++++++------ htdocs/societe/paymentmodes.php | 4 +- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/htdocs/societe/class/companybankaccount.class.php b/htdocs/societe/class/companybankaccount.class.php index 26305bb0013..26a6169dbe6 100644 --- a/htdocs/societe/class/companybankaccount.class.php +++ b/htdocs/societe/class/companybankaccount.class.php @@ -35,6 +35,17 @@ class CompanyBankAccount extends Account { public $socid; + /** + * @var string ID to identify managed object + */ + public $element = 'societe_rib'; + + /** + * @var string Name of table without prefix where object is stored + */ + public $table_element = 'societe_rib'; + + /** @var bool $default_rib 1 = this object is the third party's default bank information */ public $default_rib; /** @@ -64,6 +75,13 @@ class CompanyBankAccount extends Account */ public $datem; + /** + * @var string TRIGGER_PREFIX Dolibarr 16.0 and above use the prefix to prevent the creation of inconsistently + * named triggers + * @see CommonObject::call_trigger() + */ + const TRIGGER_PREFIX = 'COMPANY_RIB'; + /** * Constructor @@ -86,7 +104,7 @@ class CompanyBankAccount extends Account * * @param User $user User * @param int $notrigger 1=Disable triggers - * @return int <0 if KO, >= 0 if OK + * @return int <0 if KO, > 0 if OK (ID of newly created company bank account information) */ public function create(User $user = null, $notrigger = 0) { @@ -97,6 +115,7 @@ class CompanyBankAccount extends Account // Check paramaters if (empty($this->socid)) { $this->error = 'BadValueForParameter'; + $this->errors[] = $this->error; return -1; } @@ -114,6 +133,9 @@ class CompanyBankAccount extends Account } } + + $this->db->begin(); + $sql = "INSERT INTO ".MAIN_DB_PREFIX."societe_rib (fk_soc, type, datec)"; $sql .= " VALUES (".((int) $this->socid).", 'ban', '".$this->db->idate($now)."')"; $resql = $this->db->query($sql); @@ -128,19 +150,20 @@ class CompanyBankAccount extends Account $error++; } // End call triggers - - if (!$error) { - return $this->id; - } else { - return 0; - } - } else { - return 1; } } } else { + $error++; $this->error = $this->db->lasterror(); - return 0; + $this->errors[] = $this->error; + } + + if (!$error) { + $this->db->commit(); + return $this->id; + } else { + $this->db->rollback(); + return -1; } } @@ -168,6 +191,8 @@ class CompanyBankAccount extends Account $this->owner_address = dol_trunc($this->owner_address, 254, 'right', 'UTF-8', 1); } + $this->db->begin(); + $sql = "UPDATE ".MAIN_DB_PREFIX."societe_rib SET"; $sql .= " bank = '".$this->db->escape($this->bank)."'"; $sql .= ",code_banque='".$this->db->escape($this->code_banque)."'"; @@ -203,20 +228,22 @@ class CompanyBankAccount extends Account $error++; } // End call triggers - if (!$error) { - return 1; - } else { - return -1; - } - } else { - return 1; } } else { + $error++; if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { $this->error = $langs->trans('ErrorDuplicateField'); } else { $this->error = $this->db->lasterror(); } + $this->errors[] = $this->error; + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); return -1; } } diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 6869e80bd87..744d2763b71 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -183,8 +183,10 @@ if (empty($reshook)) { $companybankaccount->stripe_card_ref = GETPOST('stripe_card_ref', 'alpha'); $result = $companybankaccount->update($user); - if (!$result) { + if ($result <= 0) { + // Display error message and get back to edit mode setEventMessages($companybankaccount->error, $companybankaccount->errors, 'errors'); + $action = 'edit'; } else { // If this account is the default bank account, we disable others if ($companybankaccount->default_rib) { From e4c5fee8df10824a36e9fc71c7bfe7dfc4f41e9c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 21:04:30 +0100 Subject: [PATCH 476/816] Fix hardcoded link. Fix from #23463 --- htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php b/htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php index 192a39c9b06..e2e9fb5f899 100644 --- a/htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php +++ b/htdocs/fourn/commande/tpl/linkedobjectblock.tpl.php @@ -46,7 +46,7 @@ foreach ($linkedObjectBlock as $key => $objectlink) { ?> trans("SupplierOrder"); ?> - trans("ShowOrder"), "order").' '.$objectlink->ref; ?> + getNomUrl(1); ?> ref_supplier; ?> date, 'day'); ?> Date: Wed, 11 Jan 2023 21:06:55 +0100 Subject: [PATCH 477/816] correction bug selection contact dans emailing --- .../core/modules/mailings/contacts1.modules.php | 17 ++++++++++------- .../modules/mailings/thirdparties.modules.php | 13 +++++++------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/htdocs/core/modules/mailings/contacts1.modules.php b/htdocs/core/modules/mailings/contacts1.modules.php index 38a82907124..09595b61376 100644 --- a/htdocs/core/modules/mailings/contacts1.modules.php +++ b/htdocs/core/modules/mailings/contacts1.modules.php @@ -122,7 +122,7 @@ class mailing_contacts1 extends MailingTargets */ public function formFilter() { - global $langs; + global $langs,$conf; // Load translation files required by the page $langs->loadLangs(array("commercial", "companies", "suppliers", "categories")); @@ -307,11 +307,14 @@ class mailing_contacts1 extends MailingTargets $s .= ajax_combobox("filter_category_supplier_contact"); - // Choose language - require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; - $formadmin = new FormAdmin($this->db); - $s .= ''.$langs->trans("DefaultLang").': '; - $s .= $formadmin->select_language($langs->getDefaultLang(1), 'filter_lang', 0, 0, 1, 0, 0, '', 0, 0, 0, null, 1); + // Choose language if multilangue active + + if (@$conf->global->MAIN_MULTILANGS==1) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($this->db); + $s .= ''.$langs->trans("DefaultLang").': '; + $s .= $formadmin->select_language($langs->getDefaultLang(1), 'filter_lang', 0, 0, 1, 0, 0, '', 0, 0, 0, null, 1); + } return $s; } @@ -409,7 +412,7 @@ class mailing_contacts1 extends MailingTargets // Filter on language if (!empty($filter_lang)) { - $sql .= " AND sp.default_lang = '".$this->db->escape($filter_lang)."'"; + $sql .= " AND sp.default_lang LIKE '".$this->db->escape($filter_lang)."%'"; } // Filter on nature diff --git a/htdocs/core/modules/mailings/thirdparties.modules.php b/htdocs/core/modules/mailings/thirdparties.modules.php index 89bc2cf2b5e..81a9bfaea51 100644 --- a/htdocs/core/modules/mailings/thirdparties.modules.php +++ b/htdocs/core/modules/mailings/thirdparties.modules.php @@ -316,12 +316,13 @@ class mailing_thirdparties extends MailingTargets $s .= ''; $s .= ajax_combobox("filter_status_thirdparties"); - // Choose language - require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; - $formadmin = new FormAdmin($this->db); - $s .= ''.$langs->trans("DefaultLang").': '; - $s .= $formadmin->select_language($langs->getDefaultLang(1), 'filter_lang_thirdparties', 0, null, 1, 0, 0, '', 0, 0, 0, null, 1); - + // Choose language if multilangue active + if (@$conf->global->MAIN_MULTILANGS==1) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($this->db); + $s .= ''.$langs->trans("DefaultLang").': '; + $s .= $formadmin->select_language($langs->getDefaultLang(1), 'filter_lang_thirdparties', 0, null, 1, 0, 0, '', 0, 0, 0, null, 1); + } return $s; } From b43f38c7ad67e64261acf6f8c3d77af228ba6cf0 Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sun, 8 Jan 2023 21:43:12 +0100 Subject: [PATCH 478/816] Fix: REST MO API - It's able to have a wrong value on the 'ref' Field --- htdocs/mrp/class/api_mos.class.php | 28 ++++++++++++++++++++++++++++ htdocs/mrp/class/mo.class.php | 1 + 2 files changed, 29 insertions(+) diff --git a/htdocs/mrp/class/api_mos.class.php b/htdocs/mrp/class/api_mos.class.php index 48396025957..794ab3d5378 100644 --- a/htdocs/mrp/class/api_mos.class.php +++ b/htdocs/mrp/class/api_mos.class.php @@ -203,6 +203,9 @@ class Mos extends DolibarrApi foreach ($request_data as $field => $value) { $this->mo->$field = $value; } + + $this->checkRefNumbering(); + if (!$this->mo->create(DolibarrApiAccess::$user)) { throw new RestException(500, "Error creating MO", array_merge(array($this->mo->error), $this->mo->errors)); } @@ -239,6 +242,8 @@ class Mos extends DolibarrApi $this->mo->$field = $value; } + $this->checkRefNumbering(); + if ($this->mo->update(DolibarrApiAccess::$user) > 0) { return $this->get($id); } else { @@ -723,4 +728,27 @@ class Mos extends DolibarrApi } return $myobject; } + + /** + * Validate the ref field and get the next Number if it's necessary. + * + * @return void + */ + private function checkRefNumbering(): void + { + $ref = substr($this->mo->ref, 1, 4); + if ($this->mo->status > 0 && $ref == 'PROV') { + throw new RestException(400, "Wrong naming scheme '(PROV%)' is only allowed on 'DRAFT' status. For automatic increment use 'auto' on the 'ref' field."); + } + + if (strtolower($this->mo->ref) == 'auto') { + if (empty($this->mo->id) && $this->mo->status == 0) { + $this->mo->ref = ''; // 'ref' will auto incremented with '(PROV' + newID + ')' + } else { + $this->mo->fetch_product(); + $numref = $this->mo->getNextNumRef($this->mo->product); + $this->mo->ref = $numref; + } + } + } } diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 30d6a3660a3..13d0f67316c 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -277,6 +277,7 @@ class Mo extends CommonObject if ($this->fk_bom > 0) { // If there is a nown BOM, we force the type of MO to the type of BOM + include_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php'; $tmpbom = new BOM($this->db); $tmpbom->fetch($this->fk_bom); From 12885deb468598be223c441e3b14d4af4d5ec4f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NASSIET?= Date: Wed, 11 Jan 2023 21:19:33 +0100 Subject: [PATCH 479/816] correction bug selection contact dans emailing --- htdocs/core/modules/mailings/contacts1.modules.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/htdocs/core/modules/mailings/contacts1.modules.php b/htdocs/core/modules/mailings/contacts1.modules.php index 7406779054b..be77cf155d2 100644 --- a/htdocs/core/modules/mailings/contacts1.modules.php +++ b/htdocs/core/modules/mailings/contacts1.modules.php @@ -122,7 +122,7 @@ class mailing_contacts1 extends MailingTargets */ public function formFilter() { - global $langs; + global $langs,$conf; // Load translation files required by the page $langs->loadLangs(array("commercial", "companies", "suppliers", "categories")); @@ -308,11 +308,12 @@ class mailing_contacts1 extends MailingTargets $s .= ajax_combobox("filter_category_supplier_contact"); // Choose language - require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; - $formadmin = new FormAdmin($this->db); - $s .= ''.$langs->trans("DefaultLang").': '; - $s .= $formadmin->select_language($langs->getDefaultLang(1), 'filter_lang', 0, 0, 1, 0, 0, '', 0, 0, 0, null, 1); - + if (getDolGlobalInt('MAIN_MULTILANGS')) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($this->db); + $s .= ''.$langs->trans("DefaultLang").': '; + $s .= $formadmin->select_language($langs->getDefaultLang(1), 'filter_lang', 0, 0, 1, 0, 0, '', 0, 0, 0, null, 1); + } return $s; } From db56ef90903460c254e9d0bb742de3c15f0adb9c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 11 Jan 2023 21:32:01 +0100 Subject: [PATCH 480/816] Fix sql error --- htdocs/accountancy/class/bookkeeping.class.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index f880ac6481c..897f60e8aaa 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1168,8 +1168,10 @@ class BookKeeping extends CommonObject $sql = 'SELECT'; $sql .= " t.numero_compte,"; $sql .= " t.label_compte,"; - $sql .= " t.subledger_account,"; - $sql .= " t.subledger_label,"; + if (!empty($option)) { + $sql .= " t.subledger_account,"; + $sql .= " t.subledger_label,"; + } $sql .= " SUM(t.debit) as debit,"; $sql .= " SUM(t.credit) as credit"; $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; @@ -1210,11 +1212,11 @@ class BookKeeping extends CommonObject if (!empty($option)) { $sql .= ' AND t.subledger_account IS NOT NULL'; $sql .= ' AND t.subledger_account != ""'; - $sql .= ' GROUP BY t.subledger_account'; + $sql .= ' GROUP BY t.numero_compte, t.label_compte, t.subledger_account, t.subledger_label'; $sortfield = 't.subledger_account'.($sortfield ? ','.$sortfield : ''); $sortorder = 'ASC'.($sortfield ? ','.$sortfield : ''); } else { - $sql .= ' GROUP BY t.numero_compte'; + $sql .= ' GROUP BY t.numero_compte, t.label_compte'; $sortfield = 't.numero_compte'.($sortfield ? ','.$sortfield : ''); $sortorder = 'ASC'.($sortorder ? ','.$sortorder : ''); } From 303220a88f90501ae466a88fda10938315e67cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NASSIET?= Date: Wed, 11 Jan 2023 22:51:17 +0100 Subject: [PATCH 481/816] ajout d'un hook pour ajouter des landingpage dans la liste de user_ihm --- htdocs/user/param_ihm.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 3d2e3240ce3..1bd806849b6 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -215,6 +215,14 @@ if (isModEnabled('ticket')) { $tmparray['ticket/list.php?mainmenu=ticket&leftmenu='] = 'Tickets'; } +// Hook for insertion new items in the List of possible landing pages +$reshook = $hookmanager->executeHooks('addToLandingPageList',$tmparray,$object); +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} else if ($reshook == 0) { + $tmparray=$hookmanager->resArray; +} + $head = user_prepare_head($object); $title = $langs->trans("User"); From 74a5c91a48238b505dac86fbfe204ce6dc8bdc38 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 11 Jan 2023 21:59:55 +0000 Subject: [PATCH 482/816] Fixing style errors. --- htdocs/user/param_ihm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 1bd806849b6..81ecdca8e73 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -216,10 +216,10 @@ if (isModEnabled('ticket')) { } // Hook for insertion new items in the List of possible landing pages -$reshook = $hookmanager->executeHooks('addToLandingPageList',$tmparray,$object); +$reshook = $hookmanager->executeHooks('addToLandingPageList', $tmparray, $object); if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); -} else if ($reshook == 0) { +} elseif ($reshook == 0) { $tmparray=$hookmanager->resArray; } From 968c50d6f9281ba0705c6e88367580e3cc0b0104 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Thu, 12 Jan 2023 09:49:12 +0100 Subject: [PATCH 483/816] FIX wrong stock list with multicompany and without stock sharing --- 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 79498562210..626d4e81ee2 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -141,7 +141,6 @@ $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // N $sql .= $hookmanager->resPrint; $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as s ON p.rowid = s.fk_product'; -$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot as e ON s.fk_entrepot = e.rowid AND e.entity IN ('.getEntity('stock').')'; if (!empty($conf->global->PRODUCT_USE_UNITS)) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_units as u on p.fk_unit = u.rowid'; } @@ -150,6 +149,7 @@ if ($search_categ > 0) { $sql .= ", ".MAIN_DB_PREFIX."categorie_product as cp"; } $sql .= " WHERE p.entity IN (".getEntity('product').")"; +$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 ($search_categ > 0) { $sql .= " AND p.rowid = cp.fk_product"; // Join for the needed table to filter by categ } From 272f131b070a82ded90ab8fcb4131cd17070066a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Cendrier?= Date: Thu, 12 Jan 2023 10:18:47 +0100 Subject: [PATCH 484/816] do not let closed inventories reset stock with URL --- htdocs/product/inventory/inventory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index fd82300fdda..cbe5d782082 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -118,7 +118,7 @@ if (empty($reshook)) { } // Close inventory by recording the stock movements - if ($action == 'update' && !empty($user->rights->stock->mouvement->creer)) { + if ($action == 'update' && !empty($user->rights->stock->mouvement->creer) && $object->status == $object::STATUS_VALIDATED) { $stockmovment = new MouvementStock($db); $stockmovment->setOrigin($object->element, $object->id); From f251e92eaa54ad11559f3a9eab604aa9f2accf41 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 10:10:28 +0100 Subject: [PATCH 485/816] Fix warning --- htdocs/admin/modulehelp.php | 5 ++++- htdocs/core/modules/DolibarrModules.class.php | 4 ++-- htdocs/public/members/new.php | 3 --- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/admin/modulehelp.php b/htdocs/admin/modulehelp.php index 9a0c34aea2b..1af4b25bb27 100644 --- a/htdocs/admin/modulehelp.php +++ b/htdocs/admin/modulehelp.php @@ -498,7 +498,10 @@ if ($mode == 'feature') { if (isset($objMod->boxes) && is_array($objMod->boxes) && count($objMod->boxes)) { $i = 0; foreach ($objMod->boxes as $val) { - $text .= ($i ? ', ' : '').($val['file'] ? $val['file'] : $val[0]); + $boxstring = (empty($val['file']) ? (empty($val[0]) ? '' : $val[0]) : $val['file']); + if ($boxstring) { + $text .= ($i ? ', ' : '').$boxstring; + } $i++; } } else { diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index f88a05bd12b..96c8d14da31 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -976,8 +976,8 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $tmp = json_decode($obj->note, true); } return array( - 'authorid' => $tmp['authorid'], - 'ip' => $tmp['ip'], + 'authorid' => empty($tmp['authorid']) ? '' : $tmp['authorid'], + 'ip' => empty($tmp['ip']) ? '' : $tmp['ip'], 'lastactivationdate' => $this->db->jdate($obj->tms), 'lastactivationversion' => (!empty($tmp['lastactivationversion']) ? $tmp['lastactivationversion'] : 'unknown'), ); diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php index b37cb15d9c0..7c3e5754b23 100644 --- a/htdocs/public/members/new.php +++ b/htdocs/public/members/new.php @@ -46,9 +46,6 @@ if (!defined('NOLOGIN')) { if (!defined('NOCSRFCHECK')) { define("NOCSRFCHECK", 1); // We accept to go on this page from external web site. } -if (!defined('NOIPCHECK')) { - define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip -} if (!defined('NOBROWSERNOTIF')) { define('NOBROWSERNOTIF', '1'); } From 2093be9895b56ac4042c09cbdd40b9e911bfc7fd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 11:34:28 +0100 Subject: [PATCH 486/816] New add file .idea/php.xml for qodana --- .idea/php.xml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .idea/php.xml diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 00000000000..52e0bf0ae03 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,5 @@ + + + + + From 1ed1ff953f618c4de5fa30a7ef8103d33d172aad Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 11:40:24 +0100 Subject: [PATCH 487/816] Fix .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 55a4c417ce7..e9603bd2d8f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,6 @@ default.properties /.pydevproject /.vscode .DS_Store -.idea *.iml *.orig Thumbs.db From 366abff4f9956281628ad7feeba0db9976381772 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 11:43:10 +0100 Subject: [PATCH 488/816] Avoid qodana error email --- qodana.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qodana.yaml b/qodana.yaml index 89cc459fdfa..44da591f9de 100644 --- a/qodana.yaml +++ b/qodana.yaml @@ -1,6 +1,6 @@ version: "1.0" linter: jetbrains/qodana-php:2022.3-eap -failThreshold: 0 +failThreshold: 20000 profile: name: qodana.recommended exclude: From 1e36b45791634e6668ccd3fe80efc502081544ac Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 11:58:32 +0100 Subject: [PATCH 489/816] Fix missing entity --- 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 40c8fcf4292..1dc632bf13d 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -227,7 +227,7 @@ $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps on p.rowid = ps.fk_pro $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.'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 -$sql .= " WHERE p.entity IN (".getEntity('product').")"; +$sql .= " WHERE p.entity IN (".getEntity('product').") AND e.entity IN (".getEntity('stock').")"; if (!empty($search_categ) && $search_categ != '-1') { $sql .= " AND "; if ($search_categ == -2) { From efe1d913a7e3b470bfcff39722b87d79be2257bc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 12:06:02 +0100 Subject: [PATCH 490/816] Fix MAIN_CHECKBOX_LEFT_COLUMN --- htdocs/product/reassort.php | 36 ++++++++++++++++++++++++++++------ htdocs/product/reassortlot.php | 25 +++++++++++++++++++++-- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index fb74b4ed297..b91ae62f663 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -363,6 +363,13 @@ if ($resql) { // Fields title search print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + $searchpicto = $form->showFilterAndCheckAddButtons(0); + print $searchpicto; + print ''; + } print ''; print ''; print ''; @@ -391,14 +398,20 @@ if ($resql) { $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; - print ''; - $searchpicto = $form->showFilterAndCheckAddButtons(0); - print $searchpicto; - print ''; + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + $searchpicto = $form->showFilterAndCheckAddButtons(0); + print $searchpicto; + print ''; + } print ''; //Line for column titles print ""; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre(''); + } print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder); print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder); if (isModEnabled("service") && $type == 1) { @@ -429,7 +442,10 @@ if ($resql) { $parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; - print_liste_field_titre(''); + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre(''); + } print "\n"; while ($i < min($num, $limit)) { @@ -440,6 +456,10 @@ if ($resql) { $product->load_stock(); print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } print ''; print $product->getNomUrl(1, '', 16); //if ($objp->stock_theorique < $objp->seuil_stock_alerte) print ' '.img_warning($langs->trans("StockTooLow")); @@ -504,7 +524,11 @@ if ($resql) { $parameters = array('obj'=>$objp); $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $product); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; - print ''; + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + print "\n"; $i++; } diff --git a/htdocs/product/reassortlot.php b/htdocs/product/reassortlot.php index 1dc632bf13d..c07f0785e2c 100644 --- a/htdocs/product/reassortlot.php +++ b/htdocs/product/reassortlot.php @@ -514,6 +514,13 @@ print ''; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print ''; @@ -571,6 +578,10 @@ $totalarray['nbfield'] = 0; // Fields title label // -------------------------------------------------------------------- print ''; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre(''); +} print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", '', $param, "", $sortfield, $sortorder); print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", '', $param, "", $sortfield, $sortorder); if (isModEnabled("service") && $type == 1) { @@ -591,7 +602,9 @@ print_liste_field_titre("PhysicalStock", $_SERVER["PHP_SELF"], "stock_physique", print_liste_field_titre(''); print_liste_field_titre("ProductStatusOnSell", $_SERVER["PHP_SELF"], "p.tosell", "", $param, '', $sortfield, $sortorder, 'right '); print_liste_field_titre("ProductStatusOnBuy", $_SERVER["PHP_SELF"], "p.tobuy", "", $param, '', $sortfield, $sortorder, 'right '); -print_liste_field_titre(''); +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print_liste_field_titre(''); +} print "\n"; $product_static = new Product($db); @@ -648,6 +661,11 @@ while ($i < $imaxinloop) { print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + // Ref print ''; - print ''; + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } print "\n"; $i++; From 24651aaa6c060ebaf1d7ad407713a6343c92aaaa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 12:41:02 +0100 Subject: [PATCH 491/816] FIX #22731 #23524 --- htdocs/commande/list.php | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index ed00efdf10a..eb8b824ef3e 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -51,6 +51,7 @@ require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; // Load translation files required by the page $langs->loadLangs(array("orders", 'sendings', 'deliveries', 'companies', 'compta', 'bills', 'stocks', 'products')); +// Get Parameters $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); $show_files = GETPOST('show_files', 'int'); @@ -58,6 +59,7 @@ $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'orderlist'; +// Search Parameters $search_datecloture_start = GETPOST('search_datecloture_start', 'int'); if (empty($search_datecloture_start)) { $search_datecloture_start = dol_mktime(0, 0, 0, GETPOST('search_datecloture_startmonth', 'int'), GETPOST('search_datecloture_startday', 'int'), GETPOST('search_datecloture_startyear', 'int')); @@ -103,6 +105,7 @@ $search_remove_btn = GETPOST('button_removefilter', 'alpha'); $search_project_ref = GETPOST('search_project_ref', 'alpha'); $search_project = GETPOST('search_project', 'alpha'); $search_shippable = GETPOST('search_shippable', 'aZ09'); + $search_fk_cond_reglement = GETPOST("search_fk_cond_reglement", 'int'); $search_fk_shipping_method = GETPOST("search_fk_shipping_method", 'int'); $search_fk_mode_reglement = GETPOST("search_fk_mode_reglement", 'int'); @@ -803,7 +806,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 .= ' FROM '.MAIN_DB_PREFIX.'societe as s'; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)"; @@ -836,7 +839,7 @@ if ($search_user > 0) { // Add table from hooks $parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; $sql .= ' WHERE c.fk_soc = s.rowid'; @@ -1197,7 +1200,7 @@ if ($resql) { // Add $param from hooks $parameters = array(); - $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook + $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 @@ -1364,7 +1367,7 @@ if ($resql) { $moreforfilter .= ''; } $parameters = array(); - $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // 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 { @@ -1575,7 +1578,7 @@ if ($resql) { 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'])) { @@ -1769,7 +1772,7 @@ if ($resql) { 'sortorder' => $sortorder, 'totalarray' => &$totalarray, ); - $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook + $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.date_creation", "", $param, '', $sortfield, $sortorder, 'center nowrap '); @@ -1825,8 +1828,10 @@ if ($resql) { $total_ht = 0; $total_margin = 0; + $savnbfield = $totalarray['nbfield']; + $totalarray = array(); + $totalarray['nbfield'] = 0; $imaxinloop = ($limit ? min($num, $limit) : $num); - $last_num = min($num, $limit); while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); @@ -2063,7 +2068,7 @@ if ($resql) { } // Amount HT if (!empty($arrayfields['c.total_ht']['checked'])) { - print '\n"; + print '\n"; if (!$i) { $totalarray['nbfield']++; } @@ -2247,7 +2252,7 @@ if ($resql) { if (!$i) { $totalarray['pos'][$totalarray['nbfield']] = 'total_mark_rate'; } - if ($i >= $last_num - 1) { + if ($i >= $imaxinloop - 1) { if (!empty($total_ht)) { $totalarray['val']['total_mark_rate'] = price2num($total_margin * 100 / $total_ht, 'MT'); } else { @@ -2260,7 +2265,7 @@ if ($resql) { include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; // Fields from hook $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Date creation @@ -2479,7 +2484,7 @@ if ($resql) { $db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); - $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook + $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; print '
'; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print ''; print ''; print '
'; print $product_static->getNomUrl(1, '', 16); @@ -711,7 +729,10 @@ while ($i < $imaxinloop) { print ''.$product_static->LibStatut($objp->tobuy, 5, 1).'
'.price($obj->total_ht)."'.price($obj->total_ht)."
'."\n"; From 3c7092a114e8151d0c3fe69ad7b1515b53ea771c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 12:49:40 +0100 Subject: [PATCH 492/816] Doxygen --- htdocs/core/class/html.formadmin.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formadmin.class.php b/htdocs/core/class/html.formadmin.class.php index a0d0dd2758e..2cc15a3dd42 100644 --- a/htdocs/core/class/html.formadmin.class.php +++ b/htdocs/core/class/html.formadmin.class.php @@ -36,7 +36,7 @@ class FormAdmin /** * Constructor * - * @param DoliDB $db Database handler + * @param DoliDB|null $db Database handler */ public function __construct($db) { From 4fdf9302694fd39fbe5d496cc6590aa4869319d2 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Thu, 12 Jan 2023 12:49:45 +0100 Subject: [PATCH 493/816] make PDF custom volume work as it work on expedition/card.php --- .../core/modules/expedition/doc/pdf_espadon.modules.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php index 97be43da689..fd5c2ee1980 100644 --- a/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_espadon.modules.php @@ -846,12 +846,13 @@ class pdf_espadon extends ModelePdfExpedition $totalWeighttoshow = showDimensionInBestUnit($object->trueWeight, $object->weight_units, "weight", $outputlangs); } if ($object->trueVolume) { - $totalVolumetoshow = showDimensionInBestUnit($object->trueVolume, $object->volume_units, "volume", $outputlangs); + if ($object->volume_units < 50) { + $totalVolumetoshow = showDimensionInBestUnit($object->trueVolume, $object->volume_units, "volume", $outputlangs); + } else { + $totalVolumetoshow = price($object->trueVolume, 0, $outputlangs, 0, 0).' '.measuringUnitString(0, "volume", $object->volume_units); + } } - - - if ($this->getColumnStatus('desc')) { $this->printStdColumnContent($pdf, $tab2_top, 'desc', $outputlangs->transnoentities("Total")); } From 8c1ce7873f9d0d1d99d3004f5af9335380541489 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 13:02:04 +0100 Subject: [PATCH 494/816] standardize code --- htdocs/fichinter/class/fichinter.class.php | 28 +++++++------- htdocs/reception/class/reception.class.php | 44 +++++++++++----------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 12159f29433..01533698b1c 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -749,25 +749,25 @@ class Fichinter extends CommonObject { // phpcs:enable // Init/load array of translation of status - if (empty($this->statuts) || empty($this->statuts_short) || empty($this->statuts_logo)) { + if (empty($this->labelStatus) || empty($this->labelStatusShort)) { global $langs; $langs->load("fichinter"); - $this->statuts[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); - $this->statuts[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated'); - $this->statuts[self::STATUS_BILLED] = $langs->transnoentitiesnoconv('StatusInterInvoiced'); - $this->statuts[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Done'); - $this->statuts_short[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); - $this->statuts_short[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated'); - $this->statuts_short[self::STATUS_BILLED] = $langs->transnoentitiesnoconv('StatusInterInvoiced'); - $this->statuts_short[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Done'); - $this->statuts_logo[self::STATUS_DRAFT] = 'status0'; - $this->statuts_logo[self::STATUS_VALIDATED] = 'status1'; - $this->statuts_logo[self::STATUS_BILLED] = 'status6'; - $this->statuts_logo[self::STATUS_CLOSED] = 'status6'; + $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); + $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated'); + $this->labelStatus[self::STATUS_BILLED] = $langs->transnoentitiesnoconv('StatusInterInvoiced'); + $this->labelStatus[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Done'); + $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); + $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Validated'); + $this->labelStatusShort[self::STATUS_BILLED] = $langs->transnoentitiesnoconv('StatusInterInvoiced'); + $this->labelStatusShort[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv('Done'); } - return dolGetStatus($this->statuts[$status], $this->statuts_short[$status], '', $this->statuts_logo[$status], $mode); + $statuscode = 'status'.$status; + if ($status == self::STATUS_BILLED || $status == self::STATUS_CLOSED) { + $statuscode = 'status6'; + } + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statuscode, $mode); } /** diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php index 03ed28a2200..e9a89691c88 100644 --- a/htdocs/reception/class/reception.class.php +++ b/htdocs/reception/class/reception.class.php @@ -140,27 +140,6 @@ class Reception extends CommonObject public function __construct($db) { $this->db = $db; - - // List of long language codes for status - $this->statuts = array(); - $this->statuts[-1] = 'StatusReceptionCanceled'; - $this->statuts[0] = 'StatusReceptionDraft'; - // product to receive if stock increase is on close or already received if stock increase is on validation - $this->statuts[1] = 'StatusReceptionValidated'; - if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION")) { - $this->statuts[1] = 'StatusReceptionValidatedReceived'; - } - if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION_CLOSE")) { - $this->statuts[1] = 'StatusReceptionValidatedToReceive'; - } - $this->statuts[2] = 'StatusReceptionProcessed'; - - // List of short language codes for status - $this->statuts_short = array(); - $this->statuts_short[-1] = 'StatusReceptionCanceledShort'; - $this->statuts_short[0] = 'StatusReceptionDraftShort'; - $this->statuts_short[1] = 'StatusReceptionValidatedShort'; - $this->statuts_short[2] = 'StatusReceptionProcessedShort'; } /** @@ -1317,8 +1296,27 @@ class Reception extends CommonObject // phpcs:enable global $langs; - $labelStatus = $langs->transnoentitiesnoconv($this->statuts[$status]); - $labelStatusShort = $langs->transnoentitiesnoconv($this->statuts_short[$status]); + // List of long language codes for status + $this->labelStatus[-1] = 'StatusReceptionCanceled'; + $this->labelStatus[0] = 'StatusReceptionDraft'; + // product to receive if stock increase is on close or already received if stock increase is on validation + $this->labelStatus[1] = 'StatusReceptionValidated'; + if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION")) { + $this->labelStatus[1] = 'StatusReceptionValidatedReceived'; + } + if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION_CLOSE")) { + $this->labelStatus[1] = 'StatusReceptionValidatedToReceive'; + } + $this->labelStatus[2] = 'StatusReceptionProcessed'; + + // List of short language codes for status + $this->labelStatusShort[-1] = 'StatusReceptionCanceledShort'; + $this->labelStatusShort[0] = 'StatusReceptionDraftShort'; + $this->labelStatusShort[1] = 'StatusReceptionValidatedShort'; + $this->labelStatusShort[2] = 'StatusReceptionProcessedShort'; + + $labelStatus = $langs->transnoentitiesnoconv($this->labelStatus[$status]); + $labelStatusShort = $langs->transnoentitiesnoconv($this->labelStatusShort[$status]); $statusType = 'status'.$status; if ($status == self::STATUS_VALIDATED) { From 924679515970789c67d9443e3a2b3c50ffa20f3c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 12:47:57 +0100 Subject: [PATCH 495/816] Fix warning --- htdocs/core/class/utils.class.php | 3 +++ htdocs/core/modules/action/rapport.class.php | 5 +++++ htdocs/modulebuilder/index.php | 2 +- htdocs/public/recruitment/index.php | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index f8096ed84e9..16e000e7f59 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -34,6 +34,9 @@ class Utils */ public $db; + public $error; + public $errors; + public $output; // Used by Cron method to return message public $result; // Used by Cron method to return data diff --git a/htdocs/core/modules/action/rapport.class.php b/htdocs/core/modules/action/rapport.class.php index 8c0964b1378..d91b748d7d5 100644 --- a/htdocs/core/modules/action/rapport.class.php +++ b/htdocs/core/modules/action/rapport.class.php @@ -40,6 +40,11 @@ class CommActionRapport */ public $db; + public $error; + + public $errors; + + /** * @var string description */ diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index a6f3431bd2e..f871d916aa7 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -4461,7 +4461,7 @@ if ($module == 'initmodule') { print ''; print ''; print ' ('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledocpdf), 'dayhour').')'; - print ' '.img_picto($langs->trans("Delete"), 'delete').''; + print ' '.img_picto($langs->trans("Delete"), 'delete').''; } print '
'; diff --git a/htdocs/public/recruitment/index.php b/htdocs/public/recruitment/index.php index 23a180b9a7b..4f82139656c 100644 --- a/htdocs/public/recruitment/index.php +++ b/htdocs/public/recruitment/index.php @@ -252,7 +252,7 @@ if (is_array($results)) { } } print ''; - print $tmpuser->getFullName(-1); + print $tmpuser->getFullName($langs); print '   '.dol_print_email($emailforcontact, 0, 0, 1, 0, 0, 'envelope'); print ''; print '
'; From c50c553999834427c38e0cad55e172f7a9387a0b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 14:40:00 +0100 Subject: [PATCH 496/816] NEW Save date to invalidate other session into user table --- htdocs/install/mysql/migration/17.0.0-18.0.0.sql | 3 +++ htdocs/install/mysql/tables/llx_user.sql | 1 + htdocs/user/class/user.class.php | 10 +++++++--- 3 files changed, 11 insertions(+), 3 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 84022422fba..376d89861f2 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 @@ -56,3 +56,6 @@ ALTER TABLE llx_payment_salary MODIFY COLUMN datep datetime; INSERT INTO llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1179, 117, 'I-28' , 28, 0, '0', 0, '0', 0, 'IGST', 1); INSERT INTO llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1176, 117, 'C+S-18', 0, 9, '1', 9, '1', 0, 'CGST+SGST - Same state sales', 1); + +ALTER TABLE llx_user ADD COLUMN flagdelsessionsbefore datetime DEFAULT NULL; + diff --git a/htdocs/install/mysql/tables/llx_user.sql b/htdocs/install/mysql/tables/llx_user.sql index ca0c7bc818d..a10f8489bcb 100644 --- a/htdocs/install/mysql/tables/llx_user.sql +++ b/htdocs/install/mysql/tables/llx_user.sql @@ -84,6 +84,7 @@ create table llx_user datelastpassvalidation datetime, -- last date we change password or we made a disconnect all datestartvalidity datetime, dateendvalidity datetime, + flagdelsessionsbefore datetime DEFAULT NULL, -- set this to a date if we need to launch an external process to invalidate all sessions for the same login created before this date iplastlogin varchar(250), ippreviouslogin varchar(250), egroupware_id integer, diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 74093af63c6..65a7b7d7842 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1776,9 +1776,9 @@ class User extends CommonObject } } - if ($result > 0 && $member->fk_soc) { // If member is linked to a thirdparty + if ($result > 0 && $member->socid) { // If member is linked to a thirdparty $sql = "UPDATE ".$this->db->prefix()."user"; - $sql .= " SET fk_soc=".((int) $member->fk_soc); + $sql .= " SET fk_soc=".((int) $member->socid); $sql .= " WHERE rowid=".((int) $this->id); dol_syslog(get_class($this)."::create_from_member", LOG_DEBUG); @@ -2243,9 +2243,10 @@ class User extends CommonObject * @param int $notrigger 1=Does not launch triggers * @param int $nosyncmember Do not synchronize linked member * @param int $passwordalreadycrypted 0=Value is cleartext password, 1=Value is crypted value. + * @param int $flagdelsessionsbefore 1=Save also the current date to ask to invalidate all other session before this date. * @return string If OK return clear password, 0 if no change (warning, you may retreive 1 instead of 0 even if password was same), < 0 if error */ - public function setPassword($user, $password = '', $changelater = 0, $notrigger = 0, $nosyncmember = 0, $passwordalreadycrypted = 0) + public function setPassword($user, $password = '', $changelater = 0, $notrigger = 0, $nosyncmember = 0, $passwordalreadycrypted = 0, $flagdelsessionsbefore = 1) { global $conf, $langs; require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; @@ -2297,6 +2298,9 @@ class User extends CommonObject $sql = "UPDATE ".$this->db->prefix()."user"; $sql .= " SET pass_crypted = '".$this->db->escape($password_crypted)."',"; $sql .= " pass_temp = null"; + if (empty($flagdelsessionsbefore)) { + $sql .= ", flagdelsessionsbefore = '".$this->db->idate(dol_now() - 5, 'gmt')."'"; + } if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) { $sql .= ", pass = null"; } else { From 440d72ba9de2f151f6ab21a87db28057eb7f6c1b Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Thu, 12 Jan 2023 15:19:39 +0100 Subject: [PATCH 497/816] kanban mode for list of various payment --- .../bank/class/paymentvarious.class.php | 37 ++ htdocs/compta/bank/various_payment/list.php | 324 ++++++++++-------- 2 files changed, 214 insertions(+), 147 deletions(-) diff --git a/htdocs/compta/bank/class/paymentvarious.class.php b/htdocs/compta/bank/class/paymentvarious.class.php index 3d07c280559..857b49d1576 100644 --- a/htdocs/compta/bank/class/paymentvarious.class.php +++ b/htdocs/compta/bank/class/paymentvarious.class.php @@ -768,4 +768,41 @@ class PaymentVarious extends CommonObject } return 0; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'fk_bank')) { + $return .= ' | '.$this->fk_bank.''; + } + if (property_exists($this, 'datep')) { + $return .= '
'.$langs->trans("Date").' : '.dol_print_date($this->db->jdate($this->datep), 'day').''; + } + if (property_exists($this, 'type_payment') && !empty($this->type_payment)) { + $return .= '
'.$langs->trans("Payment", $this->type_payment).' : '.$this->type_payment.''; + } + if (property_exists($this, 'accountancy_code')) { + $return .= '
'.$langs->trans("Account").' : '.$this->accountancy_code.''; + } + if (property_exists($this, 'amount')) { + $return .= '
'.$langs->trans("Debit").' : '.price($this->amount).''; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/compta/bank/various_payment/list.php b/htdocs/compta/bank/various_payment/list.php index 0721aeb7ef0..9cd43b01924 100644 --- a/htdocs/compta/bank/various_payment/list.php +++ b/htdocs/compta/bank/various_payment/list.php @@ -45,6 +45,7 @@ if ($user->socid) { } $optioncss = GETPOST('optioncss', 'alpha'); +$mode = GETPOST('mode', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $search_ref = GETPOST('search_ref', 'int'); @@ -312,6 +313,9 @@ if ($resql) { $total = 0; $param = ''; + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -362,7 +366,10 @@ if ($resql) { if (!empty($socid)) { $url .= '&socid='.urlencode($socid); } - $newcardbutton = dolGetButtonTitle($langs->trans('MenuNewVariousPayment'), '', 'fa fa-plus-circle', $url, '', $user->rights->banque->modifier); + $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')); + $newcardbutton .= dolGetButtonTitle($langs->trans('MenuNewVariousPayment'), '', 'fa fa-plus-circle', $url, '', $user->rights->banque->modifier); print ''; @@ -375,6 +382,8 @@ if ($resql) { print ''; print ''; print ''; + print ''; + print_barre_liste($langs->trans("MenuVariousPayment"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'object_payment', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -568,166 +577,187 @@ if ($resql) { $variousstatic->id = $obj->rowid; $variousstatic->ref = $obj->rowid; $variousstatic->label = $obj->label; + $variousstatic->datep = $obj->datep; + $variousstatic->type_payment = $obj->payment_code; + $bankline->fetch($obj->fk_bank); + $variousstatic->fk_bank = $bankline->getNomUrl(1); + $variousstatic->amount = $obj->amount; - print ''; + $accountingaccount->fetch('', $obj->accountancy_code, 1); + $variousstatic->accountancy_code = $accountingaccount->getNomUrl(0, 0, 1, $obj->accountingaccount, 1); - // No - if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { - print ''.(($offset * $limit) + $i).''; - } - - // Ref - if ($arrayfields['ref']['checked']) { - print ''.$variousstatic->getNomUrl(1).""; - if (!$i) { - $totalarray['nbfield']++; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } - } + // Output Kanban - // Label payment - if ($arrayfields['label']['checked']) { - print ''.$variousstatic->label.""; - if (!$i) { - $totalarray['nbfield']++; + print $variousstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; } - } + } else { + print ''; - // Date payment - if ($arrayfields['datep']['checked']) { - print ''.dol_print_date($obj->datep, 'day').""; - if (!$i) { - $totalarray['nbfield']++; + // No + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER_IN_LIST)) { + print ''.(($offset * $limit) + $i).''; } - } - - // Date value - if ($arrayfields['datev']['checked']) { - print ''.dol_print_date($obj->datev, 'day').""; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Type - if ($arrayfields['type']['checked']) { - print ''; - if ($obj->payment_code) { - print $langs->trans("PaymentTypeShort".$obj->payment_code); - print ' '; - } - print $obj->num_payment; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Project - if ($arrayfields['project']['checked']) { - print ''; - if ($obj->fk_project > 0) { - $proj->fetch($obj->fk_project); - print $proj->getNomUrl(1); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Bank account - if ($arrayfields['bank']['checked']) { - print ''; - if ($obj->bid > 0) { - $accountstatic->id = $obj->bid; - $accountstatic->ref = $obj->bref; - $accountstatic->number = $obj->bnumber; - - if (isModEnabled('accounting')) { - $accountstatic->account_number = $obj->bank_account_number; - $accountingjournal->fetch($obj->accountancy_journal); - $accountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + // Ref + if ($arrayfields['ref']['checked']) { + print ''.$variousstatic->getNomUrl(1).""; + if (!$i) { + $totalarray['nbfield']++; } - - $accountstatic->label = $obj->blabel; - print $accountstatic->getNomUrl(1); - } else { - print ' '; } - print ''; + + // Label payment + if ($arrayfields['label']['checked']) { + print ''.$variousstatic->label.""; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Date payment + if ($arrayfields['datep']['checked']) { + print ''.dol_print_date($obj->datep, 'day').""; + if (!$i) { + $totalarray['nbfield']++; + } + } + + + // Date value + if ($arrayfields['datev']['checked']) { + print ''.dol_print_date($obj->datev, 'day').""; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Type + if ($arrayfields['type']['checked']) { + print ''; + if ($obj->payment_code) { + print $langs->trans("PaymentTypeShort".$obj->payment_code); + print ' '; + } + print $obj->num_payment; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Project + if ($arrayfields['project']['checked']) { + print ''; + if ($obj->fk_project > 0) { + $proj->fetch($obj->fk_project); + print $proj->getNomUrl(1); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Bank account + if ($arrayfields['bank']['checked']) { + print ''; + if ($obj->bid > 0) { + $accountstatic->id = $obj->bid; + $accountstatic->ref = $obj->bref; + $accountstatic->number = $obj->bnumber; + + if (isModEnabled('accounting')) { + $accountstatic->account_number = $obj->bank_account_number; + $accountingjournal->fetch($obj->accountancy_journal); + $accountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); + } + + $accountstatic->label = $obj->blabel; + print $accountstatic->getNomUrl(1); + } else { + print ' '; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Bank entry + if ($arrayfields['entry']['checked']) { + $bankline->fetch($obj->fk_bank); + print ''.$bankline->getNomUrl(1).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Accounting account + if (!empty($arrayfields['account']['checked'])) { + $accountingaccount->fetch('', $obj->accountancy_code, 1); + + print ''.$accountingaccount->getNomUrl(0, 1, 1, '', 1).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Accounting subledger account + if (!empty($arrayfields['subledger']['checked'])) { + print ''.length_accounta($obj->subledger_account).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Debit + if ($arrayfields['debit']['checked']) { + print ''; + if ($obj->sens == 0) { + print ''.price($obj->amount).''; + $totalarray['val']['total_deb'] += $obj->amount; + } + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_deb'; + } + print ''; + } + + // Credit + if ($arrayfields['credit']['checked']) { + print ''; + if ($obj->sens == 1) { + print ''.price($obj->amount).''; + $totalarray['val']['total_cred'] += $obj->amount; + } + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'total_cred'; + } + print ''; + } + + print ''; + if (!$i) { $totalarray['nbfield']++; } + + print ''."\n"; } - - // Bank entry - if ($arrayfields['entry']['checked']) { - $bankline->fetch($obj->fk_bank); - print ''.$bankline->getNomUrl(1).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Accounting account - if (!empty($arrayfields['account']['checked'])) { - $accountingaccount->fetch('', $obj->accountancy_code, 1); - - print ''.$accountingaccount->getNomUrl(0, 1, 1, '', 1).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Accounting subledger account - if (!empty($arrayfields['subledger']['checked'])) { - print ''.length_accounta($obj->subledger_account).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Debit - if ($arrayfields['debit']['checked']) { - print ''; - if ($obj->sens == 0) { - print ''.price($obj->amount).''; - $totalarray['val']['total_deb'] += $obj->amount; - } - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'total_deb'; - } - print ''; - } - - // Credit - if ($arrayfields['credit']['checked']) { - print ''; - if ($obj->sens == 1) { - print ''.price($obj->amount).''; - $totalarray['val']['total_cred'] += $obj->amount; - } - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'total_cred'; - } - print ''; - } - - print ''; - - if (!$i) { - $totalarray['nbfield']++; - } - - print ''."\n"; - $i++; } From a68df8e9f573751eff25ca66ee4e3b1d630d7318 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Thu, 12 Jan 2023 16:16:23 +0100 Subject: [PATCH 498/816] kanban mode for list of banks --- htdocs/compta/bank/class/account.class.php | 33 ++ htdocs/compta/bank/list.php | 429 +++++++++++---------- 2 files changed, 258 insertions(+), 204 deletions(-) diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index a73fd2b5f2c..5332150dfb4 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -1748,6 +1748,39 @@ class Account extends CommonObject return false; } } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + + if (property_exists($this, 'type_lib')) { + $return .= '
'.substr($this->type_lib[$this->type], 0, 24).'...'; + } + if (method_exists($this, 'solde')) { + $return .= '
'; + $return .= ''.$langs->trans("Balance").' : '.price($this->solde(1), 0, $langs, 1, -1, -1, $this->currency_code).''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/compta/bank/list.php b/htdocs/compta/bank/list.php index 38b666cc2ef..8efe9451b64 100644 --- a/htdocs/compta/bank/list.php +++ b/htdocs/compta/bank/list.php @@ -52,6 +52,7 @@ $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bankaccountlist'; // To manage different context of search +$mode = GETPOST('mode', 'alpha'); $search_ref = GETPOST('search_ref', 'alpha'); $search_label = GETPOST('search_label', 'alpha'); @@ -305,6 +306,9 @@ llxHeader('', $title, $help_url); $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); } @@ -365,8 +369,13 @@ print ''; print ''; print ''; +print ''; -$newcardbutton = dolGetButtonTitle($langs->trans('NewFinancialAccount'), '', 'fa fa-plus-circle', 'card.php?action=create', '', $user->rights->banque->configurer); + +$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')); +$newcardbutton .= dolGetButtonTitle($langs->trans('NewFinancialAccount'), '', 'fa fa-plus-circle', 'card.php?action=create', '', $user->rights->banque->configurer); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'bank_account', 0, $newcardbutton, '', $limit, 1); @@ -584,224 +593,236 @@ foreach ($accounts as $key => $type) { $lastcurrencycode = $objecttmp->currency_code; } - print ''; - // 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($objecttmp->id, $arrayofselected)) { - $selected = 1; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban + print $objecttmp->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + print ''; + // 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($objecttmp->id, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print ''; } - print ''; - } - // Ref - if (!empty($arrayfields['b.ref']['checked'])) { - print ''.$objecttmp->getNomUrl(1).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Label - if (!empty($arrayfields['b.label']['checked'])) { - print ''.dol_escape_htmltag($objecttmp->label).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Account type - if (!empty($arrayfields['accountype']['checked'])) { - print ''; - print $objecttmp->type_lib[$objecttmp->type]; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Number - if (!empty($arrayfields['b.number']['checked'])) { - print ''.dol_escape_htmltag($objecttmp->number).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Account number - if (!empty($arrayfields['b.account_number']['checked'])) { - print ''; - if (isModEnabled('accounting') && !empty($objecttmp->account_number)) { - $accountingaccount = new AccountingAccount($db); - $accountingaccount->fetch('', $objecttmp->account_number, 1); - print ''; - print $accountingaccount->getNomUrl(0, 1, 1, '', 0); - print ''; - } else { - print ''.$objecttmp->account_number.''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Accountancy journal - if (!empty($arrayfields['b.fk_accountancy_journal']['checked'])) { - print ''; - if (isModEnabled('accounting')) { - if (empty($objecttmp->fk_accountancy_journal)) { - print img_warning($langs->trans("Mandatory")); - } else { - $accountingjournal = new AccountingJournal($db); - $accountingjournal->fetch($objecttmp->fk_accountancy_journal); - print $accountingjournal->getNomUrl(0, 1, 1, '', 1); + // Ref + if (!empty($arrayfields['b.ref']['checked'])) { + print ''.$objecttmp->getNomUrl(1).''; + if (!$i) { + $totalarray['nbfield']++; } - } else { - print ''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Currency - if (!empty($arrayfields['b.currency_code']['checked'])) { - print ''; - print $objecttmp->currency_code; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Transactions to reconcile - if (!empty($arrayfields['toreconcile']['checked'])) { - $conciliate = $objecttmp->canBeConciliated(); - - $labeltoshow = ''; - if ($conciliate == -2) { - $labeltoshow = $langs->trans("CashAccount"); - } elseif ($conciliate == -3) { - $labeltoshow = $langs->trans("Closed"); - } elseif (empty($objecttmp->rappro)) { - $labeltoshow = $langs->trans("ConciliationDisabled"); } - print ''; - if ($conciliate == -2) { - print ''.$langs->trans("CashAccount").''; - } elseif ($conciliate == -3) { - print ''.$langs->trans("Closed").''; - } elseif (empty($objecttmp->rappro)) { - print ''.$langs->trans("ConciliationDisabled").''; - } else { - $result = $objecttmp->load_board($user, $objecttmp->id); - if (is_numeric($result) && $result < 0) { - setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); - } else { - print '
'; - print ''; - print $result->nbtodo; + // Label + if (!empty($arrayfields['b.label']['checked'])) { + print ''.dol_escape_htmltag($objecttmp->label).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Account type + if (!empty($arrayfields['accountype']['checked'])) { + print ''; + print $objecttmp->type_lib[$objecttmp->type]; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Number + if (!empty($arrayfields['b.number']['checked'])) { + print ''.dol_escape_htmltag($objecttmp->number).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Account number + if (!empty($arrayfields['b.account_number']['checked'])) { + print ''; + if (isModEnabled('accounting') && !empty($objecttmp->account_number)) { + $accountingaccount = new AccountingAccount($db); + $accountingaccount->fetch('', $objecttmp->account_number, 1); + print ''; + print $accountingaccount->getNomUrl(0, 1, 1, '', 0); print ''; - print ''; - if ($result->nbtodolate) { - print ''; - print ' '.$result->nbtodolate; + } else { + print ''.$objecttmp->account_number.''; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Accountancy journal + if (!empty($arrayfields['b.fk_accountancy_journal']['checked'])) { + print ''; + if (isModEnabled('accounting')) { + if (empty($objecttmp->fk_accountancy_journal)) { + print img_warning($langs->trans("Mandatory")); + } else { + $accountingjournal = new AccountingJournal($db); + $accountingjournal->fetch($objecttmp->fk_accountancy_journal); + print $accountingjournal->getNomUrl(0, 1, 1, '', 1); + } + } else { + print ''; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Currency + if (!empty($arrayfields['b.currency_code']['checked'])) { + print ''; + print $objecttmp->currency_code; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Transactions to reconcile + if (!empty($arrayfields['toreconcile']['checked'])) { + $conciliate = $objecttmp->canBeConciliated(); + + $labeltoshow = ''; + if ($conciliate == -2) { + $labeltoshow = $langs->trans("CashAccount"); + } elseif ($conciliate == -3) { + $labeltoshow = $langs->trans("Closed"); + } elseif (empty($objecttmp->rappro)) { + $labeltoshow = $langs->trans("ConciliationDisabled"); + } + + print ''; + if ($conciliate == -2) { + print ''.$langs->trans("CashAccount").''; + } elseif ($conciliate == -3) { + print ''.$langs->trans("Closed").''; + } elseif (empty($objecttmp->rappro)) { + print ''.$langs->trans("ConciliationDisabled").''; + } else { + $result = $objecttmp->load_board($user, $objecttmp->id); + if (is_numeric($result) && $result < 0) { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + } else { + print ''; + print ''; + print $result->nbtodo; print ''; + print ''; + if ($result->nbtodolate) { + print ''; + print ' '.$result->nbtodolate; + print ''; + } } } - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Extra fields - if (is_array($objecttmp->array_options)) { - $obj = new stdClass(); - foreach ($objecttmp->array_options as $k => $v) { - $obj->$k = $v; - } - } - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $objecttmp, $action); // Note that $action and $objecttmpect may have been modified by hook - print $hookmanager->resPrint; - // Date creation - if (!empty($arrayfields['b.datec']['checked'])) { - print ''; - print dol_print_date($objecttmp->date_creation, 'dayhour'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['b.tms']['checked'])) { - print ''; - print dol_print_date($objecttmp->date_update, 'dayhour'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Status - if (!empty($arrayfields['b.clos']['checked'])) { - print ''.$objecttmp->getLibStatut(5).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // Balance - if (!empty($arrayfields['balance']['checked'])) { - print ''; - print ''; - print ''.price($solde, 0, $langs, 1, -1, -1, $objecttmp->currency_code).''; - print ''; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'balance'; - } - $totalarray['val']['balance'] += $solde; - } - - // 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($objecttmp->id, $arrayofselected)) { - $selected = 1; + print ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; } - print ''; - } - if (!$i) { - $totalarray['nbfield']++; - } - print ''; + // Extra fields + if (is_array($objecttmp->array_options)) { + $obj = new stdClass(); + foreach ($objecttmp->array_options as $k => $v) { + $obj->$k = $v; + } + } + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $objecttmp, $action); // Note that $action and $objecttmpect may have been modified by hook + print $hookmanager->resPrint; + // Date creation + if (!empty($arrayfields['b.datec']['checked'])) { + print ''; + print dol_print_date($objecttmp->date_creation, 'dayhour'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['b.tms']['checked'])) { + print ''; + print dol_print_date($objecttmp->date_update, 'dayhour'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } - if (empty($total[$objecttmp->currency_code])) { - $total[$objecttmp->currency_code] = $solde; - } else { - $total[$objecttmp->currency_code] += $solde; + // Status + if (!empty($arrayfields['b.clos']['checked'])) { + print ''.$objecttmp->getLibStatut(5).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // Balance + if (!empty($arrayfields['balance']['checked'])) { + print ''; + print ''; + print ''.price($solde, 0, $langs, 1, -1, -1, $objecttmp->currency_code).''; + print ''; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'balance'; + } + $totalarray['val']['balance'] += $solde; + } + + // 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($objecttmp->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + + print ''; + + if (empty($total[$objecttmp->currency_code])) { + $total[$objecttmp->currency_code] = $solde; + } else { + $total[$objecttmp->currency_code] += $solde; + } } - $i++; } From 551daa5ca1806e0ac4d272a10a787ebf1b326a33 Mon Sep 17 00:00:00 2001 From: hystepik Date: Thu, 12 Jan 2023 16:26:39 +0100 Subject: [PATCH 499/816] New : Add reload of modules in configuration --- htdocs/admin/modules.php | 54 +++++++++++++++++++++++++++++++++++ htdocs/core/lib/admin.lib.php | 15 ++++++---- htdocs/langs/en_US/admin.lang | 2 ++ 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index e93b5a58e96..db019bd262a 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -282,10 +282,39 @@ if ($action == 'set' && $user->admin) { } header("Location: ".$_SERVER["PHP_SELF"]."?mode=".$mode.$param.($page_y ? '&page_y='.$page_y : '')); exit; +} elseif (getDolGlobalInt("MAIN_FEATURES_LEVEL") > 1 && $action == 'reload' && $user->admin && GETPOST('confirm') == 'yes') { + $result = unActivateModule($value, 0); + dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity); + if ($result) { + setEventMessages($result, null, 'errors'); + header("Location: ".$_SERVER["PHP_SELF"]."?mode=".$mode.$param.($page_y ? '&page_y='.$page_y : '')); + } + $resarray = activateModule($value, 0, 1); + dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", (int) $conf->global->MAIN_IHM_PARAMS_REV + 1, 'chaine', 0, '', $conf->entity); + if (!empty($resarray['errors'])) { + setEventMessages('', $resarray['errors'], 'errors'); + } else { + if ($resarray['nbperms'] > 0) { + $tmpsql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."user WHERE admin <> 1"; + $resqltmp = $db->query($tmpsql); + if ($resqltmp) { + $obj = $db->fetch_object($resqltmp); + if ($obj && $obj->nb > 1) { + $msg = $langs->trans('ModuleEnabledAdminMustCheckRights'); + setEventMessages($msg, null, 'warnings'); + } + } else { + dol_print_error($db); + } + } + } + header("Location: ".$_SERVER["PHP_SELF"]."?mode=".$mode.$param.($page_y ? '&page_y='.$page_y : '')); + exit; } + /* * View */ @@ -464,6 +493,19 @@ if ($action == 'reset_confirm' && $user->admin) { } } +if ($action == 'reload_confirm' && $user->admin) { + if (!empty($modules[$value])) { + $objMod = $modules[$value]; + + if (!empty($objMod->langfiles)) { + $langs->loadLangs($objMod->langfiles); + } + + $form = new Form($db); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?value='.$value.'&mode='.$mode.$param, $langs->trans('ConfirmReload'), $langs->trans(GETPOST('confirm_message_code')), 'reload', '', 'no', 1); + } +} + print $formconfirm; asort($orders); @@ -802,10 +844,22 @@ if ($mode == 'common' || $mode == 'commonkanban') { $codeenabledisable .= 'warnings_unactivation[$mysoc->country_code]).'&value='.$modName.'&mode='.$mode.$param.'">'; $codeenabledisable .= img_picto($langs->trans("Activated"), 'switch_on'); $codeenabledisable .= ''; + if (getDolGlobalInt("MAIN_FEATURES_LEVEL") > 1) { + $codeenabledisable .= ' '; + $codeenabledisable .= ''; + $codeenabledisable .= img_picto($langs->trans("Reload"), 'refresh', 'class="fa-15"'); + $codeenabledisable .= ''; + } } else { $codeenabledisable .= ''; $codeenabledisable .= img_picto($langs->trans("Activated"), 'switch_on'); $codeenabledisable .= ''; + if (getDolGlobalInt("MAIN_FEATURES_LEVEL") > 1) { + $codeenabledisable .= ' '; + $codeenabledisable .= ''; + $codeenabledisable .= img_picto($langs->trans("Reload"), 'refresh', 'class="fa-15"'); + $codeenabledisable .= ''; + } } } diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 71bcc082961..92895793082 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -1084,11 +1084,12 @@ function purgeSessions($mysessionid) /** * Enable a module * - * @param string $value Name of module to activate - * @param int $withdeps Activate/Disable also all dependencies - * @return array array('nbmodules'=>nb modules activated with success, 'errors=>array of error messages, 'nbperms'=>Nb permission added); + * @param string $value Name of module to activate + * @param int $withdeps Activate/Disable also all dependencies + * @param int $noconfverification Remove verification of $conf variable for module + * @return array array('nbmodules'=>nb modules activated with success, 'errors=>array of error messages, 'nbperms'=>Nb permission added); */ -function activateModule($value, $withdeps = 1) +function activateModule($value, $withdeps = 1, $noconfverification = 0) { global $db, $langs, $conf, $mysoc; @@ -1144,8 +1145,10 @@ function activateModule($value, $withdeps = 1) } $const_name = $objMod->const_name; - if (!empty($conf->global->$const_name)) { - return $ret; + if ($noconfverification == 0) { + if (!empty($conf->global->$const_name)) { + return $ret; + } } $result = $objMod->init(); // Enable module diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 421ba4f6fa2..34bae07fc37 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2357,3 +2357,5 @@ AllowExternalDownload=Allow external download (without login, using a shared lin DeadlineDayVATSubmission=Deadline day for vat submission on the next month MaxNumberOfAttachementOnForms=Max number of joinded files in a form IfDefinedUseAValueBeetween=If defined, use a value between %s and %s +Reload=Reload +ConfirmReload=Confirm module reload \ No newline at end of file From 8a5423b464df64b3c825efc47901f2ec1c61342d Mon Sep 17 00:00:00 2001 From: hystepik Date: Thu, 12 Jan 2023 16:29:58 +0100 Subject: [PATCH 500/816] add newline end of file --- htdocs/langs/en_US/admin.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 34bae07fc37..cfe01784bea 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2358,4 +2358,4 @@ DeadlineDayVATSubmission=Deadline day for vat submission on the next month MaxNumberOfAttachementOnForms=Max number of joinded files in a form IfDefinedUseAValueBeetween=If defined, use a value between %s and %s Reload=Reload -ConfirmReload=Confirm module reload \ No newline at end of file +ConfirmReload=Confirm module reload From 23f89c9134640099ca5fa02bea86dff01864b392 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 17:59:19 +0100 Subject: [PATCH 501/816] Missing photo --- htdocs/salaries/list.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/salaries/list.php b/htdocs/salaries/list.php index 17addfa22f4..d2344f378a0 100644 --- a/htdocs/salaries/list.php +++ b/htdocs/salaries/list.php @@ -458,7 +458,7 @@ if (isModEnabled("banque")) { // Amount print ''; -//Status +// Status print ''; $liststatus = array('0' => $langs->trans("Unpaid"), '1' => $langs->trans("Paid")); print $form->selectarray('search_status', $liststatus, $search_status, 1, 0, 0, '', 0, 0, 0, '', 'search_status width100 onrightofpage'); @@ -538,7 +538,8 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $userstatic->login = $obj->login; $userstatic->email = $obj->email; $userstatic->socid = $obj->fk_soc; - $userstatic->statut = $obj->status; + $userstatic->statut = $obj->status; // deprecated + $userstatic->status = $obj->status; $salstatic->id = $obj->rowid; $salstatic->ref = $obj->rowid; @@ -590,7 +591,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } // Employee - print ''.$userstatic->getNomUrl(1)."\n"; + print ''.$userstatic->getNomUrl(-1)."\n"; if (!$i) { $totalarray['nbfield']++; } @@ -637,7 +638,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } } - // if (!$i) $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; + // if (!$i) $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; // Amount print ''.price($obj->amount).''; From 3ae453136b1d6cbf4011e5d2509ff538cfa252ed Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 18:06:26 +0100 Subject: [PATCH 502/816] Fix error --- htdocs/install/upgrade2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index c9f1eb76b41..1e153109140 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -4196,7 +4196,7 @@ function migrate_delete_old_dir($db, $langs, $conf) } foreach ($filetodeletearray as $filetodelete) { - //print ''.$filetodelete."
\n"; + $result = 1; if (file_exists($filetodelete)) { $result = dol_delete_dir_recursive($filetodelete); } From dac735dc4be9984266df767ff6de606afb2f6b20 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 18:11:10 +0100 Subject: [PATCH 503/816] Fix missing photo --- htdocs/salaries/list.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/salaries/list.php b/htdocs/salaries/list.php index d2344f378a0..fbbac2a2f3b 100644 --- a/htdocs/salaries/list.php +++ b/htdocs/salaries/list.php @@ -224,7 +224,7 @@ $now = dol_now(); $help_url = ''; $title = $langs->trans('Salaries'); -$sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.login, u.email, u.admin, u.salary as current_salary, u.fk_soc as fk_soc, u.statut as status,"; +$sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.login, u.email, u.admin, u.photo, u.salary as current_salary, u.fk_soc as fk_soc, u.statut as status,"; $sql .= " s.rowid, s.fk_account, s.paye, s.fk_user, s.amount, s.salary, s.label, s.datesp, s.dateep, s.fk_typepayment as paymenttype, "; $sql .= " ba.rowid as bid, ba.ref as bref, ba.number as bnumber, ba.account_number, ba.fk_accountancy_journal, ba.label as blabel, ba.iban_prefix as iban, ba.bic, ba.currency_code, ba.clos,"; $sql .= " pst.code as payment_code,"; @@ -540,6 +540,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $userstatic->socid = $obj->fk_soc; $userstatic->statut = $obj->status; // deprecated $userstatic->status = $obj->status; + $userstatic->photo = $obj->photo; $salstatic->id = $obj->rowid; $salstatic->ref = $obj->rowid; From 7124a59110b4c9c3fd60a449d3c367281461b2eb Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Thu, 12 Jan 2023 18:28:57 +0100 Subject: [PATCH 504/816] kanban mode for list of prelevement orders --- .../class/bonprelevement.class.php | 34 +++++++++++++ htdocs/compta/prelevement/orders_list.php | 49 ++++++++++++++----- 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 959630a5538..e8e511f8c87 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -2397,4 +2397,38 @@ class BonPrelevement extends CommonObject */ return 0; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + + + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + + if (property_exists($this, 'date_echeance')) { + $return .= '
'.$langs->trans("Date").' : '.dol_print_date($this->db->jdate($this->date_echeance), 'day').''; + } + if (property_exists($this, 'total')) { + $return .= '
'.$langs->trans("Amount").' : '.price($this->total).''; + } + if (method_exists($this, 'LibStatut')) { + $return .= '
'.$this->LibStatut($this->statut, 5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/compta/prelevement/orders_list.php b/htdocs/compta/prelevement/orders_list.php index 01ef33eea9d..bead580ab31 100644 --- a/htdocs/compta/prelevement/orders_list.php +++ b/htdocs/compta/prelevement/orders_list.php @@ -54,6 +54,8 @@ if (!$sortfield) { } $optioncss = GETPOST('optioncss', 'alpha'); +$mode = GETPOST('mode', 'alpha'); + // Get supervariables $statut = GETPOST('statut', 'int'); @@ -147,6 +149,9 @@ if ($result) { $i = 0; $param = ''; + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -161,6 +166,8 @@ if ($result) { $selectedfields = ''; $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 ($usercancreate) { $newcardbutton .= dolGetButtonTitle($langs->trans('NewStandingOrder'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/compta/prelevement/create.php?type='.urlencode($type)); } @@ -176,6 +183,8 @@ if ($result) { print ''; print ''; print ''; + print ''; + if ($type != '') { print ''; } @@ -220,27 +229,41 @@ if ($result) { $directdebitorder->id = $obj->rowid; $directdebitorder->ref = $obj->ref; - $directdebitorder->datec = $obj->datec; - $directdebitorder->amount = $obj->amount; + $directdebitorder->date_echeance = $obj->datec; + $directdebitorder->total = $obj->amount; $directdebitorder->statut = $obj->statut; - print ''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban - print ''; - print $directdebitorder->getNomUrl(1); - print "\n"; + print $directdebitorder->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + print ''; - print ''.dol_print_date($db->jdate($obj->datec), 'day')."\n"; + print ''; + print $directdebitorder->getNomUrl(1); + print "\n"; - print ''.price($obj->amount)."\n"; + print ''.dol_print_date($db->jdate($obj->datec), 'day')."\n"; - print ''; - print $bon->LibStatut($obj->statut, 5); - print ''; + print ''.price($obj->amount)."\n"; - print ''."\n"; + print ''; + print $bon->LibStatut($obj->statut, 5); + print ''; - print "\n"; + print ''."\n"; + + print "\n"; + } $i++; } } else { From 68370083985e998642eba61b7e15d925a0423582 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Thu, 12 Jan 2023 18:53:27 +0100 Subject: [PATCH 505/816] kanban view for ligne prelevement --- htdocs/compta/prelevement/list.php | 117 +++++++++++++++++------------ 1 file changed, 71 insertions(+), 46 deletions(-) diff --git a/htdocs/compta/prelevement/list.php b/htdocs/compta/prelevement/list.php index 4906313cad1..8d9489bbec7 100644 --- a/htdocs/compta/prelevement/list.php +++ b/htdocs/compta/prelevement/list.php @@ -43,6 +43,7 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'directdebitcredittransferlinelist'; // 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', 'alpha'); $type = GETPOST('type', 'aZ09'); @@ -188,12 +189,18 @@ if ($result) { $param = "&statut=".urlencode($statut); $param .= "&search_bon=".urlencode($search_bon); + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if ($type == 'bank-transfer') { $param .= '&type=bank-transfer'; } if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } + $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')); print"\n\n"; print ''."\n"; @@ -206,6 +213,8 @@ if ($result) { print ''; print ''; print ''; + print ''; + if ($type != '') { print ''; } @@ -214,7 +223,7 @@ if ($result) { if ($type == 'bank-transfer') { $title = $langs->trans("CreditTransferLines"); } - print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'generic', 0, '', '', $limit, 0, 0, 1); + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'generic', 0, $newcardbutton, '', $limit, 0, 0, 1); $moreforfilter = ''; @@ -262,61 +271,77 @@ if ($result) { $bon->id = $obj->rowid; $bon->ref = $obj->ref; $bon->statut = $obj->status; + $bon->date_echeance = $obj->datec; + $bon->total = $obj->amount; $company->id = $obj->socid; $company->name = $obj->name; $company->email = $obj->email; $company->code_client = $obj->code_client; - print ''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban - print ''; - print $bon->getNomUrl(1); - print "\n"; + print $bon->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + print ''; - print ''; - print $line->LibStatut($obj->statut_ligne, 2); - print " "; - print ''; - print substr('000000'.$obj->rowid_ligne, -6); - print ''; + print ''; + print $bon->getNomUrl(1); + print "\n"; - print ''; - $link_to_bill = '/compta/facture/card.php?facid='; - $link_title = 'Invoice'; - $link_picto = 'bill'; - if ($type == 'bank-transfer') { - $link_to_bill = '/fourn/facture/card.php?facid='; - $link_title = 'SupplierInvoice'; - $link_picto = 'supplier_invoice'; + print ''; + print $line->LibStatut($obj->statut_ligne, 2); + print " "; + print ''; + print substr('000000'.$obj->rowid_ligne, -6); + print ''; + + print ''; + $link_to_bill = '/compta/facture/card.php?facid='; + $link_title = 'Invoice'; + $link_picto = 'bill'; + if ($type == 'bank-transfer') { + $link_to_bill = '/fourn/facture/card.php?facid='; + $link_title = 'SupplierInvoice'; + $link_picto = 'supplier_invoice'; + } + print ''; + print img_object($langs->trans($link_title), $link_picto); + print ' '.$obj->invoiceref."\n"; + print ''; + print ''; + + print ''; + print $company->getNomUrl(1); + print "\n"; + + + print ''; + $link_to_tab = '/comm/card.php?socid='; + $link_code = $obj->code_client; + if ($type == 'bank-transfer') { + $link_to_tab = '/fourn/card.php?socid='; + $link_code = $obj->code_fournisseur; + } + print ''.$link_code."\n"; + + print ''.dol_print_date($db->jdate($obj->datec), 'day')."\n"; + + print ''.price($obj->amount)."\n"; + + print ' '; + + print "\n"; } - print ''; - print img_object($langs->trans($link_title), $link_picto); - print ' '.$obj->invoiceref."\n"; - print ''; - print ''; - - print ''; - print $company->getNomUrl(1); - print "\n"; - - - print ''; - $link_to_tab = '/comm/card.php?socid='; - $link_code = $obj->code_client; - if ($type == 'bank-transfer') { - $link_to_tab = '/fourn/card.php?socid='; - $link_code = $obj->code_fournisseur; - } - print ''.$link_code."\n"; - - print ''.dol_print_date($db->jdate($obj->datec), 'day')."\n"; - - print ''.price($obj->amount)."\n"; - - print ' '; - - print "\n"; $i++; } } else { From 468b8bcab38e0b0ec6bc5f8226bc0758c776c405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NASSIET?= Date: Thu, 12 Jan 2023 19:26:55 +0100 Subject: [PATCH 506/816] correction bug si pas reponse sur le hook --- htdocs/user/param_ihm.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 81ecdca8e73..2f8f4ae24ad 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -216,11 +216,13 @@ if (isModEnabled('ticket')) { } // Hook for insertion new items in the List of possible landing pages -$reshook = $hookmanager->executeHooks('addToLandingPageList', $tmparray, $object); -if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); -} elseif ($reshook == 0) { - $tmparray=$hookmanager->resArray; +$reshook = $hookmanager->executeHooks('addToLandingPageList',$tmparray,$object); +if (!empty($reshook)) { + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } else if ($reshook == 0) { + $tmparray=$hookmanager->resArray; + } } $head = user_prepare_head($object); From c8055715447465066a6a2855fb0958d08d0b8277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NASSIET?= Date: Thu, 12 Jan 2023 19:35:49 +0100 Subject: [PATCH 507/816] correction bug si pas reponse sur le hook --- htdocs/user/param_ihm.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 2f8f4ae24ad..4ee2c318f5e 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -217,14 +217,15 @@ if (isModEnabled('ticket')) { // Hook for insertion new items in the List of possible landing pages $reshook = $hookmanager->executeHooks('addToLandingPageList',$tmparray,$object); -if (!empty($reshook)) { - if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - } else if ($reshook == 0) { +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} else if ($reshook === 0) { + if (count($hookmanager->resArray)!==0) { $tmparray=$hookmanager->resArray; } } + $head = user_prepare_head($object); $title = $langs->trans("User"); From 2f80f873eae389a27dd9851b02b1fdeebf8ae624 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 12 Jan 2023 18:36:33 +0000 Subject: [PATCH 508/816] Fixing style errors. --- htdocs/user/param_ihm.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 4ee2c318f5e..da8eebacaac 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -216,10 +216,10 @@ if (isModEnabled('ticket')) { } // Hook for insertion new items in the List of possible landing pages -$reshook = $hookmanager->executeHooks('addToLandingPageList',$tmparray,$object); +$reshook = $hookmanager->executeHooks('addToLandingPageList', $tmparray, $object); if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); -} else if ($reshook === 0) { +} elseif ($reshook === 0) { if (count($hookmanager->resArray)!==0) { $tmparray=$hookmanager->resArray; } From ca8188ee90140d0fb9ee4ab38e53f6b0618d130f Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Thu, 12 Jan 2023 19:48:32 +0100 Subject: [PATCH 509/816] kanban mode for list of payment cheque --- .../cheque/class/remisecheque.class.php | 39 ++++++++ htdocs/compta/paiement/cheque/list.php | 91 +++++++++++++------ 2 files changed, 100 insertions(+), 30 deletions(-) diff --git a/htdocs/compta/paiement/cheque/class/remisecheque.class.php b/htdocs/compta/paiement/cheque/class/remisecheque.class.php index e193939cdd6..1e4e7d05a7d 100644 --- a/htdocs/compta/paiement/cheque/class/remisecheque.class.php +++ b/htdocs/compta/paiement/cheque/class/remisecheque.class.php @@ -1020,4 +1020,43 @@ class RemiseCheque extends CommonObject return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; + + if (property_exists($this, 'date_bordereau')) { + $return .= '
'.$langs->trans("DateCreation").' : '.dol_print_date($this->db->jdate($this->date_bordereau), 'day').''; + } + if (property_exists($this, 'nbcheque')) { + $return .= '
'.$langs->trans("Cheque", '', '', '', '', 5).' : '.$this->nbcheque.''; + } + if (property_exists($this, 'account_id')) { + $return .= ' | '.$this->account_id.''; + } + if (method_exists($this, 'LibStatut')) { + $return .= '
'.$this->LibStatut($this->statut, 5).'
'; + } + if (property_exists($this, 'amount')) { + $return .= ' |
'.$langs->trans("Amount").' : '.price($this->amount).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/compta/paiement/cheque/list.php b/htdocs/compta/paiement/cheque/list.php index 054ef800586..38db4fca14b 100644 --- a/htdocs/compta/paiement/cheque/list.php +++ b/htdocs/compta/paiement/cheque/list.php @@ -44,6 +44,7 @@ $result = restrictedArea($user, 'banque', '', ''); $search_ref = GETPOST('search_ref', 'alpha'); $search_account = GETPOST('search_account', 'int'); $search_amount = GETPOST('search_amount', 'alpha'); +$mode = GETPOST('mode', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); @@ -149,6 +150,9 @@ if ($resql) { $num = $db->num_rows($resql); $i = 0; $param = ''; + if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); + } if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.$contextpage; } @@ -160,7 +164,10 @@ if ($resql) { if (!empty($socid)) { $url .= '&socid='.$socid; } - $newcardbutton = dolGetButtonTitle($langs->trans('NewCheckDeposit'), '', 'fa fa-plus-circle', $url, '', $user->rights->banque->cheque); + $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')); + $newcardbutton .= dolGetButtonTitle($langs->trans('NewCheckDeposit'), '', 'fa fa-plus-circle', $url, '', $user->rights->banque->cheque); print ''; if ($optioncss != '') { @@ -172,6 +179,8 @@ if ($resql) { print ''; print ''; print ''; + print ''; + print_barre_liste($langs->trans("MenuChequeDeposits"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'bank_account', 0, $newcardbutton, '', $limit); @@ -220,42 +229,64 @@ if ($resql) { while ($i < min($num, $limit)) { $objp = $db->fetch_object($resql); - print ''; - - // Num ref cheque - print ''; $checkdepositstatic->id = $objp->rowid; $checkdepositstatic->ref = ($objp->ref ? $objp->ref : $objp->rowid); $checkdepositstatic->statut = $objp->statut; - print $checkdepositstatic->getNomUrl(1); - print ''; + $checkdepositstatic->nbcheque = $objp->nbcheque; + $checkdepositstatic->amount = $objp->amount; + $checkdepositstatic->date_bordereau = $objp->date_bordereau; - // Date - print ''.dol_print_date($db->jdate($objp->date_bordereau), 'day').''; // TODO Use date hour + $account = new Account($db); + $account->fetch($objp->bid); + $checkdepositstatic->account_id = $account->getNomUrl(1); - // Bank - print ''; - if ($objp->bid) { - print ''.img_object($langs->trans("ShowAccount"), 'account').' '.$objp->label.''; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + // Output Kanban + print $checkdepositstatic->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } } else { - print ' '; + print ''; + + // Num ref cheque + print ''; + + print $checkdepositstatic->getNomUrl(1); + print ''; + + // Date + print ''.dol_print_date($db->jdate($objp->date_bordereau), 'day').''; // TODO Use date hour + + // Bank + print ''; + if ($objp->bid) { + print ''.img_object($langs->trans("ShowAccount"), 'account').' '.$objp->label.''; + } else { + print ' '; + } + print ''; + + // Number of cheques + print ''.$objp->nbcheque.''; + + // Amount + print ''.price($objp->amount).''; + + // Statut + print ''; + print $checkdepositstatic->LibStatut($objp->statut, 5); + print ''; + + print ''; + + print "\n"; } - print ''; - - // Number of cheques - print ''.$objp->nbcheque.''; - - // Amount - print ''.price($objp->amount).''; - - // Statut - print ''; - print $checkdepositstatic->LibStatut($objp->statut, 5); - print ''; - - print ''; - - print "\n"; $i++; } } else { From 1b81cce3bb0a1886bfa820d4944cdd62547677a5 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Thu, 12 Jan 2023 20:46:49 +0100 Subject: [PATCH 510/816] kanban mode for list of cashcontrol --- .../compta/cashcontrol/cashcontrol_list.php | 157 ++++++++++-------- .../cashcontrol/class/cashcontrol.class.php | 32 ++++ 2 files changed, 124 insertions(+), 65 deletions(-) diff --git a/htdocs/compta/cashcontrol/cashcontrol_list.php b/htdocs/compta/cashcontrol/cashcontrol_list.php index 7d433282367..b4c20a824ba 100644 --- a/htdocs/compta/cashcontrol/cashcontrol_list.php +++ b/htdocs/compta/cashcontrol/cashcontrol_list.php @@ -41,7 +41,7 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'cashcontrol'; // 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', 'alpha'); // for mode view result $id = GETPOST('id', 'int'); // Load variable for pagination @@ -344,6 +344,9 @@ $param = ''; if (!empty($mode)) { $param .= '&mode='.urlencode($mode); } +if (!empty($mode)) { + $param .= '&mode='.urlencode($mode); +} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -399,10 +402,13 @@ print ''; print ''; print ''; print ''; +print ''; $permforcashfence = 1; - -$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/compta/cashcontrol/cashcontrol_card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permforcashfence); +$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')); +$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/compta/cashcontrol/cashcontrol_card.php?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permforcashfence); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'cash-register', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -552,81 +558,102 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // Store properties in $object $object->setVarsFromFetchObj($obj); - // Show here line of result - $j = 0; - print ''; - foreach ($object->fields as $key => $val) { - $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); - if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { - $cssforfield .= ($cssforfield ? ' ' : '').'center'; - } elseif ($key == 'status') { - $cssforfield .= ($cssforfield ? ' ' : '').'center'; + // show kanban result + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } + // Output Kanban + //var_dump($obj->posmodule);exit; + $object->posmodule = $obj->posmodule; + $object->cash = $obj->cash; + $object->opening = $obj->opening; + $object->year_close = $obj->year_close; + $object->cheque = $obj->cheque; - if (in_array($val['type'], array('timestamp'))) { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif ($key == 'ref') { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + + print $object->getKanbanView(''); + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; } + } else { + // Show here line of result + $j = 0; + print ''; + foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } - if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { - $cssforfield .= ($cssforfield ? ' ' : '').'right'; - } - //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + if (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif ($key == 'ref') { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } - if (!empty($arrayfields['t.'.$key]['checked'])) { - print ''; - if ($key == 'status') { - print $object->getLibStatut(5); - } elseif ($key == 'rowid') { - print $object->showOutputField($val, $key, $object->id, ''); - } else { - print $object->showOutputField($val, $key, $object->$key, ''); - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + if ($key == 'status') { + print $object->getLibStatut(5); + } elseif ($key == 'rowid') { + print $object->showOutputField($val, $key, $object->id, ''); + } else { + print $object->showOutputField($val, $key, $object->$key, ''); + } + print ''; if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + $totalarray['nbfield']++; } - if (!isset($totalarray['val'])) { - $totalarray['val'] = array(); + if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + } + if (!isset($totalarray['val'])) { + $totalarray['val'] = array(); + } + if (!isset($totalarray['val']['t.'.$key])) { + $totalarray['val']['t.'.$key] = 0; + } + $totalarray['val']['t.'.$key] += $object->$key; } - if (!isset($totalarray['val']['t.'.$key])) { - $totalarray['val']['t.'.$key] = 0; - } - $totalarray['val']['t.'.$key] += $object->$key; } } - } - // Extra fields - 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; - // Action 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($object->id, $arrayofselected)) { - $selected = 1; + // Extra fields + 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; + // Action 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($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - - print ''."\n"; + print ''."\n"; + } $i++; } diff --git a/htdocs/compta/cashcontrol/class/cashcontrol.class.php b/htdocs/compta/cashcontrol/class/cashcontrol.class.php index bc45f3b417d..01bebc35f5d 100644 --- a/htdocs/compta/cashcontrol/class/cashcontrol.class.php +++ b/htdocs/compta/cashcontrol/class/cashcontrol.class.php @@ -469,4 +469,36 @@ class CashControl extends CommonObject return $result; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + //var_dump($this->fields['rowid']);exit; + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1, 1) : $this->ref).''; + if (property_exists($this, 'posmodule')) { + $return .= '
'.substr($langs->trans("Module/Application"), 0, 12).' : '.$this->posmodule.''; + } + if (property_exists($this, 'year_close')) { + $return .= '
'.$langs->trans("Year").' : '.$this->year_close.''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } From 256bd27c3307a0d5728856d90ad9b16d1c64bd50 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 21:59:34 +0100 Subject: [PATCH 511/816] Fix delete website --- htdocs/admin/website.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/website.php b/htdocs/admin/website.php index 3c348d71a12..aa2ee58853c 100644 --- a/htdocs/admin/website.php +++ b/htdocs/admin/website.php @@ -614,7 +614,7 @@ if ($id) { // Active print ''; - print ''.$actl[($obj->status ? 1 : 0)].''; + print ''.$actl[($obj->status ? 1 : 0)].''; print ""; // Modify link From 5bbfdbb77507372220dc3ee27163bc47ed357cb4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 22:11:13 +0100 Subject: [PATCH 512/816] NEW Show counter of access of website in website list --- htdocs/admin/website.php | 49 ++++++++++++++----- htdocs/core/lib/website.lib.php | 9 +++- .../install/mysql/migration/17.0.0-18.0.0.sql | 2 + .../mysql/tables/llx_website-website.sql | 7 +-- htdocs/langs/en_US/main.lang | 1 + htdocs/langs/en_US/website.lang | 2 + 6 files changed, 53 insertions(+), 17 deletions(-) diff --git a/htdocs/admin/website.php b/htdocs/admin/website.php index 3c348d71a12..28909470701 100644 --- a/htdocs/admin/website.php +++ b/htdocs/admin/website.php @@ -84,7 +84,7 @@ $tablib[1] = "Websites"; // Requests to extract data $tabsql = array(); -$tabsql[1] = "SELECT f.rowid as rowid, f.entity, f.ref, f.description, f.virtualhost, f.position, f.status, f.date_creation FROM ".MAIN_DB_PREFIX.'website as f WHERE f.entity IN ('.getEntity('website').')'; +$tabsql[1] = "SELECT f.rowid as rowid, f.entity, f.ref, f.description, f.virtualhost, f.position, f.status, f.date_creation, f.lastaccess, f.pageviews_previous_month, f.pageviews_total FROM ".MAIN_DB_PREFIX.'website as f WHERE f.entity IN ('.getEntity('website').')'; // Criteria to sort dictionaries $tabsqlsort = array(); @@ -92,7 +92,7 @@ $tabsqlsort[1] = "ref ASC"; // Nom des champs en resultat de select pour affichage du dictionnaire $tabfield = array(); -$tabfield[1] = "ref,description,virtualhost,position,date_creation"; +$tabfield[1] = "ref,description,virtualhost,position,date_creation,lastaccess,pageviews_previous_month,pageviews_total"; // Nom des champs d'edition pour modification d'un enregistrement $tabfieldvalue = array(); @@ -186,7 +186,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { $sql .= $tabrowid[$id].","; } $sql .= $tabfieldinsert[$id]; - $sql .= ",status)"; + $sql .= ", status, date_creation)"; $sql .= " VALUES("; // List of values @@ -211,7 +211,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { } $i++; } - $sql .= ",1)"; + $sql .= ", 1, '".$db->idate(dol_now())."')"; dol_syslog("actionadd", LOG_DEBUG); $result = $db->query($sql); @@ -441,12 +441,10 @@ if ($id) { // Form to add a new line if ($tabname[$id]) { - $fieldlist = explode(',', $tabfield[$id]); - // Line for title print ''; foreach ($fieldlist as $field => $value) { - if ($fieldlist[$field] == 'date_creation') { + if (in_array($fieldlist[$field], array('date_creation', 'lastaccess', 'pageviews_previous_month', 'pageviews_month', 'pageviews_total'))) { continue; } @@ -522,6 +520,7 @@ if ($id) { print ''; print ''; + print '
'; print ''; // Title of lines @@ -533,6 +532,10 @@ if ($id) { $align = "left"; $sortable = 1; $valuetoshow = ''; + if (in_array($fieldlist[$field], array('pageviews_total', 'pageviews_previous_month'))) { + $align = 'right'; + } + /* $tmparray=getLabelOfField($fieldlist[$field]); $showfield=$tmp['showfield']; @@ -554,14 +557,24 @@ if ($id) { if ($fieldlist[$field] == 'date_creation') { $valuetoshow = $langs->trans("DateCreation"); } + if ($fieldlist[$field] == 'lastaccess') { + $valuetoshow = $langs->trans("LastAccess"); + } + if ($fieldlist[$field] == 'pageviews_previous_month') { + $valuetoshow = $langs->trans("PagesViewedPreviousMonth"); + } + if ($fieldlist[$field] == 'pageviews_total') { + $valuetoshow = $langs->trans("PagesViewedTotal"); + } // Affiche nom du champ if ($showfield) { - print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable ? $fieldlist[$field] : ''), ($page ? 'page='.$page.'&' : ''), "", "align=".$align, $sortfield, $sortorder); + print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable ? $fieldlist[$field] : ''), ($page ? 'page='.$page.'&' : ''), "", '', $sortfield, $sortorder, $align.' '); } } - print getTitleFieldOfList($langs->trans("Status"), 0, $_SERVER["PHP_SELF"], "status", ($page ? 'page='.$page.'&' : ''), "", 'align="center"', $sortfield, $sortorder); + // Status + print getTitleFieldOfList($langs->trans("Status"), 0, $_SERVER["PHP_SELF"], "status", ($page ? 'page='.$page.'&' : ''), "", '', $sortfield, $sortorder, 'center '); print getTitleFieldOfList(''); print getTitleFieldOfList(''); print ''; @@ -581,8 +594,9 @@ if ($id) { fieldListWebsites($fieldlist, $obj, $tabname[$id], 'edit'); } - print ''; + print ''; } else { $tmpaction = 'view'; $parameters = array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]); @@ -593,13 +607,16 @@ if ($id) { if (empty($reshook)) { foreach ($fieldlist as $field => $value) { $showfield = 1; - $align = "left"; $fieldname = $fieldlist[$field]; + $align = "left"; + if (in_array($fieldname, array('pageviews_total', 'pageviews_previous_month'))) { + $align = 'right'; + } $valuetoshow = $obj->$fieldname; // Show value for field if ($showfield) { - print ''; + print ''; } } } @@ -612,6 +629,7 @@ if ($id) { $url = $_SERVER["PHP_SELF"].'?'.($page ? 'page='.$page.'&' : '').'sortfield='.$sortfield.'&sortorder='.$sortorder.'&rowid='.(!empty($obj->rowid) ? $obj->rowid : (!empty($obj->code) ? $obj->code : '')).'&code='.(!empty($obj->code) ?urlencode($obj->code) : '').'&'; + // Active print '
 '; - print '  '; + print ''; + print ' '.$valuetoshow.''.$valuetoshow.''; print ''.$actl[($obj->status ? 1 : 0)].''; @@ -633,6 +651,7 @@ if ($id) { } print '
'; + print '
'; print ''; } @@ -668,6 +687,10 @@ function fieldListWebsites($fieldlist, $obj = '', $tabname = '', $context = '') $formadmin = new FormAdmin($db); foreach ($fieldlist as $field => $value) { + if (in_array($fieldlist[$field], array('lastaccess', 'pageviews_previous_month', 'pageviews_month', 'pageviews_total'))) { + continue; + } + $fieldname = $fieldlist[$field]; if ($fieldlist[$field] == 'lang') { diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 32a6d9d962a..de5779a3f51 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -438,7 +438,14 @@ function dolWebsiteIncrementCounter($websiteid, $websitepagetype, $websitepageid if (in_array($websitepagetype, array('blogpost', 'page'))) { global $db; - $sql = "UPDATE ".$db->prefix()."website SET pageviews_total = pageviews_total + 1, lastaccess = '".$db->idate(dol_now())."'"; + $tmpnow = dol_getdate(dol_now('gmt'), true, 'gmt'); + + $sql = "UPDATE ".$db->prefix()."website SET "; + $sql .= " pageviews_total = pageviews_total + 1,"; + $sql .= " pageviews_month = pageviews_month + 1,"; + // if last access was done during previous month, we save pageview_month into pageviews_previous_month + $sql .= " pageviews_previous_month = ".$db->ifsql("lastaccess < '".$db->idate(dol_mktime(0, 0, 0, $tmpnow['month'], 1, $tmpnow['year'], 'gmt', 0), 'gmt')."'", 'pageviews_month', 'pageviews_previous_month').","; + $sql .= " lastaccess = '".$db->idate(dol_now('gmt'), 'gmt')."'"; $sql .= " WHERE rowid = ".((int) $websiteid); $resql = $db->query($sql); if (! $resql) { 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 376d89861f2..d8e1b4c12c9 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 @@ -59,3 +59,5 @@ INSERT INTO llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2 ALTER TABLE llx_user ADD COLUMN flagdelsessionsbefore datetime DEFAULT NULL; +ALTER TABLE llx_website ADD COLUMN pageviews_previous_month BIGINT UNSIGNED DEFAULT 0; + diff --git a/htdocs/install/mysql/tables/llx_website-website.sql b/htdocs/install/mysql/tables/llx_website-website.sql index 0df6ccf8ef3..8ac580919aa 100644 --- a/htdocs/install/mysql/tables/llx_website-website.sql +++ b/htdocs/install/mysql/tables/llx_website-website.sql @@ -36,9 +36,10 @@ CREATE TABLE llx_website fk_user_modif integer, date_creation datetime, position integer DEFAULT 0, - lastaccess datetime NULL, - pageviews_month BIGINT UNSIGNED DEFAULT 0, - pageviews_total BIGINT UNSIGNED DEFAULT 0, + lastaccess datetime NULL, -- updated at each page access + pageviews_previous_month BIGINT UNSIGNED DEFAULT 0, + pageviews_month BIGINT UNSIGNED DEFAULT 0, -- increased by 1 at each page access, saved into pageviews_previous_month when on different month than lastaccess + pageviews_total BIGINT UNSIGNED DEFAULT 0, -- increased by 1 at each page access, no reset tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, import_key varchar(14) -- import key ) ENGINE=innodb; diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 2473659a5c7..bdd0ef2bd0d 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1216,3 +1216,4 @@ NoSpecificContactAddress=No specific contact or address NoSpecificContactAddressBis=This tab is dedicated to force specific contacts or addresses for the current object. Use it only if you want to define one or several specific contacts or addresses for the object when the information on the thirdparty is not enough or not accurate. HideOnVCard=Hide %s AddToContacts=Add address to my contacts +LastAccess=Last access \ No newline at end of file diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 742e3afff67..7b2cc90f7ac 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -155,3 +155,5 @@ WebpageMustBeDisabled=The web page must have the status "%s" SetWebsiteOnlineBefore=When website is offline, all pages are offline. Change status of website first. Booking=Booking Reservation=Reservation +PagesViewedPreviousMonth=Pages viewed (previous month) +PagesViewedTotal=Pages viewed (total) \ No newline at end of file From 22720b652ca6d50a1939fb98d5d2d314201f98e6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 12 Jan 2023 22:28:08 +0100 Subject: [PATCH 513/816] Fix phpcs --- htdocs/fourn/facture/list.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index deeecc3af6f..9b790050571 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -766,11 +766,11 @@ if ($limit > 0 && $limit != $conf->liste_limit) { if ($search_all) { $param .= '&search_all='.urlencode($search_all); } - if ($search_date_start) { - $param .= buildParamDate('search_date_start', null, '', 'tzserver'); +if ($search_date_start) { + $param .= buildParamDate('search_date_start', null, '', 'tzserver'); } - if ($search_date_end) { - $param .= buildParamDate('search_date_end', null, '', 'tzserver'); +if ($search_date_end) { + $param .= buildParamDate('search_date_end', null, '', 'tzserver'); } if ($search_datelimit_startday) { $param .= '&search_datelimit_startday='.urlencode($search_datelimit_startday); From c52fab09e608d7eede0ece3f314304db147234d8 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Fri, 13 Jan 2023 09:01:31 +0100 Subject: [PATCH 514/816] FIX re-open supplier order should not be allowed when there is a reception. --- htdocs/fourn/commande/card.php | 46 ++++++++++++++++++++-------------- htdocs/langs/en_US/orders.lang | 1 + 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 644469a257d..ffb2e834db7 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -2440,6 +2440,19 @@ if ($action == 'create') { if (empty($reshook)) { $object->fetchObjectLinked(); // Links are used to show or not button, so we load them now. + // check if reception + $hasreception = 0; + if ($conf->reception->enabled) { + if (!empty($object->linkedObjects['reception'])) { + foreach ($object->linkedObjects['reception'] as $element) { + if ($element->statut >= 0) { + $hasreception = 1; + break; + } + } + } + } + // Validate if ($object->statut == 0 && $num > 0) { if ($usercanvalidate) { @@ -2515,17 +2528,21 @@ if ($action == 'create') { // Reopen if (in_array($object->statut, array(CommandeFournisseur::STATUS_ACCEPTED))) { $buttonshown = 0; - if (!$buttonshown && $usercanapprove) { - if (empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY) - || (!empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY) && $user->id == $object->user_approve_id)) { - print ''.$langs->trans("Disapprove").''; - $buttonshown++; + if ($hasreception) { + print ''.$langs->trans("Disapprove").''; + } else { + if (!$buttonshown && $usercanapprove) { + if (empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY) + || (!empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY) && $user->id == $object->user_approve_id)) { + print ''.$langs->trans("Disapprove").''; + $buttonshown++; + } } - } - if (!$buttonshown && $usercanapprovesecond && !empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED)) { - if (empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY) - || (!empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY) && $user->id == $object->user_approve_id2)) { - print ''.$langs->trans("Disapprove").''; + if (!$buttonshown && $usercanapprovesecond && !empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED)) { + if (empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY) + || (!empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY) && $user->id == $object->user_approve_id2)) { + print ''.$langs->trans("Disapprove").''; + } } } } @@ -2536,19 +2553,10 @@ if ($action == 'create') { } // Ship - $hasreception = 0; if (isModEnabled('stock') && (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE))) { $labelofbutton = $langs->trans('ReceiveProducts'); if ($conf->reception->enabled) { $labelofbutton = $langs->trans("CreateReception"); - if (!empty($object->linkedObjects['reception'])) { - foreach ($object->linkedObjects['reception'] as $element) { - if ($element->statut >= 0) { - $hasreception = 1; - break; - } - } - } } if (in_array($object->statut, array(3, 4, 5))) { diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index f988cd62f19..0accaadfa62 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -204,3 +204,4 @@ StatusSupplierOrderApproved=Approved StatusSupplierOrderRefused=Refused StatusSupplierOrderReceivedPartially=Partially received StatusSupplierOrderReceivedAll=All products received +NeedAtLeastOneInvoice = There has to be at least one Invoice From 534cb8f0a045552448006d957238565de7bc06c2 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 13 Jan 2023 09:55:57 +0100 Subject: [PATCH 515/816] fix: token for scan inventory --- htdocs/product/inventory/inventory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/inventory/inventory.php b/htdocs/product/inventory/inventory.php index 3d0dea9e3b7..cd27c09aaa0 100644 --- a/htdocs/product/inventory/inventory.php +++ b/htdocs/product/inventory/inventory.php @@ -609,7 +609,7 @@ if ($object->id > 0) { if ($permissiontoadd) { // Link to launch scan tool if (!empty($conf->barcode->enabled) || !empty($conf->productbatch->enabled)) { - print ''.img_picto('', 'barcode', 'class="paddingrightonly"').$langs->trans("UpdateByScaning").''; + print ''.img_picto('', 'barcode', 'class="paddingrightonly"').$langs->trans("UpdateByScaning").''; } // Link to autofill From 59a541ab8e43c413dbb5e6a0e6bc0eb42cfd0dfa Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 13 Jan 2023 10:33:48 +0100 Subject: [PATCH 516/816] NEW: Add SQL contraint on product_stock table to allow only exsting product and warehouse#23543 --- .../install/mysql/migration/17.0.0-18.0.0.sql | 36 +++++++++++++++++++ .../mysql/tables/llx_product_stock.key.sql | 2 ++ 2 files changed, 38 insertions(+) create mode 100644 htdocs/install/mysql/migration/17.0.0-18.0.0.sql 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 new file mode 100644 index 00000000000..4e68aebfdc8 --- /dev/null +++ b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql @@ -0,0 +1,36 @@ +-- +-- Be carefull to requests order. +-- This file must be loaded by calling /install/index.php page +-- when current version is 16.0.0 or higher. +-- +-- To restrict request to Mysql version x.y minimum use -- VMYSQLx.y +-- To restrict request to Pgsql version x.y minimum use -- VPGSQLx.y +-- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new; +-- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol; +-- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60); +-- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname; +-- To change type of field: ALTER TABLE llx_table MODIFY COLUMN name varchar(60); +-- To drop a foreign key: ALTER TABLE llx_table DROP FOREIGN KEY fk_name; +-- To create a unique index ALTER TABLE llx_table ADD UNIQUE INDEX uk_table_field (field); +-- To drop an index: -- VMYSQL4.1 DROP INDEX nomindex on llx_table; +-- To drop an index: -- VPGSQL8.2 DROP INDEX nomindex; +-- To make pk to be auto increment (mysql): +-- -- VMYSQL4.3 ALTER TABLE llx_table ADD PRIMARY KEY(rowid); +-- -- VMYSQL4.3 ALTER TABLE llx_table CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; +-- To make pk to be auto increment (postgres): +-- -- VPGSQL8.2 CREATE SEQUENCE llx_table_rowid_seq OWNED BY llx_table.rowid; +-- -- VPGSQL8.2 ALTER TABLE llx_table ADD PRIMARY KEY (rowid); +-- -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN rowid SET DEFAULT nextval('llx_table_rowid_seq'); +-- -- VPGSQL8.2 SELECT setval('llx_table_rowid_seq', MAX(rowid)) FROM llx_table; +-- To set a field as NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NULL; +-- To set a field as NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL; +-- To set a field as NOT NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NOT NULL; +-- To set a field as NOT NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET NOT NULL; +-- To set a field as default NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; +-- Note: fields with type BLOB/TEXT can't have default value. +-- To rebuild sequence for postgresql after insert by forcing id autoincrement fields: +-- -- VPGSQL8.2 SELECT dol_util_rebuild_sequences(); + + +ALTER TABLE llx_product_stock ADD CONSTRAINT fk_product_product_rowid FOREIGN KEY (fk_product) REFERENCES llx_product (rowid); +ALTER TABLE llx_product_stock ADD CONSTRAINT fk_entrepot_entrepot_rowid FOREIGN KEY (fk_entrepot) REFERENCES llx_entrepot (rowid); diff --git a/htdocs/install/mysql/tables/llx_product_stock.key.sql b/htdocs/install/mysql/tables/llx_product_stock.key.sql index 358a0c74f19..b07719a5478 100644 --- a/htdocs/install/mysql/tables/llx_product_stock.key.sql +++ b/htdocs/install/mysql/tables/llx_product_stock.key.sql @@ -20,5 +20,7 @@ ALTER TABLE llx_product_stock ADD INDEX idx_product_stock_fk_product (fk_product); ALTER TABLE llx_product_stock ADD INDEX idx_product_stock_fk_entrepot (fk_entrepot); +ALTER TABLE llx_product_stock ADD CONSTRAINT fk_product_product_rowid FOREIGN KEY (fk_product) REFERENCES llx_product (rowid); +ALTER TABLE llx_product_stock ADD CONSTRAINT fk_entrepot_entrepot_rowid FOREIGN KEY (fk_entrepot) REFERENCES llx_entrepot (rowid); ALTER TABLE llx_product_stock ADD UNIQUE INDEX uk_product_stock (fk_product,fk_entrepot); From a06a5d0f65e47010263b4d3aa5825ece10dc35e2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 11:09:06 +0100 Subject: [PATCH 517/816] Fix lang file not loaded --- scripts/emailings/mailing-send.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/emailings/mailing-send.php b/scripts/emailings/mailing-send.php index fcaa40e1fde..71d1604df4e 100755 --- a/scripts/emailings/mailing-send.php +++ b/scripts/emailings/mailing-send.php @@ -66,6 +66,8 @@ if (empty($conf->global->MAILING_LIMIT_SENDBYCLI)) $conf->global->MAILING_LIMIT_SENDBYCLI = 0; } +$langs->loadLangs(array("main", "mails")); + /* * Main From 336ac00ae382c803d3cb5824443d6b5d347dc918 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 11:40:50 +0100 Subject: [PATCH 518/816] kanban mode for list of jobs --- htdocs/hrm/class/job.class.php | 31 +++++++ htdocs/hrm/job_list.php | 153 ++++++++++++++++++++------------- 2 files changed, 123 insertions(+), 61 deletions(-) diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php index 93950979a1a..a013bb57a36 100644 --- a/htdocs/hrm/class/job.class.php +++ b/htdocs/hrm/class/job.class.php @@ -1054,6 +1054,37 @@ class Job extends CommonObject return $error; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $selected, $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + $return .= ''; + if (property_exists($this, 'deplacement')) { + $return .= '
'.$langs->trans("Type").''; + $return .= ' : '.$this->fields['deplacement']['arrayofkeyval'][$this->deplacement].''; + } + if (property_exists($this, 'description') && !(empty($this->description))) { + $return .= '
'.$langs->trans("Description").' : '; + $return .= '
'.(strlen($this->description) > 30 ? dol_substr($this->description, 0, 25).'...' : $this->description).''; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/hrm/job_list.php b/htdocs/hrm/job_list.php index ed0fb480a3a..6e97c0d0483 100644 --- a/htdocs/hrm/job_list.php +++ b/htdocs/hrm/job_list.php @@ -52,6 +52,7 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'joblist'; // 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', 'alpha'); // for view result with other mode $id = GETPOST('id', 'int'); @@ -362,6 +363,9 @@ llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', ''); $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); } @@ -413,8 +417,13 @@ print ''; print ''; print ''; print ''; +print ''; -$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/job_card.php', 1).'?action=create', '', $permissiontoadd); + +$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')); +$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/job_card.php', 1).'?action=create', '', $permissiontoadd); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -561,78 +570,100 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // Store properties in $object $object->setVarsFromFetchObj($obj); - // Show here line of result - print ''; - foreach ($object->fields as $key => $val) { - $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); - if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { - $cssforfield .= ($cssforfield ? ' ' : '').'center'; - } elseif ($key == 'status') { - $cssforfield .= ($cssforfield ? ' ' : '').'center'; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } + // Output Kanban - if (in_array($val['type'], array('timestamp'))) { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif ($key == 'ref') { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } + $object->deplacement = $obj->deplacement; + $object->description = $obj->description; - if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { - $cssforfield .= ($cssforfield ? ' ' : '').'right'; - } - //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; - - if (!empty($arrayfields['t.'.$key]['checked'])) { - print ''; - if ($key == 'status') { - print $object->getLibStatut(5); - } elseif ($key == 'rowid') { - print $object->showOutputField($val, $key, $object->id, ''); - } elseif ($key == 'label') { - print $object->getNomUrl(1); - } else { - print $object->showOutputField($val, $key, $object->$key, ''); + 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 ''; - if (!$i) { - $totalarray['nbfield']++; + print $object->getKanbanView(''); + } + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; + } + } else { + // Show here line of result + print ''; + foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; } - if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + + if (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif ($key == 'ref') { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + if ($key == 'status') { + print $object->getLibStatut(5); + } elseif ($key == 'rowid') { + print $object->showOutputField($val, $key, $object->id, ''); + } elseif ($key == 'label') { + print $object->getNomUrl(1); + } else { + print $object->showOutputField($val, $key, $object->$key, ''); + } + print ''; if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + $totalarray['nbfield']++; } - if (!isset($totalarray['val'])) { - $totalarray['val'] = array(); + if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + } + if (!isset($totalarray['val'])) { + $totalarray['val'] = array(); + } + if (!isset($totalarray['val']['t.'.$key])) { + $totalarray['val']['t.'.$key] = 0; + } + $totalarray['val']['t.'.$key] += $object->$key; } - if (!isset($totalarray['val']['t.'.$key])) { - $totalarray['val']['t.'.$key] = 0; - } - $totalarray['val']['t.'.$key] += $object->$key; } } - } - // Extra fields - 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; - // Action 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($object->id, $arrayofselected)) { - $selected = 1; + // Extra fields + 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; + // Action 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($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - - print ''."\n"; + print ''."\n"; + } $i++; } From a5fba0fd09db765f91d11f00e07a01a2dbb70f94 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 12:10:22 +0100 Subject: [PATCH 519/816] kanban for position list --- htdocs/hrm/class/position.class.php | 35 +++++++++++++++++++++++++++++ htdocs/hrm/position_list.php | 18 +++++++++++++-- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index 98b5fd89be9..9d4f71d24fd 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -1118,6 +1118,41 @@ class Position extends CommonObject return $error; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $selected, $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + $return .= ''; + if (property_exists($this, 'fk_user') && !(empty($this->fk_user))) { + $return .= '
'.$langs->trans("Employee").' : '; + $return .= ''.$this->fk_user.''; + } + if (property_exists($this, 'fk_job') && !(empty($this->fk_job))) { + $return .= '
'.$langs->trans("Job").' : '; + $return .= ''.$this->fk_job.''; + } + if (property_exists($this, 'date_start') && property_exists($this, 'date_end')) { + $return .= '
'.dol_print_date($this->db->jdate($this->date_start), 'day').''; + $return .= ' - '.dol_print_date($this->db->jdate($this->date_end), 'day').'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/hrm/position_list.php b/htdocs/hrm/position_list.php index 40cb706b5df..5dc33859219 100644 --- a/htdocs/hrm/position_list.php +++ b/htdocs/hrm/position_list.php @@ -426,7 +426,10 @@ print ''; print ''; print ''; -$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/position.php', 1).'?action=create', '', $permissiontoadd); +$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')); +$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/position.php', 1).'?action=create', '', $permissiontoadd); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -602,12 +605,23 @@ while ($i < $imaxinloop) { // Store properties in $object $object->setVarsFromFetchObj($obj); + if ($mode == 'kanban') { if ($i == 0) { print ''; print '
'; } - // Output Kanban + // get info needed + + $object->date_start = $obj->date_start; + $object->date_end = $obj->date_end; + $job = new job($db); + $job->fetch($obj->fk_job); + $object->fk_job = $job->getNomUrl(); + $userstatic = new User($db); + $userstatic->fetch($obj->fk_user); + $object->fk_user = $userstatic->getNomUrl(1); + // output kanban print $object->getKanbanView(''); if ($i == ($imaxinloop - 1)) { print '
'; From 8eb89e0ad14015ec4080042db82581cdf026bcf4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 12:14:20 +0100 Subject: [PATCH 520/816] Remove merged feature with too many pb: 1=Not yet implemented everywhere. 2=Seems a duplicate info with the picto warning when late (so in past not done) 3=Is also a duplicate with the existing css event-future, event-past, event-current 4=It overwrites to choice done by the theme 5=Implementation is wrong, it must use css and not #background Use CSS instead --- htdocs/admin/agenda_other.php | 82 ++----------------------------- htdocs/admin/agenda_reminder.php | 1 - htdocs/comm/action/index.php | 1 + htdocs/comm/action/list.php | 21 ++++---- htdocs/core/lib/functions.lib.php | 2 +- htdocs/langs/en_US/admin.lang | 1 + htdocs/theme/eldy/global.inc.php | 4 ++ 7 files changed, 20 insertions(+), 92 deletions(-) diff --git a/htdocs/admin/agenda_other.php b/htdocs/admin/agenda_other.php index 8916433707d..aef46db26ef 100644 --- a/htdocs/admin/agenda_other.php +++ b/htdocs/admin/agenda_other.php @@ -113,33 +113,6 @@ if ($action == 'set') { } else { setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); } -} elseif ($action == 'setcolors') { - $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_past_color', 'alphanohtml')); - $res = dolibarr_set_const($db, 'AGENDA_EVENT_PAST_COLOR', $event_color, 'chaine', 0, '', $conf->entity); - if (!$res > 0) { - $error++; - $errors[] = $db->lasterror(); - } - - $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_current_color', 'alphanohtml')); - $res = dolibarr_set_const($db, 'AGENDA_EVENT_CURRENT_COLOR', $event_color, 'chaine', 0, '', $conf->entity); - if (!$res > 0) { - $error++; - $errors[] = $db->lasterror(); - } - - $event_color = preg_replace('/[^0-9a-f#]/i', '', (string) GETPOST('event_future_color', 'alphanohtml')); - $res = dolibarr_set_const($db, 'AGENDA_EVENT_FUTURE_COLOR', $event_color, 'chaine', 0, '', $conf->entity); - if (!$res > 0) { - $error++; - $errors[] = $db->lasterror(); - } - - if ($error) { - setEventMessages('', $errors, 'errors'); - } else { - setEventMessage($langs->trans('SetupSaved')); - } } elseif ($action == 'specimen') { // For orders $modele = GETPOST('module', 'alpha'); @@ -226,8 +199,6 @@ print dol_get_fiche_head($head, 'other', $langs->trans("Agenda"), -1, 'action'); * Miscellaneous */ -print load_fiche_titre($langs->trans('Miscellaneous'), '', ''); - // Define array def of models $def = array(); @@ -339,8 +310,11 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { } } print '
'; + + print load_fiche_titre($langs->trans('MiscellaneousOptions'), '', ''); } + print '
'; print ''; print ''; @@ -431,56 +405,6 @@ print $form->buttonsSaveCancel("Save", ''); print '
'; -/* - * User interface (colors) - */ - -print load_fiche_titre($langs->trans('UserInterface'), '', ''); - -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; -$formother = new FormOther($db); - -print '
'; -print ''; -print ''; - -print ''."\n"; -print ''."\n"; -print ''."\n"; -print ''."\n"; -print ''."\n"; -print ''."\n"; - -// AGENDA_EVENT_PAST_COLOR -print ''."\n"; -print ''."\n"; -print ''."\n"; -print ''."\n"; -// AGENDA_EVENT_CURRENT_COLOR -print ''."\n"; -print ''."\n"; -print ''."\n"; -print ''."\n"; -// AGENDA_EVENT_FUTURE_COLOR -print ''."\n"; -print ''."\n"; -print ''."\n"; -print ''."\n"; - -print '
'.$langs->trans("Parameters").' '.$langs->trans("Value").'
'.$langs->trans('AGENDA_EVENT_PAST_COLOR').' '."\n"; -print $formother->selectColor($conf->global->AGENDA_EVENT_PAST_COLOR, 'event_past_color'); -print '
'.$langs->trans('AGENDA_EVENT_CURRENT_COLOR').' '."\n"; -print $formother->selectColor($conf->global->AGENDA_EVENT_CURRENT_COLOR, 'event_current_color'); -print '
'.$langs->trans('AGENDA_EVENT_FUTURE_COLOR').' '."\n"; -print $formother->selectColor($conf->global->AGENDA_EVENT_FUTURE_COLOR, 'event_future_color'); -print '
'; - -print $form->buttonsSaveCancel("Save", ''); - -print '
'; - -print "
"; - print dol_get_fiche_end(); // End of page diff --git a/htdocs/admin/agenda_reminder.php b/htdocs/admin/agenda_reminder.php index 76c717b669d..42967b4f275 100644 --- a/htdocs/admin/agenda_reminder.php +++ b/htdocs/admin/agenda_reminder.php @@ -150,7 +150,6 @@ $linkback = 'trans("Agenda"), -1, 'action'); diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 5b51d48392b..3460355a803 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -299,6 +299,7 @@ if (empty($user->conf->AGENDA_DISABLE_EXT)) { $enabled = 'AGENDA_EXT_ENABLED_'.$user->id.'_'.$i; $default = 'AGENDA_EXT_ACTIVEBYDEFAULT_'.$user->id.'_'.$i; $buggedfile = 'AGENDA_EXT_BUGGEDFILE_'.$user->id.'_'.$i; + if (getDolUserString($source) && getDolUserString($name)) { // Note: $conf->global->buggedfile can be empty or 'uselocalandtznodaylight' or 'uselocalandtzdaylight' $listofextcals[] = array( diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index dd137690e47..5abd2d3f101 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -951,14 +951,15 @@ while ($i < $imaxinloop) { $event_owner_style .= 'border-left: #' . $cache_user_list[$obj->fk_user_action]->color . ' 5px solid;'; } - // get event style for start date + // get event style for start and end date $event_more_class = ''; - $event_start_date_style = ''; + $event_start_date_css = ''; + $event_end_date_css = ''; $event_start_date_time = $actionstatic->datep; if ($event_start_date_time > $now) { // future event $event_more_class = 'event-future'; - $event_start_date_color = $conf->global->AGENDA_EVENT_FUTURE_COLOR; + $event_start_date_css = $event_end_date_css = $event_more_class; } else { if ($obj->fulldayevent == 1) { $today_start_date_time = $today_start_time; @@ -971,20 +972,16 @@ while ($i < $imaxinloop) { if ($event_end_date_time != null && $event_end_date_time < $today_start_date_time) { // past event $event_more_class = 'event-past'; - $event_start_date_color = $conf->global->AGENDA_EVENT_PAST_COLOR; } elseif ($event_end_date_time == null && $event_start_date_time < $today_start_date_time) { // past event $event_more_class = 'event-past'; - $event_start_date_color = $conf->global->AGENDA_EVENT_PAST_COLOR; } else { // current event $event_more_class = 'event-current'; - $event_start_date_color = $conf->global->AGENDA_EVENT_CURRENT_COLOR; } + $event_start_date_css = $event_end_date_css = $event_more_class; } - if ($event_start_date_color != '') { - $event_start_date_style .= 'background: #' . $event_start_date_color . ';'; - } + $event_start_date_css = $event_end_date_css = $event_more_class; print ''; // Action column @@ -1065,13 +1062,14 @@ while ($i < $imaxinloop) { // Start date if (!empty($arrayfields['a.datep']['checked'])) { - print ''; + print ''; if (empty($obj->fulldayevent)) { print dol_print_date($db->jdate($obj->dp), $formatToUse, 'tzuserrel'); } else { $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT'); print dol_print_date($db->jdate($obj->dp), $formatToUse, ($tzforfullday ? $tzforfullday : 'tzuserrel')); } + print ''; $late = 0; if ($actionstatic->hasDelay() && $actionstatic->percentage >= 0 && $actionstatic->percentage < 100 ) { $late = 1; @@ -1084,13 +1082,14 @@ while ($i < $imaxinloop) { // End date if (!empty($arrayfields['a.datep2']['checked'])) { - print ''; + print ''; if (empty($obj->fulldayevent)) { print dol_print_date($db->jdate($obj->dp2), $formatToUse, 'tzuserrel'); } else { $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT'); print dol_print_date($db->jdate($obj->dp2), $formatToUse, ($tzforfullday ? $tzforfullday : 'tzuserrel')); } + print ''; print ''; } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 8920445508a..ab96f650b6f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -116,7 +116,7 @@ function getDolUserString($key, $default = '', $tmpuser = null) } // return $conf->global->$key ?? $default; - return (string) (empty($tmpuser->conf->$key) ? $default : $$tmpuser->conf->$key); + return (string) (empty($tmpuser->conf->$key) ? $default : $tmpuser->conf->$key); } /** diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 6cc135e3b2c..db11289d299 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1272,6 +1272,7 @@ TriggerActiveAsModuleActive=Triggers in this file are active as module %s GeneratedPasswordDesc=Choose the method to be used for auto-generated passwords. DictionaryDesc=Insert all reference data. You can add your values to the default. ConstDesc=This page allows you to edit (override) parameters not available in other pages. These are mostly reserved parameters for developers/advanced troubleshooting only. +MiscellaneousOptions=Miscellaneous options MiscellaneousDesc=All other security related parameters are defined here. LimitsSetup=Limits/Precision setup LimitsDesc=You can define limits, precisions and optimizations used by Dolibarr here diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index b9e35e1e9ea..0ba59834d71 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -5428,6 +5428,10 @@ td.cal_other_month { opacity: 0.8; } +td.event-past span { + opacity: 0.5; +} + /* ============================================================================== */ From 04ce79191fb24085c27969e5bbe60e5096340970 Mon Sep 17 00:00:00 2001 From: hystepik Date: Fri, 13 Jan 2023 12:18:58 +0100 Subject: [PATCH 521/816] Fix #23531 : fix update bom line --- htdocs/core/modules/modBom.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modBom.class.php b/htdocs/core/modules/modBom.class.php index 2e92d3baeaf..d6b9e7a6ff3 100644 --- a/htdocs/core/modules/modBom.class.php +++ b/htdocs/core/modules/modBom.class.php @@ -422,7 +422,7 @@ class modBom extends DolibarrModules $this->import_fieldshidden_array[$r] = array('extra.fk_object' => 'lastrowid-'.MAIN_DB_PREFIX.'bom_bomline'); $this->import_regex_array[$r] = array(); - $this->import_updatekeys_array[$r] = array('bd.fk_bom' => 'BOM Id'); + $this->import_updatekeys_array[$r] = array('bd.fk_bom' => 'BOM Id', 'bd.fk_product' => 'ProductRef'); $this->import_convertvalue_array[$r] = array( 'bd.fk_bom' => array( 'rule' => 'fetchidfromref', From 354b94abce48f77fad507376d8f6b803b2c9ac84 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 12:24:28 +0100 Subject: [PATCH 522/816] Merge manually #23539 --- htdocs/public/onlinesign/newonlinesign.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index f0738f0e420..c7c90b90229 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -545,6 +545,8 @@ if ($action == "dosign" && empty($cancel)) { $("#signbutton").attr("disabled",false); if(!$._data($("#signbutton")[0], "events")){ $("#signbutton").on("click",function(){ + console.log("We click on button sign"); + $("#signbutton").val(\''.dol_escape_js($langs->transnoentities('PleaseBePatient')).'\'); var signature = $("#signature").jSignature("getData", "image"); $.ajax({ type: "POST", From a42c879ac5589381ab83bcfcb14a54c67d9d4282 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 12:25:44 +0100 Subject: [PATCH 523/816] modify colspan --- htdocs/hrm/position_list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/hrm/position_list.php b/htdocs/hrm/position_list.php index 5dc33859219..201be040d20 100644 --- a/htdocs/hrm/position_list.php +++ b/htdocs/hrm/position_list.php @@ -608,7 +608,7 @@ while ($i < $imaxinloop) { if ($mode == 'kanban') { if ($i == 0) { - print ''; + print ''; print '
'; } // get info needed From d823971151a1145659a9920464664d973e3b4381 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 12:31:40 +0100 Subject: [PATCH 524/816] kanban for evaluation list --- htdocs/hrm/class/evaluation.class.php | 35 ++++++ htdocs/hrm/evaluation_list.php | 151 ++++++++++++++++---------- 2 files changed, 129 insertions(+), 57 deletions(-) diff --git a/htdocs/hrm/class/evaluation.class.php b/htdocs/hrm/class/evaluation.class.php index 4a41f1c8e0e..5a628725f95 100644 --- a/htdocs/hrm/class/evaluation.class.php +++ b/htdocs/hrm/class/evaluation.class.php @@ -1055,4 +1055,39 @@ class Evaluation extends CommonObject return $error; } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $selected, $langs; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + $return .= ''; + if (property_exists($this, 'fk_user') && !(empty($this->fk_user))) { + $return .= '
'.$langs->trans("Employee").' : '; + $return .= ''.$this->fk_user.''; + } + if (property_exists($this, 'fk_job') && !(empty($this->fk_job))) { + $return .= '
'.$langs->trans("Job").' : '; + $return .= ''.$this->fk_job.''; + } + + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= ''; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/hrm/evaluation_list.php b/htdocs/hrm/evaluation_list.php index dea398ad6a6..999d6d0d44e 100644 --- a/htdocs/hrm/evaluation_list.php +++ b/htdocs/hrm/evaluation_list.php @@ -52,6 +52,7 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'evaluationlist'; // 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', 'alpha'); // for mode view result $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -369,6 +370,9 @@ llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', ''); $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); } @@ -420,8 +424,12 @@ print ''; print ''; print ''; print ''; +print ''; -$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/evaluation_card.php', 1).'?action=create', '', $permissiontoadd); +$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')); +$newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/evaluation_card.php', 1).'?action=create', '', $permissiontoadd); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -568,75 +576,104 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // Store properties in $object $object->setVarsFromFetchObj($obj); - // Show here line of result - print ''; - foreach ($object->fields as $key => $val) { - $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); - if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { - $cssforfield .= ($cssforfield ? ' ' : '').'center'; - } elseif ($key == 'status') { - $cssforfield .= ($cssforfield ? ' ' : '').'center'; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; } + // Output Kanban + $object->date_eval = $obj->date_eval; - if (in_array($val['type'], array('timestamp'))) { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif ($key == 'ref') { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } + $job = new job($db); + $job->fetch($obj->fk_job); + $object->fk_job = $job->getNomUrl(); - if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { - $cssforfield .= ($cssforfield ? ' ' : '').'right'; - } - //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + $userstatic = new User($db); + $userstatic->fetch($obj->fk_user); + $object->fk_user = $userstatic->getNomUrl(1); - if (!empty($arrayfields['t.'.$key]['checked'])) { - print ''; - if ($key == 'status') { - print $object->getLibStatut(5); - } elseif ($key == 'rowid') { - print $object->showOutputField($val, $key, $object->id, ''); - } else { - print $object->showOutputField($val, $key, $object->$key, ''); + 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 ''; - if (!$i) { - $totalarray['nbfield']++; + print $object->getKanbanView(''); + } + if ($i == ($imaxinloop - 1)) { + print '
'; + print ''; + } + } else { + // Show here line of result + print ''; + foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; } - if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + + if (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif ($key == 'ref') { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + if ($key == 'status') { + print $object->getLibStatut(5); + } elseif ($key == 'rowid') { + print $object->showOutputField($val, $key, $object->id, ''); + } else { + print $object->showOutputField($val, $key, $object->$key, ''); + } + print ''; if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + $totalarray['nbfield']++; } - if (!isset($totalarray['val'])) { - $totalarray['val'] = array(); + if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + } + if (!isset($totalarray['val'])) { + $totalarray['val'] = array(); + } + if (!isset($totalarray['val']['t.'.$key])) { + $totalarray['val']['t.'.$key] = 0; + } + $totalarray['val']['t.'.$key] += $object->$key; } - if (!isset($totalarray['val']['t.'.$key])) { - $totalarray['val']['t.'.$key] = 0; - } - $totalarray['val']['t.'.$key] += $object->$key; } } - } - // Extra fields - 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; - // Action 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($object->id, $arrayofselected)) { - $selected = 1; + // Extra fields + 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; + // Action 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($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + if (!$i) { + $totalarray['nbfield']++; } - print ''; - } - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - print ''."\n"; + print ''."\n"; + } $i++; } From 19b77e3dcda2e862afe82cc2a7b13eac97bf9b58 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 12:33:25 +0100 Subject: [PATCH 525/816] modify checkbox action --- htdocs/hrm/position_list.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/htdocs/hrm/position_list.php b/htdocs/hrm/position_list.php index 201be040d20..7a6f7fcc417 100644 --- a/htdocs/hrm/position_list.php +++ b/htdocs/hrm/position_list.php @@ -622,7 +622,13 @@ while ($i < $imaxinloop) { $userstatic->fetch($obj->fk_user); $object->fk_user = $userstatic->getNomUrl(1); // output kanban - print $object->getKanbanView(''); + 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 $object->getKanbanView(''); + } if ($i == ($imaxinloop - 1)) { print '
'; print ''; From 2d3f7d949e56f88896637afde42afb444aa2e4a5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 12:53:56 +0100 Subject: [PATCH 526/816] Fix warnings --- htdocs/compta/resultat/result.php | 128 ++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 31 deletions(-) diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index 8615e595200..94a957a5c40 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -335,7 +335,7 @@ if ($modecompta == 'CREANCES-DETTES') { // Previous Fiscal year (N-1) foreach ($sommes as $code => $det) { - $vars[$code] = $det['NP']; + $vars[$code] = empty($det['NP']) ? 0 : $det['NP']; } $result = strtr($formula, $vars); @@ -355,12 +355,16 @@ if ($modecompta == 'CREANCES-DETTES') { // Year N $code = $cat['code']; // code of categorie ('VTE', 'MAR', ...) - $sommes[$code]['NP'] += $r; + if (empty($sommes[$code]['NP'])) { + $sommes[$code]['NP'] = $r; + } else { + $sommes[$code]['NP'] += $r; + } // Current fiscal year (N) if (is_array($sommes) && !empty($sommes)) { foreach ($sommes as $code => $det) { - $vars[$code] = $det['N']; + $vars[$code] = empty($det['N']) ? 0 : $det['N']; } } @@ -371,13 +375,17 @@ if ($modecompta == 'CREANCES-DETTES') { $r = dol_eval($result, 1, 1, '1'); print ''.price($r).''; - $sommes[$code]['N'] += $r; + if (empty($sommes[$code]['N'])) { + $sommes[$code]['N'] = $r; + } else { + $sommes[$code]['N'] += $r; + } // Detail by month foreach ($months as $k => $v) { if (($k + 1) >= $date_startmonth) { foreach ($sommes as $code => $det) { - $vars[$code] = $det['M'][$k]; + $vars[$code] = empty($det['M'][$k]) ? 0 : $det['M'][$k]; } $result = strtr($formula, $vars); $result = str_replace('--', '+', $result); @@ -386,14 +394,18 @@ if ($modecompta == 'CREANCES-DETTES') { $r = dol_eval($result, 1, 1, '1'); print ''.price($r).''; - $sommes[$code]['M'][$k] += $r; + if (empty($sommes[$code]['M'][$k])) { + $sommes[$code]['M'][$k] = $r; + } else { + $sommes[$code]['M'][$k] += $r; + } } } foreach ($months as $k => $v) { if (($k + 1) < $date_startmonth) { foreach ($sommes as $code => $det) { - $vars[$code] = $det['M'][$k]; + $vars[$code] = empty($det['M'][$k]) ? 0 : $det['M'][$k]; } $result = strtr($formula, $vars); $result = str_replace('--', '+', $result); @@ -402,7 +414,11 @@ if ($modecompta == 'CREANCES-DETTES') { $r = dol_eval($result, 1, 1, '1'); print ''.price($r).''; - $sommes[$code]['M'][$k] += $r; + if (empty($sommes[$code]['M'][$k])) { + $sommes[$code]['M'][$k] = $r; + } else { + $sommes[$code]['M'][$k] += $r; + } } } @@ -429,14 +445,14 @@ if ($modecompta == 'CREANCES-DETTES') { $arrayofaccountforfilter = array(); foreach ($cpts as $i => $cpt) { // Loop on each account. - if (!is_null($cpt['account_number'])) { + if (isset($cpt['account_number'])) { $arrayofaccountforfilter[] = $cpt['account_number']; } } // N-1 if (!empty($arrayofaccountforfilter)) { - $return = $AccCat->getSumDebitCredit($arrayofaccountforfilter, $date_start_previous, $date_end_previous, $cat['dc'] ? $cat['dc'] : 0); + $return = $AccCat->getSumDebitCredit($arrayofaccountforfilter, $date_start_previous, $date_end_previous, empty($cat['dc']) ? 0 : $cat['dc']); if ($return < 0) { setEventMessages(null, $AccCat->errors, 'errors'); $resultNP = 0; @@ -444,8 +460,16 @@ if ($modecompta == 'CREANCES-DETTES') { foreach ($cpts as $i => $cpt) { // Loop on each account found $resultNP = empty($AccCat->sdcperaccount[$cpt['account_number']]) ? 0 : $AccCat->sdcperaccount[$cpt['account_number']]; - $totCat['NP'] += $resultNP; - $sommes[$code]['NP'] += $resultNP; + if (empty($totCat['NP'])) { + $totCat['NP'] = $resultNP; + } else { + $totCat['NP'] += $resultNP; + } + if (empty($sommes[$code]['NP'])) { + $sommes[$code]['NP'] = $resultNP; + } else { + $sommes[$code]['NP'] += $resultNP; + } $totPerAccount[$cpt['account_number']]['NP'] = $resultNP; } } @@ -467,23 +491,47 @@ if ($modecompta == 'CREANCES-DETTES') { } //var_dump($monthtoprocess.'_'.$yeartoprocess); - $return = $AccCat->getSumDebitCredit($cpt['account_number'], $date_start, $date_end, $cat['dc'] ? $cat['dc'] : 0, 'nofilter', $monthtoprocess, $yeartoprocess); - if ($return < 0) { - setEventMessages(null, $AccCat->errors, 'errors'); - $resultM = 0; + if (isset($cpt['account_number'])) { + $return = $AccCat->getSumDebitCredit($cpt['account_number'], $date_start, $date_end, empty($cat['dc']) ? 0 : $cat['dc'], 'nofilter', $monthtoprocess, $yeartoprocess); + if ($return < 0) { + setEventMessages(null, $AccCat->errors, 'errors'); + $resultM = 0; + } else { + $resultM = $AccCat->sdc; + } } else { - $resultM = $AccCat->sdc; + $resultM = 0; + } + if (empty($totCat['M'][$k])) { + $totCat['M'][$k] = $resultM; + } else { + $totCat['M'][$k] += $resultM; + } + if (empty($sommes[$code]['M'][$k])) { + $sommes[$code]['M'][$k] = $resultM; + } else { + $sommes[$code]['M'][$k] += $resultM; + } + if (isset($cpt['account_number'])) { + $totPerAccount[$cpt['account_number']]['M'][$k] = $resultM; } - $totCat['M'][$k] += $resultM; - $sommes[$code]['M'][$k] += $resultM; - $totPerAccount[$cpt['account_number']]['M'][$k] = $resultM; $resultN += $resultM; } - $totCat['N'] += $resultN; - $sommes[$code]['N'] += $resultN; - $totPerAccount[$cpt['account_number']]['N'] = $resultN; + if (empty($totCat)) { + $totCat['N'] = $resultN; + } else { + $totCat['N'] += $resultN; + } + if (empty($sommes[$code]['N'])) { + $sommes[$code]['N'] = $resultN; + } else { + $sommes[$code]['N'] += $resultN; + } + if (isset($cpt['account_number'])) { + $totPerAccount[$cpt['account_number']]['N'] = $resultN; + } } @@ -543,16 +591,26 @@ if ($modecompta == 'CREANCES-DETTES') { // Loop on detail of all accounts to output the detail if ($showaccountdetail != 'no') { foreach ($cpts as $i => $cpt) { - $resultNP = $totPerAccount[$cpt['account_number']]['NP']; - $resultN = $totPerAccount[$cpt['account_number']]['N']; + if (isset($cpt['account_number'])) { + $resultNP = $totPerAccount[$cpt['account_number']]['NP']; + $resultN = $totPerAccount[$cpt['account_number']]['N']; + } else { + $resultNP = 0; + $resultN = 0; + } if ($showaccountdetail == 'all' || $resultN != 0) { print ''; print ''; - print ''; - print '     '.length_accountg($cpt['account_number']); - print ' - '; - print $cpt['account_label']; + + if (isset($cpt['account_number'])) { + $labeldetail = '     '.length_accountg($cpt['account_number']).' - '.$cpt['account_label']; + } else { + $labeldetail = '-'; + } + + print ''; + print dol_escape_htmltag($labeldetail); print ''; print ''.price($resultNP).''; print ''.price($resultN).''; @@ -560,13 +618,21 @@ if ($modecompta == 'CREANCES-DETTES') { // Make one call for each month foreach ($months as $k => $v) { if (($k + 1) >= $date_startmonth) { - $resultM = $totPerAccount[$cpt['account_number']]['M'][$k]; + if (isset($cpt['account_number'])) { + $resultM = $totPerAccount[$cpt['account_number']]['M'][$k]; + } else { + $resultM = 0; + } print ''.price($resultM).''; } } foreach ($months as $k => $v) { if (($k + 1) < $date_startmonth) { - $resultM = $totPerAccount[$cpt['account_number']]['M'][$k]; + if (isset($cpt['account_number'])) { + $resultM = empty($totPerAccount[$cpt['account_number']]['M'][$k]) ? 0 : $totPerAccount[$cpt['account_number']]['M'][$k]; + } else { + $resultM = 0; + } print ''.price($resultM).''; } } From fdfe27b5df3c6bf729d9003084c337f2e84c0072 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 12:55:08 +0100 Subject: [PATCH 527/816] Doc --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index f752894b4d2..3f30b2a2f99 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ English Dolibarr ChangeLog ***** ChangeLog for 18.0.0 compared to 17.0.0 ***** +NEW: PHP 8.2 compatibility: + + WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: From 276bca95d340bc0dd3fefe8b33a5739c1122aa9a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 13:28:40 +0100 Subject: [PATCH 528/816] CSS --- htdocs/admin/modules.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index db019bd262a..714d8fc7a0a 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -847,7 +847,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { if (getDolGlobalInt("MAIN_FEATURES_LEVEL") > 1) { $codeenabledisable .= ' '; $codeenabledisable .= '
'; - $codeenabledisable .= img_picto($langs->trans("Reload"), 'refresh', 'class="fa-15"'); + $codeenabledisable .= img_picto($langs->trans("Reload"), 'refresh', 'class="opacitymedium"'); $codeenabledisable .= ''; } } else { @@ -857,7 +857,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { if (getDolGlobalInt("MAIN_FEATURES_LEVEL") > 1) { $codeenabledisable .= ' '; $codeenabledisable .= ''; - $codeenabledisable .= img_picto($langs->trans("Reload"), 'refresh', 'class="fa-15"'); + $codeenabledisable .= img_picto($langs->trans("Reload"), 'refresh', 'class="opacitymedium"'); $codeenabledisable .= ''; } } From 5fc9e093eb9a51741b80c8eec6413bc0f50171b3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 14:09:54 +0100 Subject: [PATCH 529/816] css --- htdocs/admin/modules.php | 18 ++++++++++-------- htdocs/core/modules/DolibarrModules.class.php | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 714d8fc7a0a..ccda604d35d 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -776,15 +776,17 @@ if ($mode == 'common' || $mode == 'commonkanban') { // Version (with picto warning or not) $version = $objMod->getVersion(0); $versiontrans = ''; + $warningstring = ''; if (preg_match('/development/i', $version)) { - $versiontrans .= img_warning($langs->trans("Development"), '', 'floatleft paddingright'); + $warningstring = $langs->trans("Development"); } if (preg_match('/experimental/i', $version)) { - $versiontrans .= img_warning($langs->trans("Experimental"), '', 'floatleft paddingright'); + $warningstring = $langs->trans("Experimental"); } if (preg_match('/deprecated/i', $version)) { - $versiontrans .= img_warning($langs->trans("Deprecated"), '', 'floatleft paddingright'); + $warningstring = $langs->trans("Deprecated"); } + if ($objMod->isCoreOrExternalModule() == 'external' || preg_match('/development|experimental|deprecated/i', $version)) { $versiontrans .= $objMod->getVersion(1); } @@ -842,7 +844,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { } else { if (!empty($objMod->warnings_unactivation[$mysoc->country_code]) && method_exists($objMod, 'alreadyUsed') && $objMod->alreadyUsed()) { $codeenabledisable .= 'warnings_unactivation[$mysoc->country_code]).'&value='.$modName.'&mode='.$mode.$param.'">'; - $codeenabledisable .= img_picto($langs->trans("Activated"), 'switch_on'); + $codeenabledisable .= img_picto($langs->trans("Activated").($warningstring ? ' '.$warningstring : ''), 'switch_on'); $codeenabledisable .= ''; if (getDolGlobalInt("MAIN_FEATURES_LEVEL") > 1) { $codeenabledisable .= ' '; @@ -852,7 +854,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { } } else { $codeenabledisable .= ''; - $codeenabledisable .= img_picto($langs->trans("Activated"), 'switch_on'); + $codeenabledisable .= img_picto($langs->trans("Activated").($warningstring ? ' '.$warningstring : ''), 'switch_on'); $codeenabledisable .= ''; if (getDolGlobalInt("MAIN_FEATURES_LEVEL") > 1) { $codeenabledisable .= ' '; @@ -961,7 +963,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { // Output Kanban print $objMod->getKanbanView($codeenabledisable, $codetoconfig); } else { - print ''."\n"; + print ''."\n"; if (!empty($conf->global->MAIN_MODULES_SHOW_LINENUMBERS)) { print ''.$linenum.''; } @@ -995,7 +997,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { print ''; // Version - print ''; + print ''; if ($objMod->needUpdate) { $versionTitle = $langs->trans('ModuleUpdateAvailable').' : '.$objMod->lastVersion; print ''.$versiontrans.''; @@ -1005,7 +1007,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { print "\n"; // Link enable/disable - print ''; + print ''; print $codeenabledisable; print "\n"; diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 4027fb0cbf2..f4b3b3eef1f 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -792,8 +792,8 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it * For 'experimental' modules, gives 'experimental' translation * For 'dolibarr' modules, gives Dolibarr version * - * @param int $translated 1=Special version keys are translated, 0=Special version keys are not translated - * @return string Module version + * @param int $translated 1=Special version keys are translated, 0=Special version keys are not translated + * @return string Module version */ public function getVersion($translated = 1) { From 147e3ff945a31a5e04dab6a085fb4aa32f0a7605 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 14:13:52 +0100 Subject: [PATCH 530/816] kanban for list of holidays --- htdocs/holiday/class/holiday.class.php | 37 ++++ htdocs/holiday/list.php | 284 ++++++++++++++----------- htdocs/theme/eldy/info-box.inc.php | 5 + 3 files changed, 200 insertions(+), 126 deletions(-) diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 9b3f0a1ce16..e8f56659de9 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -2419,4 +2419,41 @@ class Holiday extends CommonObject return -1; } } + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs, $selected; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (property_exists($this, 'fk_user') && !empty($this->id)) { + $return .= '| '.$this->fk_user.''; + $return .= ''; + } + if (property_exists($this, 'fk_type')) { + $return .= '
'.$langs->trans("Type").' : '; + $return .= ''.$langs->trans($this->getTypes(1, -1)[$this->fk_type]['code']).''; + } + if (property_exists($this, 'date_debut') && property_exists($this, 'date_fin')) { + $return .= '
'.dol_print_date($this->date_debut, 'day').''; + $return .= ' '.$langs->trans("To").' '; + $return .= ''.dol_print_date($this->date_fin, 'day').''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index 564fb8a2a96..b16fbaf8c16 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -52,6 +52,7 @@ $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') : 'holidaylist'; // To manage different context of search +$mode = GETPOST('mode', 'alpha'); // for switch mode view result $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') @@ -394,6 +395,9 @@ if ($resql) { $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); } @@ -476,6 +480,8 @@ if ($resql) { print ''; print ''; print ''; + print ''; + if ($id > 0) { print ''; } @@ -519,7 +525,11 @@ if ($resql) { } else { $title = $langs->trans("ListeCP"); - $newcardbutton = dolGetButtonTitle($langs->trans('MenuAddCP'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/holiday/card.php?action=create', '', $user->rights->holiday->write); + + $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')); + $newcardbutton .= dolGetButtonTitle($langs->trans('MenuAddCP'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/holiday/card.php?action=create', '', $user->rights->holiday->write); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_hrm', 0, $newcardbutton, '', $limit, 0, 0, 1); } @@ -787,7 +797,8 @@ if ($resql) { $holidaystatic->id = $obj->rowid; $holidaystatic->ref = ($obj->ref ? $obj->ref : $obj->rowid); $holidaystatic->statut = $obj->status; - $holidaystatic->date_debut = $db->jdate($obj->date_debut); + $holidaystatic->date_debut = $obj->date_debut; + $holidaystatic->date_fin = $obj->date_fin; // User $userstatic->id = $obj->fk_user; @@ -815,139 +826,160 @@ if ($resql) { $starthalfday = ($obj->halfday == -1 || $obj->halfday == 2) ? 'afternoon' : 'morning'; $endhalfday = ($obj->halfday == 1 || $obj->halfday == 2) ? 'morning' : 'afternoon'; - print ''; - // 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 + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + + $holidaystatic->fk_type = $holidaystatic->getTypes(1, -1)[$obj->fk_type]['rowid']; + $holidaystatic->fk_user = $userstatic->getNomUrl(1); + // Output Kanban + if ($massactionbutton || $massaction) { $selected = 0; - if (in_array($obj->rowid, $arrayofselected)) { + if (in_array($object->id, $arrayofselected)) { $selected = 1; } - print ''; + print $holidaystatic->getKanbanView(''); } - print ''; - } - if (!empty($arrayfields['cp.ref']['checked'])) { - print ''; - print $holidaystatic->getNomUrl(1, 1); - print ''; - if (!$i) { - $totalarray['nbfield']++; + if ($i == (min($num, $limit) - 1)) { + print '
'; + print ''; } - } - if (!empty($arrayfields['cp.fk_user']['checked'])) { - print ''.$userstatic->getNomUrl(-1, 'leave').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['cp.fk_validator']['checked'])) { - print ''.$approbatorstatic->getNomUrl(-1).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['cp.fk_type']['checked'])) { - $labeltypeleavetoshow = ($langs->trans($typeleaves[$obj->fk_type]['code']) != $typeleaves[$obj->fk_type]['code'] ? $langs->trans($typeleaves[$obj->fk_type]['code']) : $typeleaves[$obj->fk_type]['label']); - $labeltypeleavetoshow = empty($typeleaves[$obj->fk_type]['label']) ? $langs->trans("TypeWasDisabledOrRemoved", $obj->fk_type) : $labeltypeleavetoshow; - - print ''; - print $labeltypeleavetoshow; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['duration']['checked'])) { - print ''; - $nbopenedday = num_open_day($db->jdate($obj->date_debut, 1), $db->jdate($obj->date_fin, 1), 0, 1, $obj->halfday); // user jdate(..., 1) because num_open_day need UTC dates - $totalduration += $nbopenedday; - print $nbopenedday; - //print ' '.$langs->trans('DurationDays'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['cp.date_debut']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_debut), 'day'); - print ' ('.$langs->trans($listhalfday[$starthalfday]).')'; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['cp.date_fin']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_fin), 'day'); - print ' ('.$langs->trans($listhalfday[$endhalfday]).')'; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date validation - if (!empty($arrayfields['cp.date_valid']['checked'])) { // date_valid is both date_valid but also date_approval - print ''; - print dol_print_date($db->jdate($obj->date_valid), 'day'); - print ''; - if (!$i) $totalarray['nbfield']++; - } - // Date approval - if (!empty($arrayfields['cp.date_approval']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_approval), 'day'); - print ''; - if (!$i) $totalarray['nbfield']++; - } - - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - - // Date creation - if (!empty($arrayfields['cp.date_create']['checked'])) { - print ''.dol_print_date($date, 'dayhour').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['cp.tms']['checked'])) { - print ''.dol_print_date($date_modif, 'dayhour').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - if (!empty($arrayfields['cp.statut']['checked'])) { - print ''.$holidaystatic->getLibStatut(5).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - - // 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->rowid, $arrayofselected)) { - $selected = 1; + } else { + print ''; + // 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print ''; } - print ''; - } - if (!$i) { - $totalarray['nbfield']++; - } + if (!empty($arrayfields['cp.ref']['checked'])) { + print ''; + print $holidaystatic->getNomUrl(1, 1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['cp.fk_user']['checked'])) { + print ''.$userstatic->getNomUrl(-1, 'leave').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['cp.fk_validator']['checked'])) { + print ''.$approbatorstatic->getNomUrl(-1).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['cp.fk_type']['checked'])) { + $labeltypeleavetoshow = ($langs->trans($typeleaves[$obj->fk_type]['code']) != $typeleaves[$obj->fk_type]['code'] ? $langs->trans($typeleaves[$obj->fk_type]['code']) : $typeleaves[$obj->fk_type]['label']); + $labeltypeleavetoshow = empty($typeleaves[$obj->fk_type]['label']) ? $langs->trans("TypeWasDisabledOrRemoved", $obj->fk_type) : $labeltypeleavetoshow; - print ''."\n"; + print ''; + print $labeltypeleavetoshow; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['duration']['checked'])) { + print ''; + $nbopenedday = num_open_day($db->jdate($obj->date_debut, 1), $db->jdate($obj->date_fin, 1), 0, 1, $obj->halfday); // user jdate(..., 1) because num_open_day need UTC dates + $totalduration += $nbopenedday; + print $nbopenedday; + //print ' '.$langs->trans('DurationDays'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['cp.date_debut']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_debut), 'day'); + print ' ('.$langs->trans($listhalfday[$starthalfday]).')'; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['cp.date_fin']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_fin), 'day'); + print ' ('.$langs->trans($listhalfday[$endhalfday]).')'; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date validation + if (!empty($arrayfields['cp.date_valid']['checked'])) { // date_valid is both date_valid but also date_approval + print ''; + print dol_print_date($db->jdate($obj->date_valid), 'day'); + print ''; + if (!$i) $totalarray['nbfield']++; + } + // Date approval + if (!empty($arrayfields['cp.date_approval']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_approval), 'day'); + print ''; + if (!$i) $totalarray['nbfield']++; + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + // Date creation + if (!empty($arrayfields['cp.date_create']['checked'])) { + print ''.dol_print_date($date, 'dayhour').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['cp.tms']['checked'])) { + print ''.dol_print_date($date_modif, 'dayhour').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + if (!empty($arrayfields['cp.statut']['checked'])) { + print ''.$holidaystatic->getLibStatut(5).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + + // 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + + print ''."\n"; + } $i++; } diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index f35516ad58e..5c010e21e26 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -492,6 +492,11 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { max-width: 350px; } +/**for make a checkbox in the right of the box in mode kanban */ +.fright { + float:right; +} + @media only screen and (max-width: 1740px) { .info-box-module { min-width: 315px; From ee7bcc3d129bac92a35ad37563e2cad677f7c502 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 14:16:22 +0100 Subject: [PATCH 531/816] modify style for checkbox --- htdocs/hrm/class/evaluation.class.php | 2 +- htdocs/theme/eldy/info-box.inc.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/hrm/class/evaluation.class.php b/htdocs/hrm/class/evaluation.class.php index 5a628725f95..c410ae8bd8f 100644 --- a/htdocs/hrm/class/evaluation.class.php +++ b/htdocs/hrm/class/evaluation.class.php @@ -1072,7 +1072,7 @@ class Evaluation extends CommonObject $return .= ''; $return .= '
'; $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; - $return .= ''; + $return .= ''; if (property_exists($this, 'fk_user') && !(empty($this->fk_user))) { $return .= '
'.$langs->trans("Employee").' : '; $return .= ''.$this->fk_user.''; diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index f35516ad58e..f13bd8c6c26 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -492,6 +492,10 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { max-width: 350px; } +/**for make a checkbox in the right of the box in mode kanban */ +.fright { + float:right; +} @media only screen and (max-width: 1740px) { .info-box-module { min-width: 315px; From 0ee90877aa0f20caeefe92614d474f6fc34d4f2e Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 14:17:49 +0100 Subject: [PATCH 532/816] modify style for checkbox --- htdocs/hrm/class/position.class.php | 2 +- htdocs/theme/eldy/info-box.inc.php | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index 9d4f71d24fd..2f4a127999a 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -1135,7 +1135,7 @@ class Position extends CommonObject $return .= ''; $return .= '
'; $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; - $return .= ''; + $return .= ''; if (property_exists($this, 'fk_user') && !(empty($this->fk_user))) { $return .= '
'.$langs->trans("Employee").' : '; $return .= ''.$this->fk_user.''; diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index f35516ad58e..9c1f3b443ef 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -491,7 +491,10 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { min-width: 350px; max-width: 350px; } - +/**for make a checkbox in the right of the box in mode kanban */ +.fright { + float:right; +} @media only screen and (max-width: 1740px) { .info-box-module { min-width: 315px; From 313608b6273d4e4134c2561a05f147f791e9f110 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 14:19:14 +0100 Subject: [PATCH 533/816] modify style for checkbox --- htdocs/hrm/class/job.class.php | 2 +- htdocs/theme/eldy/info-box.inc.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php index a013bb57a36..85845e557ab 100644 --- a/htdocs/hrm/class/job.class.php +++ b/htdocs/hrm/class/job.class.php @@ -1071,7 +1071,7 @@ class Job extends CommonObject $return .= ''; $return .= '
'; $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; - $return .= ''; + $return .= ''; if (property_exists($this, 'deplacement')) { $return .= '
'.$langs->trans("Type").''; $return .= ' : '.$this->fields['deplacement']['arrayofkeyval'][$this->deplacement].''; diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index f35516ad58e..f13bd8c6c26 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -492,6 +492,10 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { max-width: 350px; } +/**for make a checkbox in the right of the box in mode kanban */ +.fright { + float:right; +} @media only screen and (max-width: 1740px) { .info-box-module { min-width: 315px; From 782594ba5622e46dc8092ec79661440d3e77b2a1 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 14:27:19 +0100 Subject: [PATCH 534/816] fix problem style --- htdocs/compta/cashcontrol/cashcontrol_list.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/htdocs/compta/cashcontrol/cashcontrol_list.php b/htdocs/compta/cashcontrol/cashcontrol_list.php index b4c20a824ba..a1e5dae0c91 100644 --- a/htdocs/compta/cashcontrol/cashcontrol_list.php +++ b/htdocs/compta/cashcontrol/cashcontrol_list.php @@ -344,9 +344,6 @@ $param = ''; if (!empty($mode)) { $param .= '&mode='.urlencode($mode); } -if (!empty($mode)) { - $param .= '&mode='.urlencode($mode); -} if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } @@ -405,6 +402,7 @@ print ''; print ''; $permforcashfence = 1; + $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')); @@ -564,8 +562,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { print ''; print '
'; } - // Output Kanban - //var_dump($obj->posmodule);exit; + $object->posmodule = $obj->posmodule; $object->cash = $obj->cash; $object->opening = $obj->opening; From fcd82c93f2dd2a5e69577048fdf48f48da4ca941 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Fri, 13 Jan 2023 16:58:55 +0100 Subject: [PATCH 535/816] fix total days for both view --- htdocs/holiday/list.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index b16fbaf8c16..cef7375a4b6 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -826,6 +826,9 @@ if ($resql) { $starthalfday = ($obj->halfday == -1 || $obj->halfday == 2) ? 'afternoon' : 'morning'; $endhalfday = ($obj->halfday == 1 || $obj->halfday == 2) ? 'morning' : 'afternoon'; + $nbopenedday = num_open_day($db->jdate($obj->date_debut, 1), $db->jdate($obj->date_fin, 1), 0, 1, $obj->halfday); // user jdate(..., 1) because num_open_day need UTC dates + $totalduration += $nbopenedday; + if ($mode == 'kanban') { if ($i == 0) { print ''; From 97061a9a922bd9f75d67f7187943391502893105 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 17:17:23 +0100 Subject: [PATCH 536/816] NEW Use a cache file for external RSS in calendar --- htdocs/comm/action/class/ical.class.php | 35 ++++++++++++++++++++----- htdocs/comm/action/index.php | 16 ++++++++--- htdocs/core/lib/date.lib.php | 1 + htdocs/core/lib/functions.lib.php | 16 +++++++++++ 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/htdocs/comm/action/class/ical.class.php b/htdocs/comm/action/class/ical.class.php index badd5db5c98..26db2cd5e6e 100644 --- a/htdocs/comm/action/class/ical.class.php +++ b/htdocs/comm/action/class/ical.class.php @@ -54,8 +54,8 @@ class ICal /** * Read text file, icalender text file * - * @param string $file File - * @return string + * @param string $file File + * @return string|null Content of remote file read or null if error */ public function read_file($file) { @@ -65,7 +65,7 @@ class ICal $tmpresult = getURLContent($file, 'GET'); if ($tmpresult['http_code'] != 200) { - $file_text = ''; + $file_text = null; $this->error = 'Error: '.$tmpresult['http_code'].' '.$tmpresult['content']; } else { $file_text = preg_replace("/[\r\n]{1,} /", "", $tmpresult['content']); @@ -102,17 +102,40 @@ class ICal /** * Translate Calendar * - * @param string $uri Url + * @param string $uri Url + * @param string $usecachefile Full path of a cache file to use a cache file + * @param string $delaycache Delay in seconds for cache (by default 3600 secondes) * @return array|string */ - public function parse($uri) + public function parse($uri, $usecachefile = '', $delaycache = 3600) { $this->cal = array(); // new empty array $this->event_count = -1; + $this->file_text = null; + + // Save file into a cache + if ($usecachefile) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + $datefile = dol_filemtime($usecachefile); + $now = dol_now('gmt'); + //print $datefile.' '.$now.' ...'; + if ($datefile && $datefile > ($now - $delaycache)) { + // We reuse the cache file + $this->file_text = file_get_contents($usecachefile); + } + } // read FILE text - $this->file_text = $this->read_file($uri); + if (is_null($this->file_text)) { + $this->file_text = $this->read_file($uri); + + if ($usecachefile && !is_null($this->file_text)) { + // Save the file content into cache file + file_put_contents($usecachefile, $this->file_text, LOCK_EX); + dolChmod($usecachefile); + } + } $this->file_text = preg_split("[\n]", $this->file_text); diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 3460355a803..b4e11125aee 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -49,6 +49,7 @@ if (empty($conf->global->AGENDA_EXT_NB)) { $conf->global->AGENDA_EXT_NB = 5; } $MAXAGENDA = $conf->global->AGENDA_EXT_NB; +$DELAYFORCACHE = 300; // 300 seconds $disabledefaultvalues = GETPOST('disabledefaultvalues', 'int'); @@ -615,7 +616,7 @@ if (!empty($conf->use_javascript_ajax)) { // If javascript on $default = ''; } - $s .= '
 
'; + $s .= '
 
'; } } @@ -1010,9 +1011,13 @@ if ($mode == 'show_day') { // Request only leaves for the current selected day $sql .= " AND '".$db->escape($year)."-".$db->escape($month)."-".$db->escape($day)."' BETWEEN x.date_debut AND x.date_fin"; // date_debut and date_fin are date without time } elseif ($mode == 'show_week') { - // TODO: Add filter to reduce database request + // Restrict on current month (we get more, but we will filter later) + $sql .= " AND date_debut < '".dol_get_last_day($year, $month)."'"; + $sql .= " AND date_fin >= '".dol_get_first_day($year, $month)."'"; } elseif ($mode == 'show_month') { - // TODO: Add filter to reduce database request + // Restrict on current month + $sql .= " AND date_debut <= '".dol_get_last_day($year, $month)."'"; + $sql .= " AND date_fin >= '".dol_get_first_day($year, $month)."'"; } $resql = $db->query($sql); @@ -1083,8 +1088,11 @@ if (count($listofextcals)) { $colorcal = $extcal['color']; $buggedfile = $extcal['buggedfile']; + $pathforcachefile = dol_sanitizePathName($conf->user->dir_temp).'/'.dol_sanitizeFileName('extcal_'.$namecal.'_user'.$user->id).'.cache'; + //var_dump($pathforcachefile);exit; + $ical = new ICal(); - $ical->parse($url); + $ical->parse($url, $pathforcachefile, $DELAYFORCACHE); // After this $ical->cal['VEVENT'] contains array of events, $ical->cal['DAYLIGHT'] contains daylight info, $ical->cal['STANDARD'] contains non daylight info, ... //var_dump($ical->cal); exit; diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php index 03223a7b65a..773cb6a1a97 100644 --- a/htdocs/core/lib/date.lib.php +++ b/htdocs/core/lib/date.lib.php @@ -117,6 +117,7 @@ function getServerTimeZoneInt($refgmtdate = 'now') * @param int $duration_unit Unit of added delay (d, m, y, w, h, i) * @param int $ruleforendofmonth Change the behavior of PHP over data-interval, 0 or 1 * @return int New timestamp + * @see convertSecondToTime(), convertTimeToSeconds() */ function dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth = 0) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index ab96f650b6f..278f70507bb 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -6844,6 +6844,22 @@ function dol_mkdir($dir, $dataroot = '', $newmask = '') } +/** + * Change mod of a file + * + * @param string $filepath Full file path + * @return void + */ +function dolChmod($filepath) +{ + global $conf; + + if (!empty($conf->global->MAIN_UMASK)) { + @chmod($filepath, octdec($conf->global->MAIN_UMASK)); + } +} + + /** * Return picto saying a field is required * From 669beb50d25f810bf410bd1311e4e499c21747aa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 19:07:57 +0100 Subject: [PATCH 537/816] Better navigation bar for calendars --- htdocs/comm/action/index.php | 28 ++++++++++++++-------------- htdocs/comm/action/list.php | 2 +- htdocs/comm/action/pertype.php | 7 +++++-- htdocs/comm/action/peruser.php | 7 +++++-- htdocs/theme/eldy/global.inc.php | 13 +++++++++++++ htdocs/theme/md/style.css.php | 2 ++ 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index b4e11125aee..8ec011f5e9d 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -429,36 +429,33 @@ if ($mode == 'show_day' || $mode == 'show_week' || $mode == 'show_month') { } // Show navigation bar +$nav = ''; +$nav .= ''; $nav .= $form->selectDate($dateselect, 'dateselect', 0, 0, 1, '', 1, 0); //$nav .= ' '; @@ -497,7 +494,8 @@ print ''; //print_actions_filter($form, $canedit, $status, $year, $month, $day, $showbirthday, 0, $filtert, 0, $pid, $socid, $action, $listofextcals, $actioncode, $usergroup, '', $resourceid); //print dol_get_fiche_end(); -$viewmode = ''; +$viewmode = ''; + $viewmode .= ''; // To add a space before the navigation tools diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 5abd2d3f101..ab2037d5f76 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -600,7 +600,7 @@ $num = $db->num_rows($resql); $arrayofselected = is_array($toselect) ? $toselect : array(); // Local calendar -$newtitle = '
'; +$newtitle = '
'; $newtitle .= ' '.$langs->trans("LocalAgenda").'   '; $newtitle .= '
'; //$newtitle=$langs->trans($title); diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index ce33d0f40b2..c13de5fb183 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -368,12 +368,15 @@ $max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year, 'gmt')); $tmpday = $first_day; $picto = 'calendarweek'; -$nav = "
".img_previous($langs->trans("Previous"))."\n"; +// Show navigation bar +$nav = ''; $nav .= $form->selectDate($dateselect, 'dateselect', 0, 0, 1, '', 1, 0); $nav .= ' '; diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index bd35fc16e7d..0ee3b6db4a1 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -363,13 +363,16 @@ $max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year, 'gmt')); $tmpday = $first_day; $picto = 'calendarweek'; -$nav = "trans("Previous"))."\">   \n"; +// Show navigation bar +$nav = ''; $nav .= $form->selectDate($dateselect, 'dateselect', 0, 0, 1, '', 1, 0); $nav .= ' '; diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 0ba59834d71..061af67d2b5 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1432,6 +1432,9 @@ select.flat.selectlimit { .tablelistofcalendars { margin-top: 25px !important; } +.navselectiondate { + width: 250px; +} /* Styles for amount on card */ table.paymenttable td.amountpaymentcomplete, table.paymenttable td.amountremaintopay, table.paymenttable td.amountremaintopayback { @@ -1604,6 +1607,7 @@ table[summary="list_of_modules"] .fa-cog { .minwidth100 { min-width: 100px; } .minwidth150 { min-width: 150px; } .minwidth200 { min-width: 200px; } + .minwidth250 { min-width: 250px; } .minwidth300 { min-width: 300px; } .minwidth400 { min-width: 400px; } .minwidth500 { min-width: 500px; } @@ -1626,6 +1630,7 @@ table[summary="list_of_modules"] .fa-cog { .width125 { width: 125px; } .width150 { width: 150px; } .width200 { width: 200px; } +.width250 { width: 250px; } .width300 { width: 300px; } .width400 { width: 400px; } .width500 { width: 500px; } @@ -7532,6 +7537,14 @@ div.clipboardCPValue.hidewithsize { { .imgopensurveywizard, .imgautosize { width:95%; height: auto; } + .fiche > .listactionsfilter .table-fiche-title .col-title .titre { + display: none; + } + + .navselectiondate { + width: 220px; + } + #tooltip { position: absolute; width: px; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 39f6858570a..afc43936695 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1824,6 +1824,7 @@ tr.nobottom td { .minwidth100 { min-width: 100px; } .minwidth150 { min-width: 150px; } .minwidth200 { min-width: 200px; } + .minwidth250 { min-width: 250px; } .minwidth300 { min-width: 300px; } .minwidth400 { min-width: 400px; } .minwidth500 { min-width: 500px; } @@ -1847,6 +1848,7 @@ tr.nobottom td { .width125 { width: 125px; } .width150 { width: 150px; } .width200 { width: 200px; } +.width250 { width: 250px; } .width300 { width: 300px; } .width400 { width: 400px; } .width500 { width: 500px; } From 8efb2e8f8867bf0aa2a207daa370667bdb4f6338 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 19:44:35 +0100 Subject: [PATCH 538/816] Fix placeholder of status combo --- htdocs/admin/modules.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index ccda604d35d..6e0d90499d4 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -589,6 +589,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { $moreforfilter .= '
'; $moreforfilter .= $form->selectarray('search_nature', $arrayofnatures, dol_escape_htmltag($search_nature), $langs->trans('Origin'), 0, 0, '', 0, 0, 0, '', 'maxwidth250', 1); $moreforfilter .= '
'; + if (getDolGlobalInt('MAIN_FEATURES_LEVEL')) { $array_version = array('stable'=>$langs->transnoentitiesnoconv("Stable")); if ($conf->global->MAIN_FEATURES_LEVEL < 0) { @@ -601,11 +602,12 @@ if ($mode == 'common' || $mode == 'commonkanban') { $array_version['development'] = $langs->trans("Development"); } $moreforfilter .= '
'; - $moreforfilter .= $form->selectarray('search_version', $array_version, $search_version, $langs->trans('Version'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1); + $moreforfilter .= $form->selectarray('search_version', $array_version, $search_version, $langs->transnoentitiesnoconv('Version'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1); $moreforfilter .= '
'; } + $array_status = array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")); $moreforfilter .= '
'; - $moreforfilter .= $form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, $langs->trans('Status'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1); + $moreforfilter .= $form->selectarray('search_status', $array_status, $search_status, $langs->transnoentitiesnoconv('Status'), 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1); $moreforfilter .= '
'; $moreforfilter .= ' '; $moreforfilter .= '
'; From 00415dfe54a9fe505ef89ebc5846aca2461aa3a9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 19:53:31 +0100 Subject: [PATCH 539/816] css --- htdocs/theme/eldy/global.inc.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 061af67d2b5..bef2e6e7800 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -2012,11 +2012,12 @@ td.showDragHandle { z-index: 1005; } -global->THEME_DARKMODEENABLED)) { ?> -.side-nav-vert { - border-bottom: 1px solid #888; + +@media screen and (prefers-color-scheme: dark) { + .side-nav-vert { + border-bottom: 1px solid #888; + } } - .side-nav { /*display: block; From 1bd63b36d305f59a81b067e48387c003f8891022 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Jan 2023 19:57:14 +0100 Subject: [PATCH 540/816] Trans --- htdocs/langs/en_US/companies.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index e022c7cb09f..7200ffb3d70 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -312,8 +312,8 @@ CustomerRelativeDiscountShort=Relative discount CustomerAbsoluteDiscountShort=Absolute discount CompanyHasRelativeDiscount=This customer has a default discount of %s%% CompanyHasNoRelativeDiscount=This customer has no relative discount by default -HasRelativeDiscountFromSupplier=You have a default discount of %s%% from this vendor -HasNoRelativeDiscountFromSupplier=No default relative discount from this vendor +HasRelativeDiscountFromSupplier=You have a default discount of %s%% with this vendor +HasNoRelativeDiscountFromSupplier=No default relative discount with this vendor CompanyHasAbsoluteDiscount=This customer has discounts available (credits notes or down payments) for %s %s CompanyHasDownPaymentOrCommercialDiscount=This customer has discounts available (commercial, down payments) for %s %s CompanyHasCreditNote=This customer still has credit notes for %s %s From 317b49917aa7192abc9ae375f807e96731f95292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NASSIET?= Date: Fri, 13 Jan 2023 23:06:44 +0100 Subject: [PATCH 541/816] correctif hook --- htdocs/user/param_ihm.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index da8eebacaac..136da34e1bd 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -219,13 +219,12 @@ if (isModEnabled('ticket')) { $reshook = $hookmanager->executeHooks('addToLandingPageList', $tmparray, $object); if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); -} elseif ($reshook === 0) { - if (count($hookmanager->resArray)!==0) { - $tmparray=$hookmanager->resArray; - } +} elseif ($reshook > 0) { + $tmparray=$hookmanager->resArray; +} elseif ($reshook == 0) { + $tmparray=array_merge($tmparray, $hookmanager->resArray); } - $head = user_prepare_head($object); $title = $langs->trans("User"); From b11a6a1741b53a8283fdb25eea4fe47cf2d64d06 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 02:22:52 +0100 Subject: [PATCH 542/816] Fix link to download a file must contains &output=file --- htdocs/hrm/skill_tab.php | 5 ++++- htdocs/user/agenda_extsites.php | 5 ++++- htdocs/user/bank.php | 5 ++++- htdocs/user/card.php | 2 +- htdocs/user/clicktodial.php | 5 ++++- htdocs/user/document.php | 5 ++++- htdocs/user/info.php | 5 ++++- htdocs/user/note.php | 5 ++++- htdocs/user/notify/card.php | 5 ++++- htdocs/user/param_ihm.php | 5 ++++- htdocs/user/perms.php | 5 ++++- htdocs/user/virtualcard.php | 11 ++++------- 12 files changed, 45 insertions(+), 18 deletions(-) diff --git a/htdocs/hrm/skill_tab.php b/htdocs/hrm/skill_tab.php index b30484de54f..ce238b6caf4 100644 --- a/htdocs/hrm/skill_tab.php +++ b/htdocs/hrm/skill_tab.php @@ -226,10 +226,13 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } else { $linkback = '' . $langs->trans("BackToList") . ''; - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); + $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'rowid', $morehtmlref, '&objecttype='.$objecttype); } diff --git a/htdocs/user/agenda_extsites.php b/htdocs/user/agenda_extsites.php index 4891480cc2d..13948dc841e 100644 --- a/htdocs/user/agenda_extsites.php +++ b/htdocs/user/agenda_extsites.php @@ -170,10 +170,13 @@ if ($user->rights->user->user->lire || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } -$morehtmlref = ''; +$morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; +$urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); +$morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); diff --git a/htdocs/user/bank.php b/htdocs/user/bank.php index fb795ecc6e4..3d94d23f682 100644 --- a/htdocs/user/bank.php +++ b/htdocs/user/bank.php @@ -350,10 +350,13 @@ if ($action != 'edit' && $action != 'create') { // If not bank account yet, $ac $linkback = ''.$langs->trans("BackToList").''; } - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); + $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; diff --git a/htdocs/user/card.php b/htdocs/user/card.php index e7d001b1041..0d0c3e9f8dc 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1432,7 +1432,7 @@ if ($action == 'create' || $action == 'adduserldap') { if ($action != 'edit') { print dol_get_fiche_head($head, 'user', $title, -1, 'user'); - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard").' ('.$langs->trans("AddToContacts").')', 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/clicktodial.php b/htdocs/user/clicktodial.php index 562ab081ab8..985bf978074 100644 --- a/htdocs/user/clicktodial.php +++ b/htdocs/user/clicktodial.php @@ -106,10 +106,13 @@ if ($id > 0) { $linkback = ''.$langs->trans("BackToList").''; } - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); + $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; diff --git a/htdocs/user/document.php b/htdocs/user/document.php index b607cff7f3e..1a18cde92cc 100644 --- a/htdocs/user/document.php +++ b/htdocs/user/document.php @@ -152,10 +152,13 @@ if ($object->id) { $linkback = ''.$langs->trans("BackToList").''; } - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); + $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; diff --git a/htdocs/user/info.php b/htdocs/user/info.php index 3f5d1aea604..4a49fddf5c2 100644 --- a/htdocs/user/info.php +++ b/htdocs/user/info.php @@ -80,10 +80,13 @@ if ($user->rights->user->user->lire || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } -$morehtmlref = ''; +$morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; +$urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); +$morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); diff --git a/htdocs/user/note.php b/htdocs/user/note.php index 4b64a15d217..d189226d575 100644 --- a/htdocs/user/note.php +++ b/htdocs/user/note.php @@ -94,10 +94,13 @@ if ($id) { $linkback = ''.$langs->trans("BackToList").''; } - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); + $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; diff --git a/htdocs/user/notify/card.php b/htdocs/user/notify/card.php index e20d7be3d9a..e0c01ba5d58 100644 --- a/htdocs/user/notify/card.php +++ b/htdocs/user/notify/card.php @@ -155,10 +155,13 @@ if ($result > 0) { $linkback = ''.$langs->trans("BackToList").''; - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); + $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref, '', 0, '', '', 0, ''); print '
'; diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 3d2e3240ce3..b4a03fa700e 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -343,10 +343,13 @@ if ($action == 'edit') { $linkback = ''.$langs->trans("BackToList").''; - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; + $urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); + $morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); print '
'; diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index a65762b6183..22acb8ca7d9 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -255,10 +255,13 @@ if ($user->hasRight("user", "user", "read") || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } -$morehtmlref = ''; +$morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; +$urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); +$morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + dol_banner_tab($object, 'id', $linkback, $user->hasRight("user", "user", "read") || $user->admin, 'rowid', 'ref', $morehtmlref); diff --git a/htdocs/user/virtualcard.php b/htdocs/user/virtualcard.php index c2de7e17b06..ed3fbf7beb3 100644 --- a/htdocs/user/virtualcard.php +++ b/htdocs/user/virtualcard.php @@ -114,10 +114,13 @@ if ($user->rights->user->user->lire || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } -$morehtmlref = ''; +$morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; +$urltovirtualcard = '/user/virtualcard.php?id='.((int) $object->id); +$morehtmlref .= dolButtonToOpenUrlInDialogPopup('publicvirtualcard', $langs->trans("PublicVirtualCardUrl").' - '.$object->getFullName($langs), img_picto($langs->trans("PublicVirtualCardUrl"), 'card', 'class="valignmiddle marginleftonly paddingrightonly"'), $urltovirtualcard, '', 'nohover'); + //dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); @@ -126,12 +129,6 @@ print '
'; print '
'; /* - print ''.$langs->trans("VCard").'
'; - -print ''; -print img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); -print ''; - print '
'; //print '
'; From b4702aee2454c75e6ef442a8fa34fa71cf138717 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 02:31:53 +0100 Subject: [PATCH 543/816] Fix warning --- htdocs/core/class/vcard.class.php | 4 ++-- htdocs/user/card.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index 0e9372360e6..e7eb318e476 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -465,9 +465,9 @@ class vCard $this->setTitle($object->job); } - // For user, type=home + // For user, $object->url is not defined // For contact, $object->url is not defined - if ($object->url) { + if (!empty($object->url)) { $this->setURL($object->url, ""); } diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 0d0c3e9f8dc..2e2534621b1 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -2464,6 +2464,7 @@ if ($action == 'create' || $action == 'adduserldap') { // Country print ''.$form->editfieldkey('Country', 'selectcounty_id', '', $object, 0).''; + print img_picto('', 'country', 'class="pictofixedwidth"'); if ($caneditfield) { print $form->select_country((GETPOST('country_id') != '' ?GETPOST('country_id') : $object->country_id), 'country_id'); if ($user->admin) { From 09a0d579cebac0d7ee231856ffc42df2a5d1d90f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 02:40:44 +0100 Subject: [PATCH 544/816] Fix delete group of a user --- htdocs/user/card.php | 1 + htdocs/user/class/user.class.php | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 2e2534621b1..e995fc03001 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -375,6 +375,7 @@ if (empty($reshook)) { $editgroup->oldcopy = clone $editgroup; $object->fetch($id); + if ($action == 'addgroup') { $result = $object->SetInGroup($group, $editgroup->entity); } diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 65a7b7d7842..9e208ff3e37 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2651,7 +2651,11 @@ class User extends CommonObject $sql = "DELETE FROM ".$this->db->prefix()."usergroup_user"; $sql .= " WHERE fk_user = ".((int) $this->id); $sql .= " AND fk_usergroup = ".((int) $group); - $sql .= " AND entity = ".((int) $entity); + if (empty($entity)) { + $sql .= " AND entity IN (0, 1)"; // group may be in entity 0 (so $entity=0) and link with user into entity 1. + } else { + $sql .= " AND entity = ".((int) $entity); + } $result = $this->db->query($sql); if ($result) { From 0afcec9f43ddf8e196ecb7f437ba575dac4ca43e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 02:51:58 +0100 Subject: [PATCH 545/816] Clean code --- htdocs/main.inc.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index b2c76218a5d..9fec72e2e86 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -3208,7 +3208,6 @@ function printSearchForm($urlaction, $urlobject, $title, $htmlmorecss, $htmlinpu $ret = ''; $ret .= '
'; $ret .= ''; - $ret .= ''; $ret .= ''; if ($showtitlebefore) { $ret .= '
'.$title.'
'; From 704191b4d8bd3238cc29e2ab07f84e0f5d88e128 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 03:06:27 +0100 Subject: [PATCH 546/816] Try to fix name of download file --- htdocs/user/card.php | 2 +- htdocs/user/vcard.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index e995fc03001..9ea05b69805 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1433,7 +1433,7 @@ if ($action == 'create' || $action == 'adduserldap') { if ($action != 'edit') { print dol_get_fiche_head($head, 'user', $title, -1, 'user'); - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard").' ('.$langs->trans("AddToContacts").')', 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/vcard.php b/htdocs/user/vcard.php index 576d2b90a5b..695cd0e556e 100644 --- a/htdocs/user/vcard.php +++ b/htdocs/user/vcard.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2010 Laurent Destailleur + * Copyright (C) 2004-2023 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2020 Tobias Sekan * Copyright (C) 2021-2022 Anthony Berton From 35eeb4a3c0e840f11f25eefb213d8f574ecafe33 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 03:15:46 +0100 Subject: [PATCH 547/816] Fix download link --- htdocs/hrm/skill_tab.php | 2 +- htdocs/user/agenda_extsites.php | 2 +- htdocs/user/bank.php | 2 +- htdocs/user/card.php | 2 +- htdocs/user/clicktodial.php | 2 +- htdocs/user/document.php | 2 +- htdocs/user/info.php | 2 +- htdocs/user/note.php | 2 +- htdocs/user/notify/card.php | 2 +- htdocs/user/param_ihm.php | 2 +- htdocs/user/perms.php | 2 +- htdocs/user/virtualcard.php | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/htdocs/hrm/skill_tab.php b/htdocs/hrm/skill_tab.php index ce238b6caf4..705b4fc200e 100644 --- a/htdocs/hrm/skill_tab.php +++ b/htdocs/hrm/skill_tab.php @@ -226,7 +226,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea } else { $linkback = '' . $langs->trans("BackToList") . ''; - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/agenda_extsites.php b/htdocs/user/agenda_extsites.php index 13948dc841e..3b9ebd007f6 100644 --- a/htdocs/user/agenda_extsites.php +++ b/htdocs/user/agenda_extsites.php @@ -170,7 +170,7 @@ if ($user->rights->user->user->lire || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } -$morehtmlref = ''; +$morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/bank.php b/htdocs/user/bank.php index 3d94d23f682..7040add3950 100644 --- a/htdocs/user/bank.php +++ b/htdocs/user/bank.php @@ -350,7 +350,7 @@ if ($action != 'edit' && $action != 'create') { // If not bank account yet, $ac $linkback = ''.$langs->trans("BackToList").''; } - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 9ea05b69805..67ea2174322 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1433,7 +1433,7 @@ if ($action == 'create' || $action == 'adduserldap') { if ($action != 'edit') { print dol_get_fiche_head($head, 'user', $title, -1, 'user'); - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard").' ('.$langs->trans("AddToContacts").')', 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/clicktodial.php b/htdocs/user/clicktodial.php index 985bf978074..d2f9452bac5 100644 --- a/htdocs/user/clicktodial.php +++ b/htdocs/user/clicktodial.php @@ -106,7 +106,7 @@ if ($id > 0) { $linkback = ''.$langs->trans("BackToList").''; } - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/document.php b/htdocs/user/document.php index 1a18cde92cc..f99eb9982a2 100644 --- a/htdocs/user/document.php +++ b/htdocs/user/document.php @@ -152,7 +152,7 @@ if ($object->id) { $linkback = ''.$langs->trans("BackToList").''; } - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/info.php b/htdocs/user/info.php index 4a49fddf5c2..7804579edd5 100644 --- a/htdocs/user/info.php +++ b/htdocs/user/info.php @@ -80,7 +80,7 @@ if ($user->rights->user->user->lire || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } -$morehtmlref = ''; +$morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/note.php b/htdocs/user/note.php index d189226d575..b3ee9398374 100644 --- a/htdocs/user/note.php +++ b/htdocs/user/note.php @@ -94,7 +94,7 @@ if ($id) { $linkback = ''.$langs->trans("BackToList").''; } - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/notify/card.php b/htdocs/user/notify/card.php index e0c01ba5d58..e63269d5fa6 100644 --- a/htdocs/user/notify/card.php +++ b/htdocs/user/notify/card.php @@ -155,7 +155,7 @@ if ($result > 0) { $linkback = ''.$langs->trans("BackToList").''; - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index b4a03fa700e..ee0f1d13914 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -343,7 +343,7 @@ if ($action == 'edit') { $linkback = ''.$langs->trans("BackToList").''; - $morehtmlref = ''; + $morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index 22acb8ca7d9..23265513730 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -255,7 +255,7 @@ if ($user->hasRight("user", "user", "read") || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } -$morehtmlref = ''; +$morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; diff --git a/htdocs/user/virtualcard.php b/htdocs/user/virtualcard.php index ed3fbf7beb3..7e13950747c 100644 --- a/htdocs/user/virtualcard.php +++ b/htdocs/user/virtualcard.php @@ -114,7 +114,7 @@ if ($user->rights->user->user->lire || $user->admin) { $linkback = ''.$langs->trans("BackToList").''; } -$morehtmlref = ''; +$morehtmlref = ''; $morehtmlref .= img_picto($langs->trans("Download").' '.$langs->trans("VCard"), 'vcard.png', 'class="valignmiddle marginleftonly paddingrightonly"'); $morehtmlref .= ''; From 79ecc945e9b1351b0364f64a9eb8cfe5780ab2bc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 11:43:47 +0100 Subject: [PATCH 548/816] Fix warning --- htdocs/bookmarks/list.php | 1 + htdocs/core/menus/standard/eldy_menu.php | 2 +- htdocs/core/search_page.php | 4 ++-- htdocs/modulebuilder/template/myobject_list.php | 10 +++++----- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/htdocs/bookmarks/list.php b/htdocs/bookmarks/list.php index 9434cf031a2..2500d40e25d 100644 --- a/htdocs/bookmarks/list.php +++ b/htdocs/bookmarks/list.php @@ -37,6 +37,7 @@ $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bookmarklist'; // To manage different context of search $id = GETPOST("id", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); +$mode = GETPOST('mode', 'aZ09'); // Load variable for pagination $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; diff --git a/htdocs/core/menus/standard/eldy_menu.php b/htdocs/core/menus/standard/eldy_menu.php index bbcd0cacf25..596e1e4cc3f 100644 --- a/htdocs/core/menus/standard/eldy_menu.php +++ b/htdocs/core/menus/standard/eldy_menu.php @@ -204,7 +204,7 @@ class MenuManager //if ($tmpmainmenu=='accountancy') { //var_dump($submenu->liste); exit; //} - $nexturl = dol_buildpath($submenu->liste[0]['url'], 1); + $nexturl = dol_buildpath(empty($submenu->liste[0]['url']) ? '' : $submenu->liste[0]['url'], 1); $canonrelurl = preg_replace('/\?.*$/', '', $relurl); $canonnexturl = preg_replace('/\?.*$/', '', $nexturl); diff --git a/htdocs/core/search_page.php b/htdocs/core/search_page.php index 4f6911497e4..2e5cad17c58 100644 --- a/htdocs/core/search_page.php +++ b/htdocs/core/search_page.php @@ -109,8 +109,8 @@ if ($conf->use_javascript_ajax && 1 == 2) { // select2 is not best with smartp $keysearch = 'search_all'; $accesskey = ''; - if (!$accesskeyalreadyassigned[$val['label'][0]]) { - $accesskey = $val['label'][0]; + if (empty($accesskeyalreadyassigned[$val['label'][0]])) { + $accesskey = $val['label'][0]; // First char of string $accesskeyalreadyassigned[$accesskey] = $accesskey; } diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 29c9205b1f0..1135f6d9498 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -87,7 +87,7 @@ require_once __DIR__.'/class/myobject.class.php'; // Load translation files required by the page $langs->loadLangs(array("mymodule@mymodule", "other")); -$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... +$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 @@ -96,7 +96,7 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $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'); +$mode = GETPOST('mode', 'aZ'); // The output mode ('list', 'kanban', 'hierarchy', 'calendar', ...) $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -182,9 +182,9 @@ $arrayfields = dol_sort_array($arrayfields, 'position'); // Set $enablepermissioncheck to 1 to enable a minimum low level of checks $enablepermissioncheck = 0; if ($enablepermissioncheck) { - $permissiontoread = $user->rights->mymodule->myobject->read; - $permissiontoadd = $user->rights->mymodule->myobject->write; - $permissiontodelete = $user->rights->mymodule->myobject->delete; + $permissiontoread = $user->hasRight('mymodule', 'myobject', 'read'); + $permissiontoadd = $user->hasRight('mymodule', 'myobject', 'write'); + $permissiontodelete = $user->hasRight('mymodule', 'myobject', 'delete'); } else { $permissiontoread = 1; $permissiontoadd = 1; From b7c56f5680c74a33809b9999a1ad02d1742c447b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 11:54:05 +0100 Subject: [PATCH 549/816] Fix warning --- htdocs/bookmarks/card.php | 8 +++++--- htdocs/bookmarks/list.php | 10 ++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/htdocs/bookmarks/card.php b/htdocs/bookmarks/card.php index 5b22b8918d9..245161ed253 100644 --- a/htdocs/bookmarks/card.php +++ b/htdocs/bookmarks/card.php @@ -188,7 +188,8 @@ if ($action == 'create') { // Visibility / Owner print ''.$langs->trans("Visibility").''; - print img_picto('', 'user').' '.$form->select_dolusers(GETPOSTISSET('userid') ? GETPOST('userid', 'int') : $user->id, 'userid', 0, '', 0, ($user->admin ? '' : array($user->id)), '', 0, 0, 0, '', ($user->admin) ? 1 : 0, '', 'maxwidth300 widthcentpercentminusx'); + print img_picto('', 'user', 'class="pictofixedwidth"'); + print $form->select_dolusers(GETPOSTISSET('userid') ? GETPOST('userid', 'int') : $user->id, 'userid', 0, '', 0, ($user->admin ? '' : array($user->id)), '', 0, 0, 0, '', ($user->admin) ? 1 : 0, '', 'maxwidth300 widthcentpercentminusx'); print ''; // Position @@ -282,12 +283,13 @@ if ($id > 0 && !preg_match('/^add/i', $action)) { // Visibility / owner print ''.$langs->trans("Visibility").''; if ($action == 'edit' && $user->admin) { - print img_picto('', 'user').' '.$form->select_dolusers(GETPOSTISSET('userid') ? GETPOST('userid', 'int') : ($object->fk_user ? $object->fk_user : ''), 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth300 widthcentpercentminusx'); + print img_picto('', 'user', 'class="pictofixedwidth"'); + print $form->select_dolusers(GETPOSTISSET('userid') ? GETPOST('userid', 'int') : ($object->fk_user ? $object->fk_user : ''), 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth300 widthcentpercentminusx'); } else { if ($object->fk_user > 0) { $fuser = new User($db); $fuser->fetch($object->fk_user); - print $fuser->getNomUrl(1); + print $fuser->getNomUrl(-1); } else { print ''.$langs->trans("Everybody").''; } diff --git a/htdocs/bookmarks/list.php b/htdocs/bookmarks/list.php index 2500d40e25d..2adef615a70 100644 --- a/htdocs/bookmarks/list.php +++ b/htdocs/bookmarks/list.php @@ -212,8 +212,6 @@ print_liste_field_titre("Position", $_SERVER["PHP_SELF"], "b.position", "", $par print_liste_field_titre(''); print "\n"; -$cacheOfUsers = array(); - $i = 0; while ($i < min($num, $limit)) { $obj = $db->fetch_object($resql); @@ -268,13 +266,13 @@ while ($i < min($num, $limit)) { // Author print ''; if ($obj->fk_user) { - if (empty($cacheOfUsers[$obj->fk_user])) { + if (empty($conf->cache['users'][$obj->fk_user])) { $tmpuser = new User($db); $tmpuser->fetch($obj->fk_user); - $cacheOfUsers[$obj->fk_user] = $tmpuser; + $conf->cache['users'][$obj->fk_user] = $tmpuser; } - $tmpuser = $cacheOfUsers[$obj->fk_user]; - print $tmpuser->getNomUrl(1); + $tmpuser = $conf->cache['users'][$obj->fk_user]; + print $tmpuser->getNomUrl(-1); } else { print ''.$langs->trans("Everybody").''; if (!$user->admin) { From e4515f01c04763794b3789e5fadcfcf16bf81b9d Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 14 Jan 2023 11:56:41 +0100 Subject: [PATCH 550/816] Fix php 8 warnings --- htdocs/core/lib/ticket.lib.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/core/lib/ticket.lib.php b/htdocs/core/lib/ticket.lib.php index 5d0d691228e..2c218421543 100644 --- a/htdocs/core/lib/ticket.lib.php +++ b/htdocs/core/lib/ticket.lib.php @@ -91,7 +91,7 @@ function ticket_prepare_head($object) $head[$h][2] = 'tabTicket'; $h++; - if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && empty($user->socid) && isModEnabled("societe")) { + if (!getDolGlobalInt('MAIN_DISABLE_CONTACTS_TAB') && empty($user->socid) && isModEnabled("societe")) { $nbContact = count($object->liste_contact(-1, 'internal')) + count($object->liste_contact(-1, 'external')); $head[$h][0] = DOL_URL_ROOT.'/ticket/contact.php?track_id='.$object->track_id; $head[$h][1] = $langs->trans('ContactsAddresses'); @@ -166,7 +166,7 @@ function showDirectPublicLink($object) } $out = ''; - if (empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE)) { + if (!getDolGlobalInt('TICKET_ENABLE_PUBLIC_INTERFACE')) { $langs->load('errors'); $out .= ''.$langs->trans("ErrorPublicInterfaceNotEnabled").''; } else { @@ -223,9 +223,9 @@ function llxHeaderTicket($title, $head = "", $disablejs = 0, $disablehead = 0, $ print '
'; // Define urllogo - if (!empty($conf->global->TICKET_SHOW_COMPANY_LOGO) || !empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) { + if (getDolGlobalInt('TICKET_SHOW_COMPANY_LOGO') || getDolGlobalString('TICKET_PUBLIC_INTERFACE_TOPIC')) { // Print logo - if (!empty($conf->global->TICKET_SHOW_COMPANY_LOGO)) { + if (getDolGlobalInt('TICKET_SHOW_COMPANY_LOGO')) { $urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png'; if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) { @@ -239,28 +239,28 @@ function llxHeaderTicket($title, $head = "", $disablejs = 0, $disablehead = 0, $ } // Output html code for logo - if ($urllogo || !empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) { + if ($urllogo || getDolGlobalInt('TICKET_PUBLIC_INTERFACE_TOPIC')) { print '
'; print '
'; if ($urllogo) { - print ''; + print ''; print ''; print ''; } - if (!empty($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC)) { - print '
'.($conf->global->TICKET_PUBLIC_INTERFACE_TOPIC ? $conf->global->TICKET_PUBLIC_INTERFACE_TOPIC : $langs->trans("TicketSystem")).''; + if (getDolGlobalInt('TICKET_PUBLIC_INTERFACE_TOPIC')) { + print '
'.(getDolGlobalString('TICKET_PUBLIC_INTERFACE_TOPIC') ? getDolGlobalString('TICKET_PUBLIC_INTERFACE_TOPIC') : $langs->trans("TicketSystem")).''; } print '
'; - if (empty($conf->global->MAIN_HIDE_POWERED_BY)) { + if (!getDolGlobalInt('MAIN_HIDE_POWERED_BY')) { print ''; } print '
'; } - if (!empty($conf->global->TICKET_IMAGE_PUBLIC_INTERFACE)) { + if (getDolGlobalInt('TICKET_IMAGE_PUBLIC_INTERFACE')) { print '
'; - print ''; + print ''; print '
'; } From 236b3aa9e89d2049c186d16d79f0612be21a7476 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 12:28:44 +0100 Subject: [PATCH 551/816] Revert default type of hooks. Default is now 'addreplace' hooks (and exception become 'output' hooks, that become deprecated). --- ChangeLog | 5 +- htdocs/core/class/hookmanager.class.php | 116 ++++++------------ htdocs/document.php | 5 +- htdocs/main.inc.php | 6 +- htdocs/mrp/index.php | 3 +- .../variants/class/ProductAttribute.class.php | 2 +- .../productattributevalueline_edit.tpl.php | 2 +- htdocs/webhook/target_card.php | 4 +- 8 files changed, 54 insertions(+), 89 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3f30b2a2f99..1a3e96b18ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,8 +11,9 @@ NEW: PHP 8.2 compatibility: WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: -* The deprecated method escapeunderscore() of database handlers has been removed. You must use escapeforlike instead. -* The method nb_expedition() has been renamed into countNbOfShipments() +* The deprecated method "escapeunderscore()" of database handlers has been removed. You must use "escapeforlike()" instead. +* The method "nb_expedition()" has been renamed into "countNbOfShipments()" +* Revert default type of hooks. Default is now 'addreplace' hooks (and exception become 'output' hooks, that become deprecated). diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 0659240c8c7..7a6af7b88ec 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -162,84 +162,44 @@ class HookManager //dol_syslog(get_class($this).'::executeHooks method='.$method." action=".$action." context=".$parameters['context']); // Define type of hook ('output' or 'addreplace'). - // TODO Remove hooks with type 'output' (exemple getNomUrl). All hooks must be converted into 'addreplace' hooks. - $hooktype = 'output'; - if (in_array( - $method, - array( - 'addCalendarChoice', - 'addCalendarView', - 'addMoreActionsButtons', - 'addMoreMassActions', - 'addSearchEntry', - 'addStatisticLine', - 'addSectionECMAuto', - 'checkSecureAccess', - 'createDictionaryFieldlist', - 'editDictionaryFieldlist', - 'getFormMail', - 'deleteFile', - 'doActions', - 'doMassActions', - 'formatEvent', - 'formConfirm', - 'formCreateThirdpartyOptions', - 'formObjectOptions', - 'formattachOptions', - 'formBuilddocLineOptions', - 'formatNotificationMessage', - 'formConfirm', - 'getAccessForbiddenMessage', - 'getDirList', - 'hookGetEntity', - 'getFormMail', - 'getFormatedCustomerRef', - 'getFormatedSupplierRef', - 'getIdProfUrl', - 'getInputIdProf', - 'isPaymentOK', - 'llxFooter', - 'menuDropdownQuickaddItems', - 'menuLeftMenuItems', - 'moveUploadedFile', - 'moreHtmlStatus', - 'pdf_build_address', - 'pdf_writelinedesc', - 'pdf_getlinenum', - 'pdf_getlineref', - 'pdf_getlineref_supplier', - 'pdf_getlinevatrate', - 'pdf_getlineupexcltax', - 'pdf_getlineupwithtax', - 'pdf_getlineqty', - 'pdf_getlineqty_asked', - 'pdf_getlineqty_shipped', - 'pdf_getlineqty_keeptoship', - 'pdf_getlineunit', - 'pdf_getlineremisepercent', - 'pdf_getlineprogress', - 'pdf_getlinetotalexcltax', - 'pdf_getlinetotalwithtax', - 'paymentsupplierinvoices', - 'printAddress', - 'printEmail', - 'printSearchForm', - 'printTabsHead', - 'printObjectLine', - 'printObjectSubLine', - 'restrictedArea', - 'sendMail', - 'sendMailAfter', - 'showOptionals', - 'showLinkToObjectBlock', - 'setContentSecurityPolicy', - 'setHtmlTitle', - 'completeTabsHead', - 'formDolBanner', - 'displayMarginInfos', - ) - )) { - $hooktype = 'addreplace'; + $hooktype = 'addreplace'; + // TODO Remove hooks with type 'output' (exemple createFrom). All hooks must be converted into 'addreplace' hooks. + if (!in_array($method, array( + 'createFrom', + 'dashboardMembers', + 'dashboardEmailings', + 'dashboardPropals', + 'dashboardPropals', + 'dashboardCommercials', + 'dashboardOrders', + 'dashboardSpecialBills', + 'dashboardAccountancy', + 'dashboardContracts', + 'dashboardDonation', + 'dashboardWarehouseSendings', + 'dashboardExpenseReport', + 'dashboardInterventions', + 'dashboardOrdersSuppliers', + 'dashboardHRM', + 'dashboardMRP', + 'dashboardOpensurvey', + 'dashboardWarehouse', + 'dashboardProductServices', + 'dashboardActivities', + 'dashboardProjects', + 'dashboardWarehouseReceptions', + 'dashboardThirdparties', + 'dashboardSupplierProposal', + 'dashboardTickets', + 'dashboardUsersGroups', + 'insertExtraHeader', + 'insertExtraFooter', + 'printLeftBlock', + 'formAddObjectLine', + 'formBuilddocOption', + 'showSocinfoOnPrint' + ))) { + $hooktype = 'output'; } // Init return properties diff --git a/htdocs/document.php b/htdocs/document.php index 4f6652fafda..eccf49de0be 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -286,9 +286,10 @@ $hookmanager->initHooks(array('document')); $parameters = array('ecmfile' => $ecmfile, 'modulepart' => $modulepart, 'original_file' => $original_file, 'entity' => $entity, 'refname' => $refname, 'fullpath_original_file' => $fullpath_original_file, 'filename' => $filename, 'fullpath_original_file_osencoded' => $fullpath_original_file_osencoded); -$reshook = $hookmanager->executeHooks('downloadDocument', $parameters); // Note that $action and $object may have been +$object = new stdClass(); +$reshook = $hookmanager->executeHooks('downloadDocument', $parameters, $object, $action); // Note that $action and $object may have been if ($reshook < 0) { - $errors = $hookmanager->error.(is_array($hookmanager->errors) ? (!empty($hookmanager->error) ? ', ' : '').join($separator, $hookmanager->errors) : ''); + $errors = $hookmanager->error.(is_array($hookmanager->errors) ? (!empty($hookmanager->error) ? ', ' : '').join(', ', $hookmanager->errors) : ''); dol_syslog("document.php - Errors when executing the hook 'downloadDocument' : ".$errors); print "ErrorDownloadDocumentHooks: ".$errors; exit; diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 9fec72e2e86..549c72157a6 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2603,11 +2603,11 @@ function printDropdownQuickadd() $parameters = array(); $hook_items = $items; $reshook = $hookmanager->executeHooks('menuDropdownQuickaddItems', $parameters, $hook_items); // Note that $action and $object may have been modified by some hooks - if (is_numeric($reshook) && !empty($hookmanager->results) && is_array($hookmanager->results)) { + if (is_numeric($reshook) && !empty($hookmanager->resArray) && is_array($hookmanager->resArray)) { if ($reshook == 0) { - $items['items'] = array_merge($items['items'], $hookmanager->results); // add + $items['items'] = array_merge($items['items'], $hookmanager->resArray); // add } else { - $items = $hookmanager->results; // replace + $items = $hookmanager->resArray; // replace } // Sort menu items by 'position' value diff --git a/htdocs/mrp/index.php b/htdocs/mrp/index.php index d7929ce1422..835a06cc7c6 100644 --- a/htdocs/mrp/index.php +++ b/htdocs/mrp/index.php @@ -249,11 +249,12 @@ if ($resql) { print '
'; +$object = new stdClass(); $parameters = array( //'type' => $type, 'user' => $user, ); -$reshook = $hookmanager->executeHooks('dashboardMRP', $parameters); +$reshook = $hookmanager->executeHooks('dashboardMRP', $parameters, $object); // End of page llxFooter(); diff --git a/htdocs/variants/class/ProductAttribute.class.php b/htdocs/variants/class/ProductAttribute.class.php index f89adcce0f8..74ff3fe238c 100644 --- a/htdocs/variants/class/ProductAttribute.class.php +++ b/htdocs/variants/class/ProductAttribute.class.php @@ -919,7 +919,7 @@ class ProductAttribute extends CommonObject $parameters = array('rowid' => $rowid, 'position' => $position); $action = ''; $reshook = $hookmanager->executeHooks('afterPositionOfAttributeUpdate', $parameters, $this, $action); - return 1; + return ($reshook >= 0 ? 1 : -1); } } diff --git a/htdocs/variants/tpl/productattributevalueline_edit.tpl.php b/htdocs/variants/tpl/productattributevalueline_edit.tpl.php index 3b842962258..60fc81c7418 100644 --- a/htdocs/variants/tpl/productattributevalueline_edit.tpl.php +++ b/htdocs/variants/tpl/productattributevalueline_edit.tpl.php @@ -54,7 +54,7 @@ $coldisplay++; ref); ?>"> $line); + $parameters = array('line' => $line); $reshook = $hookmanager->executeHooks('formEditProductOptions', $parameters, $object, $action); if (!empty($hookmanager->resPrint)) { print $hookmanager->resPrint; diff --git a/htdocs/webhook/target_card.php b/htdocs/webhook/target_card.php index 83f2008703f..a35f04d0138 100644 --- a/htdocs/webhook/target_card.php +++ b/htdocs/webhook/target_card.php @@ -430,7 +430,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $parameters = array(); $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook - if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } if (empty($reshook)) $object->formAddObjectLine(1, $mysoc, $soc); } From f0f3deb6198130d6e8a150021db0a6422534acbe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 13:06:13 +0100 Subject: [PATCH 552/816] Debug v17 --- htdocs/compta/bank/class/account.class.php | 6 +- htdocs/user/bank.php | 89 +++++++-------------- htdocs/user/class/userbankaccount.class.php | 61 +++++++++++++- htdocs/user/notify/card.php | 6 +- 4 files changed, 95 insertions(+), 67 deletions(-) diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 4aea92a510e..74db4005126 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -1077,8 +1077,6 @@ class Account extends CommonObject */ public function delete(User $user = null) { - global $conf; - $error = 0; $this->db->begin(); @@ -1096,8 +1094,8 @@ class Account extends CommonObject } if (!$error) { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank_account"; - $sql .= " WHERE rowid = ".((int) $this->rowid); + $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::delete", LOG_DEBUG); $result = $this->db->query($sql); diff --git a/htdocs/user/bank.php b/htdocs/user/bank.php index fb795ecc6e4..1552ff94d82 100644 --- a/htdocs/user/bank.php +++ b/htdocs/user/bank.php @@ -25,7 +25,7 @@ /** * \file htdocs/user/bank.php * \ingroup HRM - * \brief Tab for HRM + * \brief Tab for HR and bank */ // Load Dolibarr environment @@ -79,7 +79,6 @@ if (empty($account->userid)) { $account->userid = $object->id; } - // Define value to know what current user can do on users $canadduser = (!empty($user->admin) || $user->rights->user->user->creer || $user->rights->hrm->write_personal_information->write); $canreaduser = (!empty($user->admin) || $user->rights->user->user->lire || $user->rights->hrm->read_personal_information->read); @@ -143,49 +142,6 @@ if ($action == 'add' && !$cancel && $permissiontoaddbankaccount) { if ($action == 'update' && !$cancel && $permissiontoaddbankaccount) { $account->userid = $object->id; - /* - if ($action == 'update' && !$cancel) - { - require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - - if ($canedituser) // Case we can edit all field - { - $error = 0; - - if (!$error) - { - $objectuser->fetch($id); - - $objectuser->oldcopy = dol_clone($objectuser); - - $db->begin(); - - $objectuser->default_range = GETPOST('default_range'); - $objectuser->default_c_exp_tax_cat = GETPOST('default_c_exp_tax_cat'); - - if (!$error) { - $ret = $objectuser->update($user); - if ($ret < 0) { - $error++; - if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { - $langs->load("errors"); - setEventMessages($langs->trans("ErrorLoginAlreadyExists", $objectuser->login), null, 'errors'); - } else { - setEventMessages($objectuser->error, $objectuser->errors, 'errors'); - } - } - } - - if (!$error && !count($objectuser->errors)) { - setEventMessages($langs->trans("UserModified"), null, 'mesgs'); - $db->commit(); - } else { - $db->rollback(); - } - } - } - }*/ - $account->bank = GETPOST('bank', 'alpha'); $account->label = GETPOST('label', 'alpha'); $account->courant = GETPOST('courant', 'alpha'); @@ -214,6 +170,18 @@ if ($action == 'update' && !$cancel && $permissiontoaddbankaccount) { } } +if ($action == 'delete_confirmed' && !$cancel && $permissiontoaddbankaccount) { + $result = $account->delete($user); + if ($result < 0) { + setEventMessages($account->error, $account->errors, 'errors'); + } else { + setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs'); + header("Location: ".DOL_URL_ROOT.'/user/bank.php?id='.$object->id); + exit; + } + $action = ''; +} + // update birth if ($action == 'setbirth' && $canadduser && !$cancel) { $object->birth = dol_mktime(0, 0, 0, GETPOST('birthmonth', 'int'), GETPOST('birthday', 'int'), GETPOST('birthyear', 'int')); @@ -819,32 +787,32 @@ if ($action != 'edit' && $action != 'create') { // If not bank account yet, $ac if ($account->id > 0) { print ''; // Label - print ''.$account->label.''; + print ''.dol_escape_htmltag($account->label).''; // Bank name - print ''.$account->bank.''; + print ''.dol_escape_htmltag($account->bank).''; // Account number print ''; - $string = ''; + $stringescaped = ''; foreach ($account->getFieldsToShow() as $val) { if ($val == 'BankCode') { - $string .= $account->code_banque.' '; + $stringescaped .= dol_escape_htmltag($account->code_banque).' '; } elseif ($val == 'BankAccountNumber') { - $string .= $account->number.' '; + $stringescaped .= dol_escape_htmltag($account->number).' '; } elseif ($val == 'DeskCode') { - $string .= $account->code_guichet.' '; + $stringescaped .= dol_escape_htmltag($account->code_guichet).' '; } elseif ($val == 'BankAccountNumberKey') { - $string .= $account->cle_rib.' '; + $stringescaped .= dol_escape_htmltag($account->cle_rib).' '; } } if (!empty($account->label) && $account->number) { if (!checkBanForAccount($account)) { - $string .= ' '.img_picto($langs->trans("ValueIsNotValid"), 'warning'); + $stringescaped .= ' '.img_picto($langs->trans("ValueIsNotValid"), 'warning'); } else { - $string .= ' '.img_picto($langs->trans("ValueIsValid"), 'info'); + $stringescaped .= ' '.img_picto($langs->trans("ValueIsValid"), 'info'); } } - print $string; + print $stringescaped; print ''; // IBAN print ''.getIbanHumanReadable($account); @@ -855,7 +823,8 @@ if ($action != 'edit' && $action != 'create') { // If not bank account yet, $ac } print ''; // BIC - print ''.$account->bic; + print ''; + print dol_escape_htmltag($account->bic); if (!empty($account->bic)) { if (!checkSwiftForAccount($account)) { print ' '.img_picto($langs->trans("SwiftNotValid"), 'warning'); @@ -869,9 +838,13 @@ if ($action != 'edit' && $action != 'create') { // If not bank account yet, $ac // Edit/Delete print ''; if ($permissiontoaddbankaccount) { - print ''; + print ''; print img_picto($langs->trans("Modify"), 'edit'); print ''; + + print ''; + print img_picto($langs->trans("Delete"), 'delete'); + print ''; } print ''; @@ -880,7 +853,7 @@ if ($action != 'edit' && $action != 'create') { // If not bank account yet, $ac if ($account->id == 0) { - $colspan = 6; + $colspan = 7; print ''.$langs->trans("NoBANRecord").''; } diff --git a/htdocs/user/class/userbankaccount.class.php b/htdocs/user/class/userbankaccount.class.php index 6e9cc8e52af..857f60d55e5 100644 --- a/htdocs/user/class/userbankaccount.class.php +++ b/htdocs/user/class/userbankaccount.class.php @@ -117,8 +117,6 @@ class UserBankAccount extends Account */ public function update(User $user = null, $notrigger = 0) { - global $conf; - if (!$this->id) { $this->create(); } @@ -193,7 +191,7 @@ class UserBankAccount extends Account $obj = $this->db->fetch_object($resql); $this->id = $obj->rowid; - $this->userid = $obj->fk_soc; + $this->userid = $obj->fk_user; $this->bank = $obj->bank; $this->code_banque = $obj->code_banque; $this->code_guichet = $obj->code_guichet; @@ -226,6 +224,63 @@ class UserBankAccount extends Account } } + /** + * Delete user bank account from database + * + * @param User $user User deleting + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user = null) + { + $error = 0; + + $this->db->begin(); + + // Delete link between tag and bank account + /* + if (!$error) { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_account"; + $sql .= " WHERE fk_account = ".((int) $this->id); + + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->error = "Error ".$this->db->lasterror(); + } + } + */ + + if (!$error) { + $sql = "DELETE FROM ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " WHERE rowid = ".((int) $this->id); + + dol_syslog(get_class($this)."::delete", LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) { + // Remove extrafields + /* + if (!$error) { + $result = $this->deleteExtraFields(); + if ($result < 0) { + $error++; + dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR); + } + }*/ + } else { + $error++; + $this->error = "Error ".$this->db->lasterror(); + } + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + /** * Return RIB * diff --git a/htdocs/user/notify/card.php b/htdocs/user/notify/card.php index e20d7be3d9a..f55a42ca159 100644 --- a/htdocs/user/notify/card.php +++ b/htdocs/user/notify/card.php @@ -332,7 +332,8 @@ if ($result > 0) { $userstatic->email = $obj->email; $userstatic->statut = $obj->status; - print ''.$userstatic->getNomUrl(1); + print ''; + print ''.$userstatic->getNomUrl(1); if ($obj->type == 'email') { if (isValidEmail($obj->email)) { print ' <'.$obj->email.'>'; @@ -359,8 +360,9 @@ if ($result > 0) { $i++; } $db->free($resql); + } else { + print ''.$langs->trans("None").''; } - // List of notifications enabled for fixed email /* foreach($conf->global as $key => $val) { From f9158c9a0201b23906458fd881f1bf2056f178f1 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 14 Jan 2023 14:47:58 +0100 Subject: [PATCH 553/816] Fix php 8 warnings --- htdocs/societe/paymentmodes.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 744d2763b71..de2c45381cb 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -6,7 +6,7 @@ * Copyright (C) 2013 Peter Fontaine * Copyright (C) 2015-2016 Marcos García * Copyright (C) 2017 Ferran Marcet - * Copyright (C) 2018-2021 Thibault FOUCART + * Copyright (C) 2018-2023 Thibault FOUCART * Copyright (C) 2021 Alexandre Spangaro * * This program is free software; you can redistribute it and/or modify @@ -1378,7 +1378,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' if (is_array($currencybalance)) { foreach ($currencybalance as $cpt) { - print ''.$langs->trans("Currency".strtoupper($cpt['currency'])).''.price($cpt['available'], 0, '', 1, - 1, - 1, strtoupper($cpt['currency'])).''.price($cpt->pending, 0, '', 1, - 1, - 1, strtoupper($cpt['currency'])).''.price($cpt['available'] + $cpt->pending, 0, '', 1, - 1, - 1, strtoupper($cpt['currency'])).''; + print ''.$langs->trans("Currency".strtoupper($cpt['currency'])).''.price($cpt['available'], 0, '', 1, - 1, - 1, strtoupper($cpt['currency'])).''.price(isset($cpt->pending)?$cpt->pending:0, 0, '', 1, - 1, - 1, strtoupper($cpt['currency'])).''.price($cpt['available'] + (isset($cpt->pending)?$cpt->pending:0), 0, '', 1, - 1, - 1, strtoupper($cpt['currency'])).''; } } From 3e273d40042a7fd9f3769a25da155566d9dbc238 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 15:11:15 +0100 Subject: [PATCH 554/816] Debug v17 --- htdocs/accountancy/expensereport/list.php | 1 - htdocs/accountancy/journal/bankjournal.php | 12 +- htdocs/compta/accounting-files.php | 5 + htdocs/compta/stats/byratecountry.php | 4 +- htdocs/compta/stats/casoc.php | 14 +- htdocs/compta/stats/index.php | 12 +- .../class/conferenceorbooth.class.php | 10 +- .../conferenceorbooth_list.php | 204 ++++++++++++------ htdocs/holiday/list.php | 23 +- htdocs/holiday/month_report.php | 75 ++++--- htdocs/hrm/class/establishment.class.php | 31 +-- .../knowledgerecord_list.php | 2 +- .../modulebuilder/template/myobject_list.php | 1 + .../recruitmentcandidature_agenda.php | 1 + .../recruitmentjobposition_agenda.php | 9 +- htdocs/user/agenda_extsites.php | 30 +++ htdocs/user/perms.php | 17 ++ 17 files changed, 311 insertions(+), 140 deletions(-) diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index 9cfbd940875..25b86a8d527 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -443,7 +443,6 @@ if ($result) { $expensereport_static->id = $objp->erid; $userstatic->id = $objp->userid; - $userstatic->ref = $objp->label; $userstatic->login = $objp->login; $userstatic->statut = $objp->statut; $userstatic->email = $objp->email; diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 699002395ab..c23392cada0 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -349,7 +349,11 @@ if ($result) { $societestatic->email = $tabcompany[$obj->rowid]['email']; $tabpay[$obj->rowid]["soclib"] = $societestatic->getNomUrl(1, '', 30); if ($compta_soc) { - $tabtp[$obj->rowid][$compta_soc] += $amounttouse; + if (empty($tabtp[$obj->rowid][$compta_soc])) { + $tabtp[$obj->rowid][$compta_soc] = $amounttouse; + } else { + $tabtp[$obj->rowid][$compta_soc] += $amounttouse; + } } } elseif ($links[$key]['type'] == 'user') { $userstatic->id = $links[$key]['url_id']; @@ -510,7 +514,11 @@ if ($result) { } } - $tabbq[$obj->rowid][$compta_bank] += $amounttouse; + if (empty($tabbq[$obj->rowid][$compta_bank])) { + $tabbq[$obj->rowid][$compta_bank] = $amounttouse; + } else { + $tabbq[$obj->rowid][$compta_bank] += $amounttouse; + } // If no links were found to know the amount on thirdparty, we try to guess it. // This may happens on bank entries without the links lines to 'company'. diff --git a/htdocs/compta/accounting-files.php b/htdocs/compta/accounting-files.php index 2f2f5816ae1..af8d626eba1 100644 --- a/htdocs/compta/accounting-files.php +++ b/htdocs/compta/accounting-files.php @@ -376,6 +376,9 @@ if (($action == 'searchfiles' || $action == 'dl')) { $nofile['country_code'] = $objd->country_code; $nofile['vatnum'] = $objd->vatnum; $nofile['sens'] = $objd->sens; + $nofile['currency'] = $objd->currency; + $nofile['link'] = ''; + $nofile['name'] = ''; $filesarray[$nofile['item'].'_'.$nofile['id']] = $nofile; } else { @@ -396,6 +399,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { $file['country_code'] = $objd->country_code; $file['vatnum'] = $objd->vatnum; $file['sens'] = $objd->sens; + $file['currency'] = $objd->currency; // Save record into array (only the first time it is found) if (empty($filesarray[$file['item'].'_'.$file['id']])) { @@ -415,6 +419,7 @@ if (($action == 'searchfiles' || $action == 'dl')) { 'relpathnamelang' => $langs->trans($file['item']).'/'.$file['name'], 'modulepart' => $modulepart, 'subdir' => $subdir, + 'currency' => $file['currency'] ); //var_dump($file['item'].'_'.$file['id']); //var_dump($filesarray[$file['item'].'_'.$file['id']]['files']); diff --git a/htdocs/compta/stats/byratecountry.php b/htdocs/compta/stats/byratecountry.php index fb8ad4de1a5..b9dd6c7429d 100644 --- a/htdocs/compta/stats/byratecountry.php +++ b/htdocs/compta/stats/byratecountry.php @@ -461,9 +461,9 @@ if ($modecompta == 'CREANCES-DETTES') { $j -= 12; } $monthj = 'month'.str_pad($j, 2, '0', STR_PAD_LEFT); - print ''.price($totalpermonth[$j]).''; + print ''.price(empty($totalpermonth[$j]) ? 0 : $totalpermonth[$j]).''; } - print ''.price($totalpermonth['total']).''; + print ''.price(empty($totalpermonth['total']) ? 0 : $totalpermonth['total']).''; print ''; } else { print $db->lasterror(); // Show last sql error diff --git a/htdocs/compta/stats/casoc.php b/htdocs/compta/stats/casoc.php index d24e5a5452a..b499ca17c71 100644 --- a/htdocs/compta/stats/casoc.php +++ b/htdocs/compta/stats/casoc.php @@ -406,12 +406,16 @@ if ($modecompta == "RECETTES-DEPENSES") { while ($i < $num) { $obj = $db->fetch_object($result); - $amount[$obj->rowid] += $obj->amount_ttc; + if (empty($amount[$obj->socid])) { + $amount[$obj->socid] = $obj->amount_ttc; + } else { + $amount[$obj->socid] += $obj->amount_ttc; + } - $name[$obj->rowid] = $obj->name; - $address_zip[$obj->rowid] = $obj->zip; - $address_town[$obj->rowid] = $obj->town; - $address_pays[$obj->rowid] = getCountry($obj->fk_pays); + $name[$obj->socid] = $obj->name; + $address_zip[$obj->socid] = ''; + $address_town[$obj->socid] = ''; + $address_pays[$obj->socid] = 0; $catotal += $obj->amount_ttc; diff --git a/htdocs/compta/stats/index.php b/htdocs/compta/stats/index.php index 058fba33177..7d70bc10527 100644 --- a/htdocs/compta/stats/index.php +++ b/htdocs/compta/stats/index.php @@ -577,7 +577,7 @@ for ($annee = $year_start; $annee <= $year_end; $annee++) { // Montant total HT if ($total_ht[$annee] || ($annee >= $minyear && $annee <= max($nowyear, $maxyear))) { print ''; - print ($total_ht[$annee] ?price($total_ht[$annee]) : "0"); + print (empty($total_ht[$annee]) ? '0' : price($total_ht[$annee])); print ""; } else { print ' '; @@ -587,7 +587,7 @@ for ($annee = $year_start; $annee <= $year_end; $annee++) { // Total amount if (!empty($total[$annee]) || ($annee >= $minyear && $annee <= max($nowyear, $maxyear))) { print ''; - print ($total[$annee] ?price($total[$annee]) : "0"); + print (empty($total[$annee]) ? '0' : price($total[$annee])); print ""; } else { print ' '; @@ -595,19 +595,19 @@ for ($annee = $year_start; $annee <= $year_end; $annee++) { // Pourcentage total if ($annee > $minyear && $annee <= max($nowyear, $maxyear)) { - if ($total[$annee - 1] && $total[$annee]) { + if (!empty($total[$annee - 1]) && !empty($total[$annee])) { $percent = (round(($total[$annee] - $total[$annee - 1]) / $total[$annee - 1], 4) * 100); print ''; print ($percent >= 0 ? "+$percent" : "$percent").'%'; print ''; } - if ($total[$annee - 1] && !$total[$annee]) { + if (!empty($total[$annee - 1]) && empty($total[$annee])) { print '-100%'; } - if (!$total[$annee - 1] && $total[$annee]) { + if (empty($total[$annee - 1]) && !empty($total[$annee])) { print '+'.$langs->trans('Inf').'%'; } - if (!$total[$annee - 1] && !$total[$annee]) { + if (empty($total[$annee - 1]) && empty($total[$annee])) { print '+0%'; } } else { diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index 556443a25e8..db0928efc7d 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -104,12 +104,12 @@ class ConferenceOrBooth extends ActionComm */ public $fields = array( 'id' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), - 'ref' => array('type'=>'integer', 'label'=>'Ref', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>2, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), - 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax125', 'help'=>"OrganizationEvenLabelName", 'showoncombobox'=>'1',), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500'), - 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:t.usage_organize_event=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'picto'=>'project', 'css'=>'tdoverflowmax150 maxwidth500'), + 'ref' => array('type'=>'integer', 'label'=>'Ref', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>2, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'csslist'=>'left', 'comment'=>"Id"), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax125', 'help'=>"OrganizationEvenLabelName", 'showoncombobox'=>'1', 'autofocusoncreate'=>1), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500', 'csslist'=>'width100'), + 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:t.usage_organize_event=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'picto'=>'project', 'css'=>'tdoverflowmax150 maxwidth500', 'csslist'=>'width100'), 'note' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>1), - 'fk_action' => array('type'=>'sellist:c_actioncomm:libelle:id::module LIKE (\'%@eventorganization\')', 'label'=>'Format', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>1, 'css'=>'width300'), + 'fk_action' => array('type'=>'sellist:c_actioncomm:libelle:id::module LIKE (\'%@eventorganization\')', 'label'=>'Format', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>1, 'css'=>'width100'), 'datep' => array('type'=>'datetime', 'label'=>'DateStart', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>1, 'showoncombobox'=>'2',), 'datep2' => array('type'=>'datetime', 'label'=>'DateEnd', 'enabled'=>'1', 'position'=>71, 'notnull'=>0, 'visible'=>1, 'showoncombobox'=>'3',), 'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), diff --git a/htdocs/eventorganization/conferenceorbooth_list.php b/htdocs/eventorganization/conferenceorbooth_list.php index dd7bfd93a47..1dd77122384 100644 --- a/htdocs/eventorganization/conferenceorbooth_list.php +++ b/htdocs/eventorganization/conferenceorbooth_list.php @@ -25,17 +25,14 @@ // Load Dolibarr environment require '../main.inc.php'; - require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php'; - require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorbooth.class.php'; require_once DOL_DOCUMENT_ROOT.'/eventorganization/class/conferenceorboothattendee.class.php'; require_once DOL_DOCUMENT_ROOT.'/eventorganization/lib/eventorganization_conferenceorbooth.lib.php'; - require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; global $dolibarr_main_url_root; @@ -56,6 +53,7 @@ $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'conferenceorboothlist'; // 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', ...) $id = GETPOST('id', 'int'); $projectid = GETPOST('projectid', 'int'); @@ -67,8 +65,9 @@ $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); 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 or if we click on clear filters +} $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; @@ -120,11 +119,11 @@ $arrayfields = array(); foreach ($object->fields as $key => $val) { // If $val['visible']==0, then we never show the field if (!empty($val['visible'])) { - $visible = (int) dol_eval($val['visible'], 1, 1, '1'); + $visible = (int) dol_eval($val['visible'], 1); $arrayfields['t.'.$key] = array( 'label'=>$val['label'], 'checked'=>(($visible < 0) ? 0 : 1), - 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1, 1, '1')), + 'enabled'=>(abs($visible) != 3 && dol_eval($val['enabled'], 1)), 'position'=>$val['position'], 'help'=> isset($val['help']) ? $val['help'] : '' ); @@ -235,9 +234,11 @@ if (empty($reshook)) { $form = new Form($db); $now = dol_now(); -$title = $langs->trans('ListOfConferencesOrBooths'); //$help_url="EN:Module_ConferenceOrBooth|FR:Module_ConferenceOrBooth_FR|ES:Módulo_ConferenceOrBooth"; $help_url = ''; +$title = $langs->trans('ListOfConferencesOrBooths'); +$morejs = array(); +$morecss = array(); if ($projectid > 0 || $projectref) { $project = new Project($db); @@ -524,9 +525,13 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook $sql .= preg_replace('/^,/', '', $hookmanager->resPrint); $sql = preg_replace('/,\s*$/', '', $sql); +//$sql .= ", COUNT(rc.rowid) as anotherfield"; + +$sqlfields = $sql; // $sql fields to remove for count total + $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; -if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.id = ef.fk_object)"; +if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; } $sql .= " INNER JOIN ".MAIN_DB_PREFIX."c_actioncomm as cact ON cact.id=t.fk_action AND cact.module LIKE '%@eventorganization'"; // Add table from hooks @@ -554,17 +559,17 @@ foreach ($search as $key => $val) { $mode_search = 2; } if ($search[$key] != '') { - $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); + $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search)); } } else { if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') { $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key); if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) { if (preg_match('/_dtstart$/', $key)) { - $sql .= " AND t.".$columnName." >= '".$db->idate($search[$key])."'"; + $sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'"; } if (preg_match('/_dtend$/', $key)) { - $sql .= " AND t." . $columnName . " <= '" . $db->idate($search[$key]) . "'"; + $sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'"; } } } @@ -582,35 +587,42 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; -$sql .= $db->order($sortfield, $sortorder); - // Count total nb of records $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { - $resql = $db->query($sql); - $nbtotalofrecords = $db->num_rows($resql); - if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql); + $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount); + $resql = $db->query($sqlforcount); + if ($resql) { + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + } else { + dol_print_error($db); + } + + if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 $page = 0; $offset = 0; } + $db->free($resql); } -// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set. -if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit))) { - $num = $nbtotalofrecords; -} else { - if ($limit) { - $sql .= $db->plimit($limit + 1, $offset); - } - $resql = $db->query($sql); - if (!$resql) { - dol_print_error($db); - exit; - } +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); - $num = $db->num_rows($resql); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); } +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + // 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); @@ -622,6 +634,9 @@ if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $ $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); } @@ -629,11 +644,17 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } foreach ($search as $key => $val) { - if (is_array($search[$key]) && count($search[$key])) { + if (is_array($search[$key])) { foreach ($search[$key] as $skey) { - $param .= '&search_'.$key.'[]='.urlencode($skey); + if ($skey != '') { + $param .= '&search_'.$key.'[]='.urlencode($skey); + } } - } else { + } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) { + $param .= '&search_'.$key.'month='.((int) GETPOST('search_'.$key.'month', 'int')); + $param .= '&search_'.$key.'day='.((int) GETPOST('search_'.$key.'day', 'int')); + $param .= '&search_'.$key.'year='.((int) GETPOST('search_'.$key.'year', 'int')); + } elseif ($search[$key] != '') { $param .= '&search_'.$key.'='.urlencode($search[$key]); } } @@ -655,7 +676,7 @@ $arrayofmassactions = array( 'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail").' ('.$langs->trans("ToSpeakers").')', //'presend_attendees'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail").' - '.$langs->trans("Attendees"), ); -if ($permissiontodelete) { +if (!empty($permissiontodelete)) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { @@ -672,8 +693,11 @@ print ''; print ''; print ''; +print ''; print ''; print ''; +print ''; + $title = $langs->trans("EventOrganizationConfOrBoothes"); @@ -683,7 +707,7 @@ print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sort // Add code for pre mass action (confirmation or email presend form) -$topicmail = $projectstatic->title; +$topicmail = ''; $modelmail = "conferenceorbooth"; $objecttmp = new ConferenceOrBooth($db); $trackid = 'conferenceorbooth_'.$object->id; @@ -692,10 +716,13 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; if ($search_all) { + $setupstring = ''; foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); + $setupstring .= $key."=".$val.";"; } - print '
'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
'; + print ''."\n"; + print '
'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
'."\n"; } $moreforfilter = ''; @@ -718,7 +745,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); @@ -729,9 +756,15 @@ print ''; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} foreach ($object->fields as $key => $val) { - $searchkey = (empty($search[$key]) ? '' : $search[$key]); - + $searchkey = empty($search[$key]) ? '' : $search[$key]; $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if ($key == 'status') { $cssforfield .= ($cssforfield ? ' ' : '').'center'; @@ -739,17 +772,15 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } if (!empty($arrayfields['t.'.$key]['checked'])) { print ''; } @@ -769,16 +806,23 @@ $parameters = array('arrayfields'=>$arrayfields); $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -print ''; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print ''."\n"; +$totalarray = array(); +$totalarray['nbfield'] = 0; // Fields title label // -------------------------------------------------------------------- print ''; +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +} foreach ($object->fields as $key => $val) { $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if ($key == 'status') { @@ -787,27 +831,32 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'ref')) && $val['label'] != 'TechnicalID') { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $key != 'ref' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } + $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label if (!empty($arrayfields['t.'.$key]['checked'])) { print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + $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); +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +} +$totalarray['nbfield']++; print ''."\n"; // Detect if we need a fetch on each output line $needToFetchEachLine = 0; -if (!empty($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { +if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) { if (preg_match('/\$object/', $val)) { $needToFetchEachLine++; // There is at least one compute field that use $object @@ -819,8 +868,11 @@ if (!empty($extrafields->attributes[$object->table_element]['computed']) && is_a // Loop on record // -------------------------------------------------------------------- $i = 0; +$savnbfield = $totalarray['nbfield']; $totalarray = array(); -while ($i < ($limit ? min($num, $limit) : $num)) { +$totalarray['nbfield'] = 0; +$imaxinloop = ($limit ? min($num, $limit) : $num); +while ($i < $imaxinloop) { $obj = $db->fetch_object($resql); if (empty($obj)) { break; // Should not happen @@ -830,10 +882,22 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $object->setVarsFromFetchObj($obj); // Show here line of result - print ''; - $totalarray['nbfield'] = 0; + $j = 0; + print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } foreach ($object->fields as $key => $val) { - $cssforfield = (empty($val['css']) ? '' : $val['css']); + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif ($key == 'status') { @@ -843,7 +907,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { if (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; } elseif ($key == 'ref') { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap left'; + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; } if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'ref', 'status'))) { @@ -852,7 +916,11 @@ while ($i < ($limit ? min($num, $limit) : $num)) { //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; if (!empty($arrayfields['t.'.$key]['checked'])) { - print ''; + print ''; if ($key == 'status') { print $object->getLibStatut(5); } elseif ($key == 'ref') { @@ -885,15 +953,17 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column - print ''; } - print ''; if (!$i) { $totalarray['nbfield']++; } @@ -921,7 +991,7 @@ if ($num == 0) { $db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); -$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { - print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $searchkey, $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); - } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:')=== 0)) { - print $object->showInputField($val, $key, $searchkey, '', '', 'search_', 'maxwidth125', 1); - } elseif (!preg_match('/^(date|timestamp|datetime)/', $val['type'])) { - print ''; + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status onrightofpage' : ''), 1); + } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { + print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1); } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { print '
'; print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); @@ -757,6 +788,12 @@ foreach ($object->fields as $key => $val) { print '
'; print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); print '
'; + } elseif ($key == 'lang') { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($db); + print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth150 maxwidth200', 2); + } else { + print ''; } print '
'; -$searchpicto = $form->showFilterButtons(); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + 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($object->id, $arrayofselected)) { + $selected = 1; + } + 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($object->id, $arrayofselected)) { - $selected = 1; + if (empty($conf->global->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($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print '
'."\n"; diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index 564fb8a2a96..dedfed07157 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -827,6 +827,9 @@ if ($resql) { print ''; } print ''; + if (!$i) { + $totalarray['nbfield']++; + } } if (!empty($arrayfields['cp.ref']['checked'])) { print ''; @@ -849,8 +852,11 @@ if ($resql) { } } if (!empty($arrayfields['cp.fk_type']['checked'])) { - $labeltypeleavetoshow = ($langs->trans($typeleaves[$obj->fk_type]['code']) != $typeleaves[$obj->fk_type]['code'] ? $langs->trans($typeleaves[$obj->fk_type]['code']) : $typeleaves[$obj->fk_type]['label']); - $labeltypeleavetoshow = empty($typeleaves[$obj->fk_type]['label']) ? $langs->trans("TypeWasDisabledOrRemoved", $obj->fk_type) : $labeltypeleavetoshow; + if (empty($typeleaves[$obj->fk_type])) { + $labeltypeleavetoshow = $langs->trans("TypeWasDisabledOrRemoved", $obj->fk_type); + } else { + $labeltypeleavetoshow = ($langs->trans($typeleaves[$obj->fk_type]['code']) != $typeleaves[$obj->fk_type]['code'] ? $langs->trans($typeleaves[$obj->fk_type]['code']) : $typeleaves[$obj->fk_type]['label']); + } print ''; print $labeltypeleavetoshow; @@ -941,9 +947,9 @@ if ($resql) { print ''; } print ''; - } - if (!$i) { - $totalarray['nbfield']++; + if (!$i) { + $totalarray['nbfield']++; + } } print ''."\n"; @@ -954,6 +960,9 @@ if ($resql) { // Add a line for total if there is a total to show if (!empty($arrayfields['duration']['checked'])) { print ''; + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } foreach ($arrayfields as $key => $val) { if (!empty($val['checked'])) { if ($key == 'duration') { @@ -964,7 +973,9 @@ if ($resql) { } } // status - print ''; + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } print ''; } } diff --git a/htdocs/holiday/month_report.php b/htdocs/holiday/month_report.php index a1a23715126..fe2d33ff78a 100644 --- a/htdocs/holiday/month_report.php +++ b/htdocs/holiday/month_report.php @@ -227,27 +227,34 @@ print '
'; $moreforfilter = ''; $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = ''; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); print '
'; -print ''; +print '
'; -print ''; +print ''; + +// Action column +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; +} // Filter: Ref if (!empty($arrayfields['cp.ref']['checked'])) { - print ''; } // Filter: Employee if (!empty($arrayfields['cp.fk_user']['checked'])) { - print ''; } // Filter: Type @@ -259,45 +266,50 @@ if (!empty($arrayfields['cp.fk_type']['checked'])) { $arraytypeleaves[$val['rowid']] = $labeltoshow; } - print ''; } if (!empty($arrayfields['cp.date_debut']['checked'])) { - print ''; + print ''; } if (!empty($arrayfields['cp.date_fin']['checked'])) { - print ''; + print ''; } if (!empty($arrayfields['used_days']['checked'])) { - print ''; + print ''; } if (!empty($arrayfields['date_start_month']['checked'])) { - print ''; + print ''; } if (!empty($arrayfields['date_end_month']['checked'])) { - print ''; + print ''; } if (!empty($arrayfields['used_days_month']['checked'])) { - print ''; + print ''; } // Filter: Description if (!empty($arrayfields['cp.description']['checked'])) { - print ''; } - // Action column -print ''; +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; +} print ''; print ''; +// Action column +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +} if (!empty($arrayfields['cp.ref']['checked'])) { print_liste_field_titre($arrayfields['cp.ref']['label'], $_SERVER["PHP_SELF"], 'cp.ref', '', '', '', $sortfield, $sortorder); } @@ -331,11 +343,14 @@ if (!empty($arrayfields['used_days_month']['checked'])) { if (!empty($arrayfields['cp.description']['checked'])) { print_liste_field_titre($arrayfields['cp.description']['label'], $_SERVER["PHP_SELF"], 'cp.description', '', '', '', $sortfield, $sortorder); } -print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +// Action column +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +} print ''; if ($num == 0) { - print ''; + print ''; } else { while ($obj = $db->fetch_object($resql)) { $user = new User($db); @@ -385,6 +400,10 @@ if ($num == 0) { $holidaystatic->ref = $obj->ref; print ''; + // Action column + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } if (!empty($arrayfields['cp.ref']['checked'])) { print ''; @@ -430,8 +449,10 @@ if ($num == 0) { if (!empty($arrayfields['cp.description']['checked'])) { print ''; } - - print ''; + // Action column + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + print ''; + } print ''; } } diff --git a/htdocs/hrm/class/establishment.class.php b/htdocs/hrm/class/establishment.class.php index 6a37ba1e929..05bd8d47cf8 100644 --- a/htdocs/hrm/class/establishment.class.php +++ b/htdocs/hrm/class/establishment.class.php @@ -285,7 +285,7 @@ class Establishment extends CommonObject * Load an object from database * * @param int $id Id of record to load - * @return int <0 if KO, >0 if OK + * @return int <0 if KO, >=0 if OK */ public function fetch($id) { @@ -299,21 +299,24 @@ class Establishment extends CommonObject $result = $this->db->query($sql); if ($result) { $obj = $this->db->fetch_object($result); + if ($obj) { + $this->id = $obj->rowid; + $this->ref = $obj->ref; + $this->label = $obj->label; + $this->address = $obj->address; + $this->zip = $obj->zip; + $this->town = $obj->town; + $this->status = $obj->status; + $this->entity = $obj->entity; - $this->id = $obj->rowid; - $this->ref = $obj->ref; - $this->label = $obj->label; - $this->address = $obj->address; - $this->zip = $obj->zip; - $this->town = $obj->town; - $this->status = $obj->status; - $this->entity = $obj->entity; + $this->country_id = $obj->country_id; + $this->country_code = $obj->country_code; + $this->country = $obj->country; - $this->country_id = $obj->country_id; - $this->country_code = $obj->country_code; - $this->country = $obj->country; - - return 1; + return 1; + } else { + return 0; + } } else { $this->error = $this->db->lasterror(); return -1; diff --git a/htdocs/knowledgemanagement/knowledgerecord_list.php b/htdocs/knowledgemanagement/knowledgerecord_list.php index dffd3d63d7b..cafb5776cf7 100644 --- a/htdocs/knowledgemanagement/knowledgerecord_list.php +++ b/htdocs/knowledgemanagement/knowledgerecord_list.php @@ -501,7 +501,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $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 diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 1135f6d9498..95442195ff9 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -492,6 +492,7 @@ print ''; print ''; print ''; print ''; +print ''; print ''; diff --git a/htdocs/recruitment/recruitmentcandidature_agenda.php b/htdocs/recruitment/recruitmentcandidature_agenda.php index 04118f55572..3648b8ca13b 100644 --- a/htdocs/recruitment/recruitmentcandidature_agenda.php +++ b/htdocs/recruitment/recruitmentcandidature_agenda.php @@ -41,6 +41,7 @@ $action = GETPOST('action', 'aZ09'); $cancel = GETPOST('cancel', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); $socid = GETPOST('socid', 'int'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search if (GETPOST('actioncode', 'array')) { $actioncode = GETPOST('actioncode', 'array', 3); diff --git a/htdocs/recruitment/recruitmentjobposition_agenda.php b/htdocs/recruitment/recruitmentjobposition_agenda.php index f2f4d37484b..fab164dcd2f 100644 --- a/htdocs/recruitment/recruitmentjobposition_agenda.php +++ b/htdocs/recruitment/recruitmentjobposition_agenda.php @@ -40,6 +40,7 @@ $ref = GETPOST('ref', 'alpha'); $action = GETPOST('action', 'aZ09'); $cancel = GETPOST('cancel', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search if (GETPOST('actioncode', 'array')) { $actioncode = GETPOST('actioncode', 'array', 3); @@ -79,7 +80,7 @@ $extrafields->fetch_name_optionals_label($object->table_element); // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals if ($id > 0 || !empty($ref)) { - $upload_dir = $conf->recruitment->multidir_output[$object->entity]."/".$object->id; + $upload_dir = $conf->recruitment->multidir_output[!empty($object->entity) ? $object->entity : $conf->entity]."/".$object->id; } $permissiontoadd = $user->rights->recruitment->recruitmentjobposition->write; // Used by the include of actions_addupdatedelete.inc.php @@ -163,11 +164,11 @@ if ($object->id > 0) { $morehtmlref .= ''; $morehtmlref .= ''; $morehtmlref .= ''; - $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1); $morehtmlref .= ''; $morehtmlref .= ''; } else { - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, 0, $object->fk_project, 'none', 0, 0, 0, 1); } } else { if (!empty($object->fk_project)) { @@ -228,7 +229,7 @@ if ($object->id > 0) { print '
'; if (isModEnabled('agenda') && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { - $param = '&id='.$object->id.'&socid='.$socid; + $param = '&id='.$object->id; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.urlencode($contextpage); } diff --git a/htdocs/user/agenda_extsites.php b/htdocs/user/agenda_extsites.php index 4891480cc2d..c2b58c4e2a0 100644 --- a/htdocs/user/agenda_extsites.php +++ b/htdocs/user/agenda_extsites.php @@ -176,8 +176,38 @@ $morehtmlref .= ''; dol_banner_tab($object, 'id', $linkback, $user->rights->user->user->lire || $user->admin, 'rowid', 'ref', $morehtmlref); +print '
'; print '
'; +print '
'; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; + print ''; print ''; - print ''; + print ''; + print ''; print $form->select_dolusers($search_employee, "search_employee", 1, null, 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth100'); - print ''; + print ''; + print ''; print $form->selectarray('search_type', $arraytypeleaves, $search_type, 1, 0, 0, '', 0, 0, 0, '', '', 1); - print ''; + print ''; + print ''; print ''; - print ''; + print ''; -$searchpicto = $form->showFilterButtons(); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
'.$langs->trans('None').'
'.$langs->trans('None').'
'.$holidaystatic->getNomUrl(1, 1).''.dolGetFirstLineOfText(dol_string_nohtmltag($obj->description, 1)).'
'; + +// Login +print ''; +if (!empty($object->ldap_sid) && $object->statut == 0) { + print ''; +} else { + print ''; +} +print ''."\n"; + +print '
'.$langs->trans("Login").''; + print $langs->trans("LoginAccountDisableInDolibarr"); + print ''; + $addadmin = ''; + if (property_exists($object, 'admin')) { + if (isModEnabled('multicompany') && !empty($object->admin) && empty($object->entity)) { + $addadmin .= img_picto($langs->trans("SuperAdministratorDesc"), "redstar", 'class="paddingleft"'); + } elseif (!empty($object->admin)) { + $addadmin .= img_picto($langs->trans("AdministratorDesc"), "star", 'class="paddingleft"'); + } + } + print showValueWithClipboardCPButton($object->login).$addadmin; + print '
'; + +print '
'; + +print dol_get_fiche_end(); + print '
'; print ''.$langs->trans("AgendaExtSitesDesc")."
\n"; diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index a65762b6183..1cd094d882d 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -288,6 +288,23 @@ if (!empty($object->ldap_sid) && $object->statut == 0) { } print ''."\n"; +// Type +print ''; +$text = $langs->trans("Type"); +print $form->textwithpicto($text, $langs->trans("InternalExternalDesc")); +print ''; +$type = $langs->trans("Internal"); +if ($object->socid > 0) { + $type = $langs->trans("External"); +} +print ''; +print $type; +if ($object->ldap_sid) { + print ' ('.$langs->trans("DomainUser").')'; +} +print ''; +print ''."\n"; + print ''; print '
'; From fbc74cd571aa4deebbf8cac9f9d4c695452981da Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 15:57:12 +0100 Subject: [PATCH 555/816] Fix missing doxygen doc --- .../DataCollector/DolConfigCollector.php | 21 +++++++++++++++ .../DataCollector/DolExceptionsCollector.php | 21 +++++++++++++++ .../class/DataCollector/DolLogsCollector.php | 21 +++++++++++++++ .../DataCollector/DolMemoryCollector.php | 26 ++++++++++++++++--- .../DataCollector/DolMessagesCollector.php | 21 +++++++++++++++ .../class/DataCollector/DolPhpCollector.php | 21 +++++++++++++++ .../class/DataCollector/DolQueryCollector.php | 21 +++++++++++++++ .../DataCollector/DolRequestDataCollector.php | 21 +++++++++++++++ .../DataCollector/DolTimeDataCollector.php | 21 +++++++++++++++ .../class/DataCollector/DolibarrCollector.php | 21 +++++++++++++++ htdocs/debugbar/class/DebugBar.php | 21 +++++++++++++++ htdocs/debugbar/class/TraceableDB.php | 21 +++++++++++++++ 12 files changed, 254 insertions(+), 3 deletions(-) diff --git a/htdocs/debugbar/class/DataCollector/DolConfigCollector.php b/htdocs/debugbar/class/DataCollector/DolConfigCollector.php index 715d20abcf9..0920b140dbc 100644 --- a/htdocs/debugbar/class/DataCollector/DolConfigCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolConfigCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolConfigCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use \DebugBar\DataCollector\ConfigCollector; diff --git a/htdocs/debugbar/class/DataCollector/DolExceptionsCollector.php b/htdocs/debugbar/class/DataCollector/DolExceptionsCollector.php index 15d433fd050..38d2b971dde 100644 --- a/htdocs/debugbar/class/DataCollector/DolExceptionsCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolExceptionsCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolexceptionsCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use \DebugBar\DataCollector\ExceptionsCollector; diff --git a/htdocs/debugbar/class/DataCollector/DolLogsCollector.php b/htdocs/debugbar/class/DataCollector/DolLogsCollector.php index d21cdd6233f..44885296bae 100644 --- a/htdocs/debugbar/class/DataCollector/DolLogsCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolLogsCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolLogsCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use DebugBar\DataCollector\MessagesCollector; use Psr\Log\LogLevel; diff --git a/htdocs/debugbar/class/DataCollector/DolMemoryCollector.php b/htdocs/debugbar/class/DataCollector/DolMemoryCollector.php index b52ac8ff8c4..3372e89c2b6 100644 --- a/htdocs/debugbar/class/DataCollector/DolMemoryCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolMemoryCollector.php @@ -1,17 +1,37 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolMemoryCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use \DebugBar\DataCollector\MemoryCollector; /** * DolMemoryCollector class */ - class DolMemoryCollector extends MemoryCollector { /** * Return value of indicator * - * @return void + * @return array */ public function collect() { @@ -28,7 +48,7 @@ class DolMemoryCollector extends MemoryCollector /** * Return widget settings * - * @return void + * @return array */ public function getWidgets() { diff --git a/htdocs/debugbar/class/DataCollector/DolMessagesCollector.php b/htdocs/debugbar/class/DataCollector/DolMessagesCollector.php index 1fcf60c8ba6..733009e77c6 100644 --- a/htdocs/debugbar/class/DataCollector/DolMessagesCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolMessagesCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolMessagesCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use \DebugBar\DataCollector\MessagesCollector; diff --git a/htdocs/debugbar/class/DataCollector/DolPhpCollector.php b/htdocs/debugbar/class/DataCollector/DolPhpCollector.php index 3d6536bd258..bca2b2a7071 100644 --- a/htdocs/debugbar/class/DataCollector/DolPhpCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolPhpCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolPhpCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use DebugBar\DataCollector\DataCollector; use DebugBar\DataCollector\Renderable; diff --git a/htdocs/debugbar/class/DataCollector/DolQueryCollector.php b/htdocs/debugbar/class/DataCollector/DolQueryCollector.php index ca5aa284dd2..8cc55e34df9 100644 --- a/htdocs/debugbar/class/DataCollector/DolQueryCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolQueryCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolQueryCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use DebugBar\DataCollector\AssetProvider; use DebugBar\DataCollector\DataCollector; diff --git a/htdocs/debugbar/class/DataCollector/DolRequestDataCollector.php b/htdocs/debugbar/class/DataCollector/DolRequestDataCollector.php index 938643802d5..4ddcac9af7c 100644 --- a/htdocs/debugbar/class/DataCollector/DolRequestDataCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolRequestDataCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolRequestDataCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use \DebugBar\DataCollector\RequestDataCollector; diff --git a/htdocs/debugbar/class/DataCollector/DolTimeDataCollector.php b/htdocs/debugbar/class/DataCollector/DolTimeDataCollector.php index ed5e979d539..d16622d329f 100644 --- a/htdocs/debugbar/class/DataCollector/DolTimeDataCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolTimeDataCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolTimeDataCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use \DebugBar\DataCollector\TimeDataCollector; diff --git a/htdocs/debugbar/class/DataCollector/DolibarrCollector.php b/htdocs/debugbar/class/DataCollector/DolibarrCollector.php index 3193fe26176..11cedbe2b93 100644 --- a/htdocs/debugbar/class/DataCollector/DolibarrCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolibarrCollector.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/DolibarrCollector.php + * \brief Class for debugbar collection + * \ingroup debugbar + */ use DebugBar\DataCollector\AssetProvider; use DebugBar\DataCollector\DataCollector; diff --git a/htdocs/debugbar/class/DebugBar.php b/htdocs/debugbar/class/DebugBar.php index bf797e638f7..6181ad7cd60 100644 --- a/htdocs/debugbar/class/DebugBar.php +++ b/htdocs/debugbar/class/DebugBar.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DebugBar.php + * \brief Class for debugbar + * \ingroup debugbar + */ dol_include_once('/debugbar/class/autoloader.php'); diff --git a/htdocs/debugbar/class/TraceableDB.php b/htdocs/debugbar/class/TraceableDB.php index 9f0a83fae3c..8e28b0c59bd 100644 --- a/htdocs/debugbar/class/TraceableDB.php +++ b/htdocs/debugbar/class/TraceableDB.php @@ -1,4 +1,25 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/debugbar/class/DataCollector/TraceableDB.php + * \brief Class for debugbar DB + * \ingroup debugbar + */ require_once DOL_DOCUMENT_ROOT.'/core/db/DoliDB.class.php'; From 7aba21dd3e194ef49ed7dfee466856b345717085 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Sat, 14 Jan 2023 17:05:45 +0100 Subject: [PATCH 556/816] Update list.php --- htdocs/adherents/list.php | 67 +++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index b9cbb252144..39a4d993221 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -73,7 +73,7 @@ $search_categ = GETPOST("search_categ", 'int'); $search_filter = GETPOST("search_filter", 'alpha'); $search_status = GETPOST("search_status", 'intcomma'); $search_morphy = GETPOST("search_morphy", 'alpha'); -$search_import_key = trim(GETPOST("search_import_key", "alpha")); +$search_import_key = trim(GETPOST("search_import_key", 'alpha')); $catid = GETPOST("catid", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); $socid = GETPOST('socid', 'int'); @@ -141,6 +141,7 @@ $fieldstosearchall = array( if ($db->type == 'pgsql') { unset($fieldstosearchall['d.rowid']); } + $arrayfields = array( 'd.ref'=>array('label'=>"Ref", 'checked'=>1), 'd.civility'=>array('label'=>"Civility", 'checked'=>0), @@ -169,6 +170,7 @@ $arrayfields = array( 'd.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000), 'd.import_key'=>array('label'=>"ImportId", 'checked'=>0, 'position'=>1100), ); + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; @@ -317,7 +319,11 @@ $formother = new FormOther($db); $membertypestatic = new AdherentType($db); $memberstatic = new Adherent($db); -$title = $langs->trans("Members"); +// Page Header +$title = $langs->trans("Members")." - ".$langs->trans("List");; +$help_url = 'EN:Module_Foundations|FR:Module_Adhérents|ES:Módulo_Miembros|DE:Modul_Mitglieder'; +llxHeader('', $title, $help_url); + $now = dol_now(); @@ -335,12 +341,14 @@ $sql .= " s.nom,"; $sql .= " ".$db->ifsql("d.societe IS NULL", "s.nom", "d.societe")." as companyname,"; $sql .= " t.libelle as type, t.subscription,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; + // 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); // Note that $action and $object may have been modified by hook @@ -349,13 +357,16 @@ $sql = preg_replace('/,\s*$/', '', $sql); $sqlfields = $sql; // $sql fields to remove for count total -$sql .= " FROM ".MAIN_DB_PREFIX."adherent as d"; +// SQL Aliase adherent +$sql .= " FROM ".MAIN_DB_PREFIX."adherent as d"; // maybe better to use ad (adh) instead od d if (!empty($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (d.rowid = ef.fk_object)"; } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = d.country)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as state on (state.rowid = d.state_id)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on (s.rowid = d.fk_soc)"; + +// SQL Aliase adherent_type $sql .= ", ".MAIN_DB_PREFIX."adherent_type as t"; $sql .= " WHERE d.fk_adherent_type = t.rowid"; @@ -525,8 +536,6 @@ if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $ exit; } -$help_url = 'EN:Module_Foundations|FR:Module_Adhérents|ES:Módulo_Miembros'; -llxHeader('', $title, $help_url); if ($search_type > 0) { $membertype = new AdherentType($db); @@ -534,6 +543,7 @@ if ($search_type > 0) { $title .= " (".$membertype->label.")"; } +// $parameters $param = ''; if (!empty($mode)) { $param .= '&mode='.urlencode($mode); @@ -613,6 +623,7 @@ if ($search_type > 0) { if ($optioncss != '') { $param .= '&optioncss='.urlencode($optioncss); } + // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; @@ -705,6 +716,7 @@ print ''; + // Action column if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print ''; } + // Line numbering if (!empty($conf->global->MAIN_SHOW_TECHNICAL_ID)) { print ''; @@ -723,32 +736,45 @@ if (!empty($arrayfields['d.ref']['checked'])) { print ''; print ''; } + +// Civility if (!empty($arrayfields['d.civility']['checked'])) { print ''; } + +// First Name if (!empty($arrayfields['d.firstname']['checked'])) { print ''; } + +// Last Name if (!empty($arrayfields['d.lastname']['checked'])) { print ''; } + +// Gender if (!empty($arrayfields['d.gender']['checked'])) { print ''; } + +// Company if (!empty($arrayfields['d.company']['checked'])) { print ''; } + +// Login if (!empty($arrayfields['d.login']['checked'])) { print ''; } + // Nature if (!empty($arrayfields['d.morphy']['checked'])) { print ''; } + +// Member Type if (!empty($arrayfields['t.libelle']['checked'])) { print ''; } @@ -766,51 +794,62 @@ if (!empty($arrayfields['t.libelle']['checked'])) { print ''; } +// Address - Street if (!empty($arrayfields['d.address']['checked'])) { print ''; } +// ZIP if (!empty($arrayfields['d.zip']['checked'])) { print ''; } + +// Town/City if (!empty($arrayfields['d.town']['checked'])) { print ''; } -// State + +// State / County / Departement if (!empty($arrayfields['state.nom']['checked'])) { print ''; } + // Country if (!empty($arrayfields['country.code_iso']['checked'])) { print ''; } + // Phone pro if (!empty($arrayfields['d.phone']['checked'])) { print ''; } + // Phone perso if (!empty($arrayfields['d.phone_perso']['checked'])) { print ''; + print ''; } + // Phone mobile if (!empty($arrayfields['d.phone_mobile']['checked'])) { print ''; } + // Email if (!empty($arrayfields['d.email']['checked'])) { print ''; } + // End of subscription date if (!empty($arrayfields['d.datefin']['checked'])) { print ''; } + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; @@ -826,21 +866,25 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; $parameters = array('arrayfields'=>$arrayfields); $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; + // Date creation if (!empty($arrayfields['d.datec']['checked'])) { print ''; } + // Birthday if (!empty($arrayfields['d.birth']['checked'])) { print ''; } + // Date modification if (!empty($arrayfields['d.tms']['checked'])) { print ''; } + // Status if (!empty($arrayfields['d.statut']['checked'])) { print ''; } + +// Import Key if (!empty($arrayfields['d.import_key']['checked'])) { print ''; } + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { // Action column print ''; } - + // Technical ID if (!empty($conf->global->MAIN_SHOW_TECHNICAL_ID)) { print ''; if (!$i) { $totalarray['nbfield']++; } } - // Ref if (!empty($arrayfields['d.ref']['checked'])) { print "\n"; if (!$i) { From cb84d7797f2291824c4d62a835e81ac00e1cc1bd Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sat, 14 Jan 2023 16:06:39 +0000 Subject: [PATCH 557/816] Fixing style errors. --- htdocs/adherents/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 39a4d993221..d06d91cbea6 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -358,7 +358,7 @@ $sql = preg_replace('/,\s*$/', '', $sql); $sqlfields = $sql; // $sql fields to remove for count total // SQL Aliase adherent -$sql .= " FROM ".MAIN_DB_PREFIX."adherent as d"; // maybe better to use ad (adh) instead od d +$sql .= " FROM ".MAIN_DB_PREFIX."adherent as d"; // maybe better to use ad (adh) instead od d if (!empty($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (d.rowid = ef.fk_object)"; } From bff128a061735948435045d55893a5bcc6a0fd2a Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Sat, 14 Jan 2023 17:41:29 +0100 Subject: [PATCH 558/816] Update list.php --- htdocs/contact/list.php | 100 +++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 26 deletions(-) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index a025ef81b97..1cc2d67cf93 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -101,10 +101,10 @@ $search_type = GETPOST('search_type', 'alpha'); $search_address = GETPOST('search_address', 'alpha'); $search_zip = GETPOST('search_zip', 'alpha'); $search_town = GETPOST('search_town', 'alpha'); -$search_import_key = GETPOST("search_import_key", "alpha"); +$search_import_key = GETPOST("search_import_key", 'alpha'); $search_country = GETPOST("search_country", 'intcomma'); $search_roles = GETPOST("search_roles", 'array'); -$search_level = GETPOST("search_level", "array"); +$search_level = GETPOST("search_level", 'array'); $search_stcomm = GETPOST('search_stcomm', 'int'); if ($search_status === '') { @@ -350,9 +350,14 @@ $formother = new FormOther($db); $formcompany = new FormCompany($db); $contactstatic = new Contact($db); -$morejs=array(); +$morejs = array(); $morecss = array(); +// Page Header +$title = $langs->trans("Contacts")." - ".$langs->trans("List"); +$help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Módulo_Empresas'; +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist'); + if (!empty($conf->global->THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES)) { $contactstatic->loadCacheOfProspStatus(); } @@ -387,6 +392,7 @@ $sql .= " p.phone as phone_pro, p.phone_mobile, p.phone_perso, p.fax, p.fk_pays, $sql .= " p.import_key,"; $sql .= " st.libelle as stcomm, st.picto as stcomm_picto, p.fk_stcommcontact as stcomm_id, p.fk_prospectlevel,"; $sql .= " co.label as country, co.code as country_code"; + // Add fields from extrafields if (!empty($extrafields->attributes[$object->table_element]['label'])) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { @@ -396,13 +402,15 @@ if (!empty($extrafields->attributes[$object->table_element]['label'])) { if (isModEnabled('mailing')) { $sql .= ", (SELECT count(*) FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = p.email) as unsubscribed"; } -// Add fields from hooks + +// Add fields from hooks - ListSelect $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; $sqlfields = $sql; // $sql fields to remove for count total +// SQL Table Aliase $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as p"; if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (p.rowid = ef.fk_object)"; @@ -413,7 +421,8 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_stcommcontact as st ON st.id = p.fk_stco if (empty($user->rights->societe->client->voir) && !$socid) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc"; } -// Add fields from hooks + +// Add fields from hooks - ListFrom $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; @@ -443,9 +452,13 @@ if ($search_priv != '0' && $search_priv != '1') { } } + +// Search Categories + + // Search Contact Categories $searchCategoryContactList = $search_categ ? array($search_categ) : array(); $searchCategoryContactOperator = 0; -// Search for tag/category ($searchCategoryContactList is an array of ID) + // Search for tag/category ($searchCategoryContactList is an array of ID) if (!empty($searchCategoryContactList)) { $searchCategoryContactSqlList = array(); $listofcategoryid = ''; @@ -473,9 +486,11 @@ if (!empty($searchCategoryContactList)) { } } } + + // Search Customer Categories $searchCategoryCustomerList = $search_categ_thirdparty ? array($search_categ_thirdparty) : array(); $searchCategoryCustomerOperator = 0; -// Search for tag/category ($searchCategoryCustomerList is an array of ID) + // Search for tag/category ($searchCategoryCustomerList is an array of ID) if (!empty($searchCategoryCustomerList)) { $searchCategoryCustomerSqlList = array(); $listofcategoryid = ''; @@ -503,9 +518,11 @@ if (!empty($searchCategoryCustomerList)) { } } } + + // Search Supplier Categories $searchCategorySupplierList = $search_categ_supplier ? array($search_categ_supplier) : array(); $searchCategorySupplierOperator = 0; -// Search for tag/category ($searchCategorySupplierList is an array of ID) + // Search for tag/category ($searchCategorySupplierList is an array of ID) if (!empty($searchCategorySupplierList)) { $searchCategorySupplierSqlList = array(); $listofcategoryid = ''; @@ -600,6 +617,7 @@ if (isModEnabled('socialnetworks')) { } } //print $sql; + if (strlen($search_email)) { $sql .= natural_search('p.email', $search_email); } @@ -627,20 +645,22 @@ if ($search_status != '' && $search_status >= 0) { if ($search_import_key) { $sql .= natural_search("p.import_key", $search_import_key); } -if ($type == "o") { // filtre sur type +if ($type == "o") { // filter on type $sql .= " AND p.fk_soc IS NULL"; -} elseif ($type == "f") { // filtre sur type +} elseif ($type == "f") { // filter on type $sql .= " AND s.fournisseur = 1"; -} elseif ($type == "c") { // filtre sur type +} elseif ($type == "c") { // filter on type $sql .= " AND s.client IN (1, 3)"; -} elseif ($type == "p") { // filtre sur type +} elseif ($type == "p") { // filter on type $sql .= " AND s.client IN (2, 3)"; } if (!empty($socid)) { $sql .= " AND s.rowid = ".((int) $socid); } + // 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, $object, $action); // Note that $action and $object may have been modified by hook @@ -695,8 +715,7 @@ if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && ( exit; } -$help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Módulo_Empresas'; -llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist'); + $param = ''; if (!empty($mode)) { @@ -948,20 +967,25 @@ if (!empty($arrayfields['p.town']['checked'])) { print ''; print ''; } + +/* // State -/*if (!empty($arrayfields['state.nom']['checked'])) + if (!empty($arrayfields['state.nom']['checked'])) { print ''; } + // Region if (!empty($arrayfields['region.nom']['checked'])) { print ''; - }*/ + } +*/ + // Country if (!empty($arrayfields['country.code_iso']['checked'])) { print ''; } -// Alias +// Alias of ThirdParty if (!empty($arrayfields['s.name_alias']['checked'])) { print ''; -// Ligne des titres +// Title line print ''; if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); @@ -1238,6 +1262,7 @@ while ($i < min($num, $limit)) { } print ''; } + // ID if (!empty($arrayfields['p.rowid']['checked'])) { print ''; @@ -1263,6 +1290,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Job position if (!empty($arrayfields['p.poste']['checked'])) { print ''; @@ -1270,6 +1298,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Address if (!empty($arrayfields['p.address']['checked'])) { print ''; @@ -1277,6 +1306,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Zip if (!empty($arrayfields['p.zip']['checked'])) { print ''; @@ -1284,6 +1314,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Town if (!empty($arrayfields['p.town']['checked'])) { print ''; @@ -1291,18 +1322,22 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + + /* // State - /*if (!empty($arrayfields['state.nom']['checked'])) + if (!empty($arrayfields['state.nom']['checked'])) { print "\n"; if (! $i) $totalarray['nbfield']++; } + // Region if (!empty($arrayfields['region.nom']['checked'])) { print "\n"; if (! $i) $totalarray['nbfield']++; }*/ + // Country if (!empty($arrayfields['country.code_iso']['checked'])) { print ''; if (!$i) { $totalarray['nbfield']++; } } + // Phone perso if (!empty($arrayfields['p.phone_perso']['checked'])) { print ''; @@ -1327,6 +1364,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Phone mobile if (!empty($arrayfields['p.phone_mobile']['checked'])) { print ''; @@ -1334,6 +1372,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Fax if (!empty($arrayfields['p.fax']['checked'])) { print ''; @@ -1341,6 +1380,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // EMail if (!empty($arrayfields['p.email']['checked'])) { print ''; @@ -1348,7 +1388,8 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - // No EMail + + // No EMail Subscription if (!empty($arrayfields['unsubscribed']['checked'])) { print '"; @@ -1415,8 +1459,8 @@ while ($i < min($num, $limit)) { } } + // Prospect status if (!empty($arrayfields['p.fk_stcommcontact']['checked'])) { - // Prospect status print ''; @@ -1466,6 +1513,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Import key if (!empty($arrayfields['p.import_key']['checked'])) { print ''; } - + // Region if (!empty($arrayfields['region.nom']['checked'])) { @@ -1262,7 +1262,7 @@ while ($i < min($num, $limit)) { } print ''; } - + // ID if (!empty($arrayfields['p.rowid']['checked'])) { print ''; @@ -1290,7 +1290,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Job position if (!empty($arrayfields['p.poste']['checked'])) { print ''; @@ -1298,7 +1298,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Address if (!empty($arrayfields['p.address']['checked'])) { print ''; @@ -1306,7 +1306,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Zip if (!empty($arrayfields['p.zip']['checked'])) { print ''; @@ -1314,7 +1314,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Town if (!empty($arrayfields['p.town']['checked'])) { print ''; @@ -1322,7 +1322,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + /* // State if (!empty($arrayfields['state.nom']['checked'])) @@ -1330,14 +1330,14 @@ while ($i < min($num, $limit)) { print "\n"; if (! $i) $totalarray['nbfield']++; } - + // Region if (!empty($arrayfields['region.nom']['checked'])) { print "\n"; if (! $i) $totalarray['nbfield']++; }*/ - + // Country if (!empty($arrayfields['country.code_iso']['checked'])) { print ''; @@ -1356,7 +1356,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Phone perso if (!empty($arrayfields['p.phone_perso']['checked'])) { print ''; @@ -1364,7 +1364,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Phone mobile if (!empty($arrayfields['p.phone_mobile']['checked'])) { print ''; @@ -1372,7 +1372,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Fax if (!empty($arrayfields['p.fax']['checked'])) { print ''; @@ -1380,7 +1380,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // EMail if (!empty($arrayfields['p.email']['checked'])) { print ''; @@ -1388,7 +1388,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // No EMail Subscription if (!empty($arrayfields['unsubscribed']['checked'])) { print ''; @@ -1513,7 +1513,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Import key if (!empty($arrayfields['p.import_key']['checked'])) { print '\n"; + // Address + print '\n"; + // Company name print '\n"; // Office fax print '\n"; // User mobile print '\n"; @@ -238,7 +238,7 @@ if (getDolUserInt('USER_ENABLE_PUBLIC', 0, $object)) { // Social networks print '\n"; @@ -262,7 +262,8 @@ if (getDolUserInt('USER_ENABLE_PUBLIC', 0, $object)) { print $langs->trans("Text"); print '\n"; From bd8a48b6ddd7b15788782a9703daa12db440ff55 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 01:45:54 +0100 Subject: [PATCH 568/816] css --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 278f70507bb..3e3a87c7bd0 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3170,7 +3170,7 @@ function dol_print_socialnetworks($value, $cid, $socid, $type, $dictsocialnetwor if (!empty($type)) { $htmllink = '
'; // Use dictionary definition for picto $dictsocialnetworks[$type]['icon'] - $htmllink .= ''; + $htmllink .= ''; if ($type == 'skype') { $htmllink .= dol_escape_htmltag($value); $htmllink .= ' 
'; //print '
'; From d7e4304992b37ff13a4059ccbe0e85856f4f9de0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 02:09:55 +0100 Subject: [PATCH 571/816] Try to fix social network inks in vcard --- htdocs/core/class/vcard.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index a5e1cbf6814..f6c8d14979b 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -441,7 +441,7 @@ class vCard } } if ($urlsn) { - $this->properties["socialProfile;type=".$key] = $urlsn; + $this->properties["SOCIALPROFILE;TYPE=home"] = $key.':'.$urlsn; } } } From bec559aae9406eca2171cfb4b6926ad756563709 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 02:16:35 +0100 Subject: [PATCH 572/816] Try to fix social network inks in vcard --- htdocs/core/class/vcard.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index f6c8d14979b..c66974f939b 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -359,7 +359,8 @@ class vCard $text .= "VERSION:4.0\r\n"; // With V4, all encoding are UTF-8 //$text.= "VERSION:2.1\r\n"; foreach ($this->properties as $key => $value) { - $text .= $key.":".$value."\r\n"; + $newkey = preg_replace('/-.*$/', '', $key); // remove suffix -twitter, -facebook, ... + $text .= $newkey.":".$value."\r\n"; } $text .= "REV:".date("Ymd")."T".date("His")."Z\r\n"; //$text .= "MAILER: Dolibarr\r\n"; @@ -441,7 +442,7 @@ class vCard } } if ($urlsn) { - $this->properties["SOCIALPROFILE;TYPE=home"] = $key.':'.$urlsn; + $this->properties["SOCIALPROFILE;TYPE=home-".$key] = $key.':'.$urlsn; } } } From 6a30104beb598a545d8798e68730c6afddc0981e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 02:19:47 +0100 Subject: [PATCH 573/816] Try to fix social network inks in vcard --- htdocs/core/class/vcard.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index c66974f939b..7b5a320f678 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -442,7 +442,7 @@ class vCard } } if ($urlsn) { - $this->properties["SOCIALPROFILE;TYPE=home-".$key] = $key.':'.$urlsn; + $this->properties["SOCIALPROFILE;TYPE=WORK-".$key] = $key.':'.$urlsn; } } } From b54a15f5047ae977bf39ec959161aa6931c7763f Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Sun, 15 Jan 2023 09:11:29 +0100 Subject: [PATCH 574/816] Fix missing keywords in dol_dir_list_in_database --- htdocs/core/lib/files.lib.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 21c290b595d..4195dee8dc1 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -344,6 +344,7 @@ function completeFileArrayWithDatabaseInfo(&$filearray, $relativedir) $filearray[$key]['position_name'] = ($filearrayindatabase[$key2]['position'] ? $filearrayindatabase[$key2]['position'] : '0').'_'.$filearrayindatabase[$key2]['name']; $filearray[$key]['position'] = $filearrayindatabase[$key2]['position']; $filearray[$key]['cover'] = $filearrayindatabase[$key2]['cover']; + $filearray[$key]['keywords'] = $filearrayindatabase[$key2]['keywords']; $filearray[$key]['acl'] = $filearrayindatabase[$key2]['acl']; $filearray[$key]['rowid'] = $filearrayindatabase[$key2]['rowid']; $filearray[$key]['label'] = $filearrayindatabase[$key2]['label']; From 24c5fcb5a7b0e6e0c2b97062bace7c5eab67a363 Mon Sep 17 00:00:00 2001 From: TuxGasy Date: Sun, 15 Jan 2023 10:24:19 +0100 Subject: [PATCH 575/816] Update to PHP 8.1 --- build/docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/docker/Dockerfile b/build/docker/Dockerfile index ead2a8af1c5..69f4d27b26f 100644 --- a/build/docker/Dockerfile +++ b/build/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM php:7.3-apache +FROM php:8.1-apache-bullseye ENV PHP_INI_DATE_TIMEZONE 'UTC' ENV PHP_INI_MEMORY_LIMIT 256M @@ -25,7 +25,7 @@ RUN apt-get update -y \ mailutils \ && apt-get autoremove -y \ && rm -rf /var/lib/apt/lists/* \ - && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ + && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) calendar intl mysqli pdo_mysql gd soap zip \ && docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu/ \ && docker-php-ext-install -j$(nproc) ldap && \ From 0cb2af4ecb26b9cfdc932538e952a3918cb83a59 Mon Sep 17 00:00:00 2001 From: TuxGasy Date: Sun, 15 Jan 2023 10:42:52 +0100 Subject: [PATCH 576/816] Fix update PHP config --- build/docker/README.md | 2 +- build/docker/docker-compose.yml | 2 ++ build/docker/docker-run.sh | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/build/docker/README.md b/build/docker/README.md index d469c7c7aae..007b5db6ace 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -25,7 +25,7 @@ The URL to go to the Dolibarr is : The URL to go to PhpMyAdmin is (login/password is root/root) : http://0.0.0.0:8080 - + In Dolibarr configuration Email let PHP mail function, To see all mail send by Dolibarr go to maildev http://0.0.0.0:8081 diff --git a/build/docker/docker-compose.yml b/build/docker/docker-compose.yml index 8994043cd8a..e197d5dd06e 100644 --- a/build/docker/docker-compose.yml +++ b/build/docker/docker-compose.yml @@ -34,6 +34,8 @@ services: build: . environment: HOST_USER_ID: $HOST_USER_ID + PHP_INI_DATE_TIMEZONE: $PHP_INI_DATE_TIMEZONE + PHP_INI_MEMORY_LIMIT: $PHP_INI_MEMORY_LIMIT volumes: - ../../htdocs:/var/www/html/ - ../../documents:/var/documents diff --git a/build/docker/docker-run.sh b/build/docker/docker-run.sh index 4e69ea4a3a2..fbd256ab625 100644 --- a/build/docker/docker-run.sh +++ b/build/docker/docker-run.sh @@ -15,10 +15,10 @@ fi echo "[docker-run] => Set Permission to www-data for /var/documents" chown -R www-data:www-data /var/documents -if [ ! -f /usr/local/etc/php/php.ini ]; then - cat < /usr/local/etc/php/php.ini -date.timezone = $PHP_INI_DATE_TIMEZONE +echo "[docker-run] => update ${PHP_INI_DIR}/conf.d/dolibarr-php.ini" +cat < ${PHP_INI_DIR}/conf.d/dolibarr-php.ini +date.timezone = ${PHP_INI_DATE_TIMEZONE:-UTC} +memory_limit = ${PHP_INI_MEMORY_LIMIT:-256M} EOF -fi exec apache2-foreground From 132fe6c19d9f42682a5b1f596fc5fc224ee47ba5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 11:13:53 +0100 Subject: [PATCH 577/816] Fix missing photo on user link --- htdocs/core/class/html.form.class.php | 5 +---- htdocs/user/card.php | 12 ++++++------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 369deba4455..276f7bacd69 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2137,10 +2137,7 @@ class Form $out .= ' selected'; } $out .= ' data-html="'; - $outhtml = ''; - // if (!empty($obj->photo)) { - $outhtml .= $userstatic->getNomUrl(-3, '', 0, 1, 24, 1, 'login', '', 1).' '; - // } + $outhtml = $userstatic->getNomUrl(-3, '', 0, 1, 24, 1, 'login', '', 1).' '; if ($showstatus >= 0 && $obj->status == 0) { $outhtml .= ''; } diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 0af78cc208f..ea47ba10beb 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1514,7 +1514,7 @@ if ($action == 'create' || $action == 'adduserldap') { $huser = new User($db); if ($object->fk_user > 0) { $huser->fetch($object->fk_user); - print $huser->getNomUrl(1); + print $huser->getNomUrl(-1); } else { print ''.$langs->trans("None").''; } @@ -1532,7 +1532,7 @@ if ($action == 'create' || $action == 'adduserldap') { if (!empty($object->fk_user_expense_validator)) { $evuser = new User($db); $evuser->fetch($object->fk_user_expense_validator); - print $evuser->getNomUrl(1); + print $evuser->getNomUrl(-1); } print ''; print "\n"; @@ -1548,7 +1548,7 @@ if ($action == 'create' || $action == 'adduserldap') { if (!empty($object->fk_user_holiday_validator)) { $hvuser = new User($db); $hvuser->fetch($object->fk_user_holiday_validator); - print $hvuser->getNomUrl(1); + print $hvuser->getNomUrl(-1); } print ''; print "\n"; @@ -2263,7 +2263,7 @@ if ($action == 'create' || $action == 'adduserldap') { print ''; $huser = new User($db); $huser->fetch($object->fk_user); - print $huser->getNomUrl(1); + print $huser->getNomUrl(-1); } print ''; print "\n"; @@ -2281,7 +2281,7 @@ if ($action == 'create' || $action == 'adduserldap') { print ''; $evuser = new User($db); $evuser->fetch($object->fk_user_expense_validator); - print $evuser->getNomUrl(1); + print $evuser->getNomUrl(-1); } print ''; print "\n"; @@ -2300,7 +2300,7 @@ if ($action == 'create' || $action == 'adduserldap') { print ''; $hvuser = new User($db); $hvuser->fetch($object->fk_user_holiday_validator); - print $hvuser->getNomUrl(1); + print $hvuser->getNomUrl(-1); } print ''; print "\n"; From fe2a58cf1d4beb1650c3089a306a7295b388451c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 11:36:31 +0100 Subject: [PATCH 578/816] Fix popup of companies in contract home page --- htdocs/contrat/index.php | 113 ++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/htdocs/contrat/index.php b/htdocs/contrat/index.php index d537934a299..c14775449c6 100644 --- a/htdocs/contrat/index.php +++ b/htdocs/contrat/index.php @@ -241,7 +241,7 @@ print "
'; @@ -712,6 +724,7 @@ if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { print $searchpicto; print ' '; print ''; print ''; print ''; $arraygender = array('man'=>$langs->trans("Genderman"), 'woman'=>$langs->trans("Genderwoman"), 'other'=>$langs->trans("Genderother")); print $form->selectarray('search_gender', $arraygender, $search_gender, 1); print ''; print ''; print ''; @@ -756,6 +782,8 @@ if (!empty($arrayfields['d.morphy']['checked'])) { print $form->selectarray('search_morphy', $arraymorphy, $search_morphy, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100'); print ''; print ''; print ''; print ''; print ''; print ''; print $form->select_country($search_country, 'search_country', '', 0, 'minwidth100imp maxwidth100'); print ''; print ''; - print ''; print ''; print ''; @@ -819,6 +858,7 @@ if (!empty($arrayfields['d.datefin']['checked'])) { print $form->selectarray('search_filter', $selectarray, $search_filter); print ''; print ''; print ''; print ''; @@ -853,11 +897,14 @@ if (!empty($arrayfields['d.statut']['checked'])) { print $form->selectarray('search_status', $liststatus, $search_status, -3, 0, 0, '', 0, 0, 0, '', 'search_status width100 onrightofpage'); print ''; print ''; print ''; @@ -938,6 +985,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; + if (!empty($arrayfields['d.datec']['checked'])) { print_liste_field_titre($arrayfields['d.datec']['label'], $_SERVER["PHP_SELF"], "d.datec", "", $param, 'align="center" class="nowrap"', $sortfield, $sortorder); } @@ -1025,14 +1073,13 @@ while ($i < min($num, $limit)) { } print ''.$obj->rowid.'"; @@ -1142,7 +1189,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - // State + // State / County / Departement if (!empty($arrayfields['state.nom']['checked'])) { print "".$obj->state_name."'; print ''; print ''; print ''; print ''; @@ -1014,7 +1038,7 @@ if (!empty($arrayfields['p.fk_soc']['checked']) || !empty($arrayfields['s.nom'][ print ''; print ''; print ''; @@ -1079,7 +1103,7 @@ if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { } print '
'; @@ -1247,7 +1272,8 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - // Name + + // (Last) Name if (!empty($arrayfields['p.lastname']['checked'])) { print ''; print $contactstatic->getNomUrl(1); @@ -1256,6 +1282,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Firstname if (!empty($arrayfields['p.firstname']['checked'])) { print ''.dol_escape_htmltag($obj->firstname).''.dol_escape_htmltag($obj->poste).''.dol_escape_htmltag($obj->address).''.dol_escape_htmltag($obj->zip).''.dol_escape_htmltag($obj->town).'".$obj->state_name."".$obj->region_name."'; @@ -1313,13 +1348,15 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - // Phone + + // Phone pro if (!empty($arrayfields['p.phone']['checked'])) { print ''.dol_print_phone($obj->phone_pro, $obj->country_code, $obj->rowid, $obj->socid, 'AC_TEL', ' ', 'phone').''.dol_print_phone($obj->phone_perso, $obj->country_code, $obj->rowid, $obj->socid, 'AC_TEL', ' ', 'phone').''.dol_print_phone($obj->phone_mobile, $obj->country_code, $obj->rowid, $obj->socid, 'AC_TEL', ' ', 'mobile').''.dol_print_phone($obj->fax, $obj->country_code, $obj->rowid, $obj->socid, 'AC_TEL', ' ', 'fax').''.dol_print_email($obj->email, $obj->rowid, $obj->socid, 'AC_EMAIL', 18, 0, 1).''; if (empty($obj->email)) { @@ -1361,6 +1402,8 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + + // Social Networks if (isModEnabled('socialnetworks')) { foreach ($socialnetworks as $key => $value) { if ($value['active'] && !empty($arrayfields['p.'.$key]['checked'])) { @@ -1371,7 +1414,8 @@ while ($i < min($num, $limit)) { } } } - // Company + + // Company / Third Party if (!empty($arrayfields['p.fk_soc']['checked']) || !empty($arrayfields['s.nom']['checked'])) { print ''; if ($obj->socid) { @@ -1404,9 +1448,9 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + + // Prospect Level if (!empty($arrayfields['p.fk_prospectlevel']['checked'])) { - // Prospect level print ''; print $contactstatic->getLibProspLevel(); print "
'; print '
'.$contactstatic->libProspCommStatut($obj->stcomm_id, 2, $contactstatic->cacheprospectstatus[$obj->stcomm_id]['label'], $obj->stcomm_picto); print '
-
'; @@ -1437,6 +1481,7 @@ while ($i < min($num, $limit)) { // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -1450,6 +1495,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Date modification if (!empty($arrayfields['p.tms']['checked'])) { print '
'; @@ -1459,6 +1505,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } + // Status if (!empty($arrayfields['p.statut']['checked'])) { print ''.$contactstatic->getLibStatut(5).''; From 35300b3dfc0b84910959113e74b2555f14804ca7 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sat, 14 Jan 2023 16:42:30 +0000 Subject: [PATCH 559/816] Fixing style errors. --- htdocs/contact/list.php | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 1cc2d67cf93..f34c477ff71 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -455,7 +455,7 @@ if ($search_priv != '0' && $search_priv != '1') { // Search Categories - // Search Contact Categories + // Search Contact Categories $searchCategoryContactList = $search_categ ? array($search_categ) : array(); $searchCategoryContactOperator = 0; // Search for tag/category ($searchCategoryContactList is an array of ID) @@ -487,7 +487,7 @@ if (!empty($searchCategoryContactList)) { } } - // Search Customer Categories + // Search Customer Categories $searchCategoryCustomerList = $search_categ_thirdparty ? array($search_categ_thirdparty) : array(); $searchCategoryCustomerOperator = 0; // Search for tag/category ($searchCategoryCustomerList is an array of ID) @@ -976,7 +976,7 @@ if (!empty($arrayfields['p.town']['checked'])) { print ''; print ''; @@ -1272,7 +1272,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // (Last) Name if (!empty($arrayfields['p.lastname']['checked'])) { print ''; @@ -1282,7 +1282,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Firstname if (!empty($arrayfields['p.firstname']['checked'])) { print ''.dol_escape_htmltag($obj->firstname).''.dol_escape_htmltag($obj->poste).''.dol_escape_htmltag($obj->address).''.dol_escape_htmltag($obj->zip).''.dol_escape_htmltag($obj->town).'".$obj->state_name."".$obj->region_name."'; @@ -1348,7 +1348,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Phone pro if (!empty($arrayfields['p.phone']['checked'])) { print ''.dol_print_phone($obj->phone_pro, $obj->country_code, $obj->rowid, $obj->socid, 'AC_TEL', ' ', 'phone').''.dol_print_phone($obj->phone_perso, $obj->country_code, $obj->rowid, $obj->socid, 'AC_TEL', ' ', 'phone').''.dol_print_phone($obj->phone_mobile, $obj->country_code, $obj->rowid, $obj->socid, 'AC_TEL', ' ', 'mobile').''.dol_print_phone($obj->fax, $obj->country_code, $obj->rowid, $obj->socid, 'AC_TEL', ' ', 'fax').''.dol_print_email($obj->email, $obj->rowid, $obj->socid, 'AC_EMAIL', 18, 0, 1).''; @@ -1402,7 +1402,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Social Networks if (isModEnabled('socialnetworks')) { foreach ($socialnetworks as $key => $value) { @@ -1448,7 +1448,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Prospect Level if (!empty($arrayfields['p.fk_prospectlevel']['checked'])) { print ''; @@ -1481,7 +1481,7 @@ while ($i < min($num, $limit)) { // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - + // Fields from hook $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -1495,7 +1495,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Date modification if (!empty($arrayfields['p.tms']['checked'])) { print ''; @@ -1505,7 +1505,7 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } } - + // Status if (!empty($arrayfields['p.statut']['checked'])) { print ''.$contactstatic->getLibStatut(5).''; From 64ecdd0632f4ef18518abcedf7ba117635e99362 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Sat, 14 Jan 2023 18:35:09 +0100 Subject: [PATCH 560/816] Update subaccount.php --- htdocs/accountancy/admin/subaccount.php | 32 ++++++++++++++++--------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/htdocs/accountancy/admin/subaccount.php b/htdocs/accountancy/admin/subaccount.php index 4f2274269d8..2f6a731ca48 100644 --- a/htdocs/accountancy/admin/subaccount.php +++ b/htdocs/accountancy/admin/subaccount.php @@ -19,17 +19,18 @@ /** * \file htdocs/accountancy/admin/subaccount.php - * \ingroup Accountancy (Double entries) - * \brief List of accounting sub-account (auxiliary accounts) + * \ingroup Accountancy (Double entries) + * \brief List of accounting sub-account (auxiliary accounts) */ // Load Dolibarr environment require '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; + // Load translation files required by the page -$langs->loadLangs(array("compta", "bills", "admin", "accountancy", "salaries", "hrm", "errors")); +$langs->loadLangs(array("accountancy", "admin", "bills", "compta", "errors", "hrm", "salaries")); $mesg = ''; $action = GETPOST('action', 'aZ09'); @@ -81,6 +82,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL < 2) { unset($arrayfields['reconcilable']); } + /* * Actions */ @@ -120,11 +122,13 @@ if (empty($reshook)) { $form = new Form($db); -$help_url = ''; -$title = $langs->trans('ChartOfIndividualAccountsOfSubsidiaryLedger'); +// Page Header +$help_url = 'EN:Module_Double_Entry_Accounting#Setup'; +$title = $langs->trans('ChartOfIndividualAccountsOfSubsidiaryLedger'); llxHeader('', $title, $help_url); + // Customer $sql = "SELECT sa.rowid, sa.nom as label, sa.code_compta as subaccount, '1' as type, sa.entity"; $sql .= " FROM ".MAIN_DB_PREFIX."societe sa"; @@ -219,7 +223,7 @@ if (!empty($search_type) && $search_type >= 0) { $sql .= " HAVING type LIKE '".$db->escape($search_type)."'"; } -// User +// User - Employee $sql .= " UNION "; $sql .= " SELECT u.rowid, u.lastname as label, u.accountancy_code as subaccount, '3' as type, u.entity FROM ".MAIN_DB_PREFIX."user u"; $sql .= " WHERE u.entity IN (".getEntity('user').")"; @@ -400,14 +404,17 @@ if ($resql) { if (!empty($arrayfields['type']['checked'])) { print ''; $s = ''; + // Customer if ($obj->type == 1) { $s .= ''.$langs->trans("Customer").''; } elseif ($obj->type == 2) { - // Supplier + + // Supplier $s .= ''.$langs->trans("Supplier").''; } elseif ($obj->type == 3) { - // User + + // User - Employee $s .= ''.$langs->trans("Employee").''; } print $s; @@ -440,14 +447,17 @@ if ($resql) { // Action print ''; $e = ''; + // Customer if ($obj->type == 1) { $e .= ''.img_edit().''; } elseif ($obj->type == 2) { - // Supplier + + // Supplier $e .= ''.img_edit().''; } elseif ($obj->type == 3) { - // User + + // User - Employee $e .= ''.img_edit().''; } print $e; From 5fef3398fd2e70a17ff9d3c8ce9b4185e1deb356 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sat, 14 Jan 2023 17:36:09 +0000 Subject: [PATCH 561/816] Fixing style errors. --- htdocs/accountancy/admin/subaccount.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/htdocs/accountancy/admin/subaccount.php b/htdocs/accountancy/admin/subaccount.php index 2f6a731ca48..40055a4b75f 100644 --- a/htdocs/accountancy/admin/subaccount.php +++ b/htdocs/accountancy/admin/subaccount.php @@ -404,17 +404,15 @@ if ($resql) { if (!empty($arrayfields['type']['checked'])) { print ''; $s = ''; - + // Customer if ($obj->type == 1) { $s .= ''.$langs->trans("Customer").''; } elseif ($obj->type == 2) { - - // Supplier + // Supplier $s .= ''.$langs->trans("Supplier").''; } elseif ($obj->type == 3) { - - // User - Employee + // User - Employee $s .= ''.$langs->trans("Employee").''; } print $s; @@ -447,17 +445,15 @@ if ($resql) { // Action print ''; $e = ''; - + // Customer if ($obj->type == 1) { $e .= ''.img_edit().''; } elseif ($obj->type == 2) { - - // Supplier + // Supplier $e .= ''.img_edit().''; } elseif ($obj->type == 3) { - - // User - Employee + // User - Employee $e .= ''.img_edit().''; } print $e; From 982ee6259fa649b233b98e0e5e9f88a5127cc54e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Jan 2023 21:21:48 +0100 Subject: [PATCH 562/816] NEW Session invalidation after a password change --- htdocs/api/class/api_login.class.php | 3 +++ htdocs/core/lib/security2.lib.php | 7 +++---- htdocs/core/lib/ws.lib.php | 4 ++++ htdocs/core/login/functions_dolibarr.php | 19 ++++++++++++++++++- htdocs/main.inc.php | 1 + htdocs/user/card.php | 4 ++++ htdocs/user/class/user.class.php | 2 +- 7 files changed, 34 insertions(+), 6 deletions(-) diff --git a/htdocs/api/class/api_login.class.php b/htdocs/api/class/api_login.class.php index d5362f4ac56..0b8d3e64828 100644 --- a/htdocs/api/class/api_login.class.php +++ b/htdocs/api/class/api_login.class.php @@ -121,6 +121,9 @@ class Login include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; $login = checkLoginPassEntity($login, $password, $entity, $authmode, 'api'); // Check credentials. + if ($login === '--bad-login-validity--') { + $login = ''; + } if (empty($login)) { throw new RestException(403, 'Access denied'); } diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index b33ad1333ef..5e4d58103d8 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -52,12 +52,11 @@ function dol_getwebuser($mode) * @param string $entitytotest Instance of data we must check * @param array $authmode Array list of selected authentication mode array('http', 'dolibarr', 'xxx'...) * @param string $context Context checkLoginPassEntity was created for ('api', 'dav', 'ws', '') - * @return string Login or '' + * @return string Login or '' or '--bad-login-validity--' */ function checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $authmode, $context = '') { global $conf, $langs; - //global $dolauthmode; // To return authentication finally used // Check parameters if ($entitytotest == '') { @@ -100,10 +99,10 @@ function checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $auth if ($login && $login != '--bad-login-validity--') { // Login is successfull $test = false; // To stop once at first login success $conf->authmode = $mode; // This properties is defined only when logged to say what mode was successfully used - $dol_tz = GETPOST('tz'); + /*$dol_tz = GETPOST('tz'); $dol_dst = GETPOST('dst'); $dol_screenwidth = GETPOST('screenwidth'); - $dol_screenheight = GETPOST('screenheight'); + $dol_screenheight = GETPOST('screenheight');*/ } } else { dol_syslog("Authentication KO - failed to load file '".$authfile."'", LOG_ERR); diff --git a/htdocs/core/lib/ws.lib.php b/htdocs/core/lib/ws.lib.php index ad4688f9134..a26604b18bc 100644 --- a/htdocs/core/lib/ws.lib.php +++ b/htdocs/core/lib/ws.lib.php @@ -86,6 +86,10 @@ function check_authentication($authentication, &$error, &$errorcode, &$errorlabe include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; $login = checkLoginPassEntity($authentication['login'], $authentication['password'], $authentication['entity'], $authmode, 'ws'); + if ($login === '--bad-login-validity--') { + $login = ''; + } + if (empty($login)) { $error++; $errorcode = 'BAD_CREDENTIALS'; diff --git a/htdocs/core/login/functions_dolibarr.php b/htdocs/core/login/functions_dolibarr.php index e8c3ab38e46..b732d2ef64b 100644 --- a/htdocs/core/login/functions_dolibarr.php +++ b/htdocs/core/login/functions_dolibarr.php @@ -28,6 +28,7 @@ /** * Check validity of user/password/entity * If test is ko, reason must be filled into $_SESSION["dol_loginmesg"] + * Note: On critical error (hack attempt), we put a log "functions_dolibarr::check_user_password_dolibarr authentication KO" * * @param string $usertotest Login * @param string $passwordtotest Password @@ -56,7 +57,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes $usernamecol2 = 'email'; $entitycol = 'entity'; - $sql = "SELECT rowid, login, entity, pass, pass_crypted, datestartvalidity, dateendvalidity"; + $sql = "SELECT rowid, login, entity, pass, pass_crypted, datestartvalidity, dateendvalidity, flagdelsessionsbefore"; $sql .= " FROM ".$table; $sql .= " WHERE (".$usernamecol1." = '".$db->escape($usertotest)."'"; if (preg_match('/@/', $usertotest)) { @@ -74,18 +75,34 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes $obj = $db->fetch_object($resql); if ($obj) { $now = dol_now(); + // Check date start validity if ($obj->datestartvalidity && $db->jdate($obj->datestartvalidity) > $now) { // Load translation files required by the page $langs->loadLangs(array('main', 'errors')); $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity"); + dol_syslog("functions_dolibarr::check_user_password_dolibarr bad datestart validity", LOG_WARNING); return '--bad-login-validity--'; } + // Check date end validity if ($obj->dateendvalidity && $db->jdate($obj->dateendvalidity) < dol_get_first_hour($now)) { // Load translation files required by the page $langs->loadLangs(array('main', 'errors')); $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity"); + dol_syslog("functions_dolibarr::check_user_password_dolibarr bad date end validity", LOG_WARNING); return '--bad-login-validity--'; } + // If there is an invalidation date, check that the current session date is not before this date + if ($obj->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"])) { + dol_syslog("functions_dolibarr::check_user_password_dolibarr user has a date for session invalidation = ".$obj->flagdelsessionsbefore." and session date = ".$_SESSION["dol_logindate"]); + $datetmp = $db->jdate($obj->flagdelsessionsbefore, 'gmt'); + if ($datetmp > $now) { + // Load translation files required by the page + $langs->loadLangs(array('main', 'errors')); + $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorSessionInvalidatedAfterPasswordChange"); + dol_syslog("functions_dolibarr::check_user_password_dolibarr session was invalidated", LOG_WARNING); + return '--bad-login-validity--'; + } + } $passclear = $obj->pass; $passcrypted = $obj->pass_crypted; diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 549c72157a6..7d764d4a105 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1048,6 +1048,7 @@ if (!defined('NOLOGIN')) { // Store value into session (values always stored) $_SESSION["dol_login"] = $user->login; + $_SESSION["dol_logindate"] = dol_now('gmt'); $_SESSION["dol_authmode"] = isset($dol_authmode) ? $dol_authmode : ''; $_SESSION["dol_tz"] = isset($dol_tz) ? $dol_tz : ''; $_SESSION["dol_tz_string"] = isset($dol_tz_string) ? $dol_tz_string : ''; diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 67ea2174322..0af78cc208f 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -71,6 +71,10 @@ $group = GETPOST("group", "int", 3); $cancel = GETPOST('cancel', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'useracard'; // To manage different context of search +if (empty($id)) { + $id = $user->id; +} + $dateemployment = dol_mktime(0, 0, 0, GETPOST('dateemploymentmonth', 'int'), GETPOST('dateemploymentday', 'int'), GETPOST('dateemploymentyear', 'int')); $dateemploymentend = dol_mktime(0, 0, 0, GETPOST('dateemploymentendmonth', 'int'), GETPOST('dateemploymentendday', 'int'), GETPOST('dateemploymentendyear', 'int')); $datestartvalidity = dol_mktime(0, 0, 0, GETPOST('datestartvaliditymonth', 'int'), GETPOST('datestartvalidityday', 'int'), GETPOST('datestartvalidityyear', 'int')); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 9e208ff3e37..7e342e64337 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2298,7 +2298,7 @@ class User extends CommonObject $sql = "UPDATE ".$this->db->prefix()."user"; $sql .= " SET pass_crypted = '".$this->db->escape($password_crypted)."',"; $sql .= " pass_temp = null"; - if (empty($flagdelsessionsbefore)) { + if (!empty($flagdelsessionsbefore)) { $sql .= ", flagdelsessionsbefore = '".$this->db->idate(dol_now() - 5, 'gmt')."'"; } if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) { From 39a224d7a1eaf637c369a199a8971b5c5874a019 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Sun, 15 Jan 2023 01:18:32 +0100 Subject: [PATCH 563/816] Update bookmarks.lang --- htdocs/langs/en_US/bookmarks.lang | 47 ++++++++++++++++--------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/htdocs/langs/en_US/bookmarks.lang b/htdocs/langs/en_US/bookmarks.lang index 26551eee4f0..bfbab1ef520 100644 --- a/htdocs/langs/en_US/bookmarks.lang +++ b/htdocs/langs/en_US/bookmarks.lang @@ -1,23 +1,24 @@ -# Dolibarr language file - Source file is en_US - marque pages -AddThisPageToBookmarks=Add current page to bookmarks -Bookmark=Bookmark -Bookmarks=Bookmarks -ListOfBookmarks=List of bookmarks -EditBookmarks=List/edit bookmarks -NewBookmark=New bookmark -ShowBookmark=Show bookmark -OpenANewWindow=Open a new tab -ReplaceWindow=Replace current tab -BookmarkTargetNewWindowShort=New tab -BookmarkTargetReplaceWindowShort=Current tab -BookmarkTitle=Bookmark name -UrlOrLink=URL -BehaviourOnClick=Behaviour when a bookmark URL is selected -CreateBookmark=Create bookmark -SetHereATitleForLink=Set a name for the bookmark -UseAnExternalHttpLinkOrRelativeDolibarrLink=Use an external/absolute link (https://externalurl.com) or an internal/relative link (/mypage.php). You can also use phone like tel:0123456. -ChooseIfANewWindowMustBeOpenedOnClickOnBookmark=Choose if the linked page should open in the current tab or a new tab -BookmarksManagement=Bookmarks management -BookmarksMenuShortCut=Ctrl + shift + m -NoBookmarks=No bookmarks defined -NoBookmarkFound=No bookmark found \ No newline at end of file +# Dolibarr language file - Source file is en_US - marque pages / bookmarks + +AddThisPageToBookmarks = Add current page to bookmarks +BehaviourOnClick = Behaviour when a bookmark URL is selected +Bookmark = Bookmark +Bookmarks = Bookmarks +BookmarkTargetNewWindowShort = New tab +BookmarkTargetReplaceWindowShort = Current tab +BookmarkTitle = Bookmark name +BookmarksManagement = Bookmarks management +BookmarksMenuShortCut = Ctrl + shift + m +ChooseIfANewWindowMustBeOpenedOnClickOnBookmark = Choose if the linked page should open in the current tab or a new tab +CreateBookmark = Create bookmark +EditBookmarks = List/edit bookmarks +ListOfBookmarks = List of bookmarks +NewBookmark = New bookmark +NoBookmarkFound = No bookmark found +NoBookmarks = No bookmarks defined +OpenANewWindow = Open a new tab +ReplaceWindow = Replace current tab +SetHereATitleForLink = Set a name for the bookmark +ShowBookmark = Show bookmark +UrlOrLink = URL +UseAnExternalHttpLinkOrRelativeDolibarrLink = Use an external/absolute link (https://externalurl.com) or an internal/relative link (/mypage.php). You can also use phone like tel:0123456. From b754b7a99fb530c4f7eee006ae7dc9b0ef0ee51f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 01:25:07 +0100 Subject: [PATCH 564/816] Enhance vcard --- htdocs/core/class/vcard.class.php | 10 ++++++---- htdocs/public/users/view.php | 27 +++++++++++++++------------ htdocs/user/virtualcard.php | 8 ++++++++ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index e7eb318e476..4404736f5e0 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -183,7 +183,7 @@ class vCard } /** - * mise en forme de l'adresse + * Address * * @param string $postoffice Postoffice * @param string $extended Extended @@ -196,7 +196,7 @@ class vCard * @param string $label Label * @return void */ - public function setAddress($postoffice = "", $extended = "", $street = "", $city = "", $region = "", $zip = "", $country = "", $type = "HOME", $label = '') + public function setAddress($postoffice = "", $extended = "", $street = "", $city = "", $region = "", $zip = "", $country = "", $type = "", $label = "") { // $type may be DOM | INTL | POSTAL | PARCEL | HOME | WORK or any combination of these: e.g. "WORK;PARCEL;POSTAL" $key = "ADR"; @@ -207,7 +207,7 @@ class vCard $key .= ';LABEL="'.encode($label).'"'; } $key .= ";".$this->encoding; - $this->properties[$key] = ";".encode($extended).";".encode($street).";".encode($city).";".encode($region).";".encode($zip).";".encode($country); + $this->properties[$key] = encode($postoffice).";".encode($extended).";".encode($street).";".encode($city).";".encode($region).";".encode($zip).";".encode($country); //if ($this->properties["LABEL;".$type.";".$this->encoding] == '') { //$this->setLabel($postoffice, $extended, $street, $city, $region, $zip, $country, $type); @@ -215,7 +215,7 @@ class vCard } /** - * mise en forme du label + * Address (old standard) * * @param string $postoffice Postoffice * @param string $extended Extended @@ -226,6 +226,7 @@ class vCard * @param string $country Country * @param string $type Type * @return void + * @deprecated */ public function setLabel($postoffice = "", $extended = "", $street = "", $city = "", $region = "", $zip = "", $country = "", $type = "HOME") { @@ -378,6 +379,7 @@ class vCard /** * Return a VCARD string + * See RFC https://datatracker.ietf.org/doc/html/rfc6350 * * @param Object $object Object (User or Contact) * @param Societe|null $company Company. May be null diff --git a/htdocs/public/users/view.php b/htdocs/public/users/view.php index ec5f53377c2..a5d3ac5b1e6 100644 --- a/htdocs/public/users/view.php +++ b/htdocs/public/users/view.php @@ -114,11 +114,11 @@ if (!empty($object->photo)) { $urllogo = ''; $urllogofull = ''; if (!empty($logosmall) && is_readable($dir.'/'.$logosmall)) { - $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logosmall); - $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logosmall); + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.($conf->entity > 1 ? '&entity='.$conf->entity : '').'&securekey='.urlencode($securekey).'&file='.urlencode($logosmall); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.($conf->entity > 1 ? '&entity='.$conf->entity : '').'&securekey='.urlencode($securekey).'&file='.urlencode($logosmall); } elseif (!empty($logo) && is_readable($dir.'/'.$logo)) { - $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logo); - $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.'&entity='.$conf->entity.'&securekey='.urlencode($securekey).'&file='.urlencode($logo); + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.($conf->entity > 1 ? '&entity='.$conf->entity : '').'&securekey='.urlencode($securekey).'&file='.urlencode($logo); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart='.$modulepart.($conf->entity > 1 ? '&entity='.$conf->entity : '').'&securekey='.urlencode($securekey).'&file='.urlencode($logo); } // Clean data we don't want on public page @@ -152,6 +152,12 @@ if (getDolUserInt('USER_PUBLIC_HIDE_BIRTH', 0, $object)) { if (getDolUserInt('USER_PUBLIC_HIDE_SOCIALNETWORKS', 0, $object)) { $object->socialnetworks = ''; } +if (getDolUserInt('USER_PUBLIC_HIDE_ADDRESS', 0, $object)) { + $object->address = ''; + $object->zip = ''; + $object->state = ''; + $object->country = ''; +} if (getDolUserInt('USER_PUBLIC_HIDE_COMPANY', 0, $object)) { $company = null; } @@ -159,9 +165,6 @@ if (getDolUserInt('USER_PUBLIC_HIDE_COMPANY', 0, $object)) { // Output vcard if ($mode == 'vcard') { - // Reset data no selected for public VCard - - // We create VCard $output = $v->buildVCardString($object, $company, $langs, $urllogofull); @@ -169,7 +172,7 @@ if ($mode == 'vcard') { $filenameurlencoded = dol_sanitizeFileName(urlencode($filename)); //$filename = dol_sanitizeFileName($filename); - top_httphead('text/x-vcard; name="'.$filename.'"'); + top_httphead('text/vcard; name="'.$filename.'"'); header("Content-Disposition: attachment; filename=\"".$filename."\""); header("Content-Length: ".dol_strlen($output)); @@ -387,11 +390,11 @@ if (!getDolUserInt('USER_PUBLIC_HIDE_COMPANY', 0, $object)) { $urllogo = ''; $urllogofull = ''; if (!empty($logosmall) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$logosmall)) { - $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall); - $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall); + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany'.($conf->entity > 1 ? '&entity='.$conf->entity : '').'&file='.urlencode('logos/thumbs/'.$logosmall); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany'.($conf->entity > 1 ? '&entity='.$conf->entity : '').'&file='.urlencode('logos/thumbs/'.$logosmall); } elseif (!empty($logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$logo)) { - $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo); - $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo); + $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany'.($conf->entity > 1 ? '&entity='.$conf->entity : '').'&file='.urlencode('logos/'.$logo); + $urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany'.($conf->entity > 1 ? '&entity='.$conf->entity : '').'&file='.urlencode('logos/'.$logo); } // Output html code for logo if ($urllogo) { diff --git a/htdocs/user/virtualcard.php b/htdocs/user/virtualcard.php index 7e13950747c..4685c6e9b16 100644 --- a/htdocs/user/virtualcard.php +++ b/htdocs/user/virtualcard.php @@ -75,6 +75,7 @@ if ($action == 'update') { $tmparray['USER_PUBLIC_HIDE_USER_MOBILE'] = (GETPOST('USER_PUBLIC_HIDE_USER_MOBILE') ? 1 : 0); $tmparray['USER_PUBLIC_HIDE_BIRTH'] = (GETPOST('USER_PUBLIC_HIDE_BIRTH') ? 1 : 0); $tmparray['USER_PUBLIC_HIDE_SOCIALNETWORKS'] = (GETPOST('USER_PUBLIC_HIDE_SOCIALNETWORKS') ? 1 : 0); + $tmparray['USER_PUBLIC_HIDE_ADDRESS'] = (GETPOST('USER_PUBLIC_HIDE_ADDRESS') ? 1 : 0); $tmparray['USER_PUBLIC_HIDE_COMPANY'] = (GETPOST('USER_PUBLIC_HIDE_COMPANY') ? 1 : 0); $tmparray['USER_PUBLIC_MORE'] = (GETPOST('USER_PUBLIC_MORE') ? GETPOST('USER_PUBLIC_MORE') : ''); @@ -242,6 +243,13 @@ if (getDolUserInt('USER_ENABLE_PUBLIC', 0, $object)) { print $form->selectyesno("USER_PUBLIC_HIDE_SOCIALNETWORKS", (getDolUserInt('USER_PUBLIC_HIDE_SOCIALNETWORKS', 0, $object) ? getDolUserInt('USER_PUBLIC_HIDE_SOCIALNETWORKS', 0, $object) : 0), 1); print "
'; + print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("Address")); + print ''; + print $form->selectyesno("USER_PUBLIC_HIDE_ADDRESS", (getDolUserInt('USER_PUBLIC_HIDE_ADDRESS', 0, $object) ? getDolUserInt('USER_PUBLIC_HIDE_ADDRESS', 0, $object) : 0), 1); + print "
'; print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("CompanySection")); From 35a7f3c0ff759ee89ac1f4fdc45db37a26bd209e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 01:28:02 +0100 Subject: [PATCH 565/816] Enhance vcard --- htdocs/core/class/vcard.class.php | 2 +- htdocs/public/users/view.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index 4404736f5e0..8d586648f80 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -449,7 +449,7 @@ class vCard $country = $object->country_code ? $object->country : ''; if ($object->address || $object->town || $object->state || $object->zip || $object->country) { - $this->setAddress("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=WORK"); + $this->setAddress("", "", $object->address, $object->town, $object->state, $object->zip, $country, ""); //$this->setLabel("", "", $object->address, $object->town, $object->state, $object->zip, $country, "TYPE=HOME"); } diff --git a/htdocs/public/users/view.php b/htdocs/public/users/view.php index a5d3ac5b1e6..03d153dedd0 100644 --- a/htdocs/public/users/view.php +++ b/htdocs/public/users/view.php @@ -154,6 +154,7 @@ if (getDolUserInt('USER_PUBLIC_HIDE_SOCIALNETWORKS', 0, $object)) { } if (getDolUserInt('USER_PUBLIC_HIDE_ADDRESS', 0, $object)) { $object->address = ''; + $object->town = ''; $object->zip = ''; $object->state = ''; $object->country = ''; From e41098c5273838f1ac3d7991eaec8a4c84061f52 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 01:31:23 +0100 Subject: [PATCH 566/816] Enhance vcard --- htdocs/core/class/vcard.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index 8d586648f80..7625954690b 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -31,7 +31,7 @@ */ function encode($string) { - return str_replace(";", "\;", (dol_quoted_printable_encode(utf8_decode($string)))); + return str_replace(";", "\;", (dol_quoted_printable_encode($string))); } @@ -488,7 +488,7 @@ class vCard $this->setPhoneNumber($company->fax, "TYPE=WORK,FAX"); } if ($company->address || $company->town || $company->state || $company->zip || $company->country) { - $this->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, "TYPE=WORK"); + $this->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, ""); } if ($company->email && $company->email != $object->email) { From f8e5889ba7777d056a297c0c882a71c1841f5cd0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 01:42:11 +0100 Subject: [PATCH 567/816] Enhance vcard --- htdocs/core/class/vcard.class.php | 2 +- htdocs/langs/en_US/companies.lang | 3 ++- htdocs/user/virtualcard.php | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/vcard.class.php b/htdocs/core/class/vcard.class.php index 7625954690b..a5e1cbf6814 100644 --- a/htdocs/core/class/vcard.class.php +++ b/htdocs/core/class/vcard.class.php @@ -488,7 +488,7 @@ class vCard $this->setPhoneNumber($company->fax, "TYPE=WORK,FAX"); } if ($company->address || $company->town || $company->state || $company->zip || $company->country) { - $this->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, ""); + $this->setAddress("", "", $company->address, $company->town, $company->state, $company->zip, $company->country, "TYPE=WORK"); } if ($company->email && $company->email != $object->email) { diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 7200ffb3d70..d31ecb077ff 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -499,4 +499,5 @@ OutOfEurope=Out of Europe (EEC) CurrentOutstandingBillLate=Current outstanding bill late BecarefullChangeThirdpartyBeforeAddProductToInvoice=Be carefull, depending on your product price settings, you should change thirdparty before adding product to POS. EmailAlreadyExistsPleaseRewriteYourCompanyName=email already exists please rewrite your company name -TwoRecordsOfCompanyName=more than one record exists for this company please contact us to complete your partnership request" \ No newline at end of file +TwoRecordsOfCompanyName=more than one record exists for this company please contact us to complete your partnership request" +CompanySection=Company section \ No newline at end of file diff --git a/htdocs/user/virtualcard.php b/htdocs/user/virtualcard.php index 4685c6e9b16..04f8fb42030 100644 --- a/htdocs/user/virtualcard.php +++ b/htdocs/user/virtualcard.php @@ -210,21 +210,21 @@ if (getDolUserInt('USER_ENABLE_PUBLIC', 0, $object)) { // Office phone print '
'; - print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("OfficePhone")); + print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("PhonePro")); print ''; print $form->selectyesno("USER_PUBLIC_HIDE_OFFICE_PHONE", (getDolUserInt('USER_PUBLIC_HIDE_OFFICE_PHONE', 0, $object) ? getDolUserInt('USER_PUBLIC_HIDE_OFFICE_PHONE', 0, $object) : 0), 1); print "
'; - print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("OfficeFax")); + print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("Fax")); print ''; print $form->selectyesno("USER_PUBLIC_HIDE_OFFICE_FAX", (getDolUserInt('USER_PUBLIC_HIDE_OFFICE_FAX', 0, $object) ? getDolUserInt('USER_PUBLIC_HIDE_OFFICE_FAX', 0, $object) : 0), 1); print "
'; - print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("UserMobile")); + print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("PhoneMobile")); print ''; print $form->selectyesno("USER_PUBLIC_HIDE_USER_MOBILE", (getDolUserInt('USER_PUBLIC_HIDE_USER_MOBILE', 0, $object) ? getDolUserInt('USER_PUBLIC_HIDE_USER_MOBILE', 0, $object) : 0), 1); print "
'; - print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("SocialNetworks")); + print $langs->trans("HideOnVCard", $langs->transnoentitiesnoconv("SocialNetworksInformation")); print ''; print $form->selectyesno("USER_PUBLIC_HIDE_SOCIALNETWORKS", (getDolUserInt('USER_PUBLIC_HIDE_SOCIALNETWORKS', 0, $object) ? getDolUserInt('USER_PUBLIC_HIDE_SOCIALNETWORKS', 0, $object) : 0), 1); print "
'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; - $doleditor = new DolEditor('USER_PUBLIC_MORE', getDolUserString('USER_PUBLIC_MORE', '', $object), '', 160, 'dolibarr_notes', '', false, false, isModEnabled('fckeditor'), ROWS_5, '90%'); + $extendededitor = 0; // We force no WYSIWYG editor + $doleditor = new DolEditor('USER_PUBLIC_MORE', getDolUserString('USER_PUBLIC_MORE', '', $object), '', 160, 'dolibarr_notes', '', false, false, $extendededitor, ROWS_5, '90%'); $doleditor->Create(); print "

"; if (isModEnabled('contrat') && $user->rights->contrat->lire) { $sql = "SELECT c.rowid, c.ref,"; - $sql .= " s.nom as name, s.rowid as socid"; + $sql .= " s.nom as name, s.name_alias, s.logo, s.rowid as socid, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur"; $sql .= " FROM ".MAIN_DB_PREFIX."contrat as c, ".MAIN_DB_PREFIX."societe as s"; if (empty($user->rights->societe->client->voir) && !$socid) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -266,8 +266,6 @@ if (isModEnabled('contrat') && $user->rights->contrat->lire) { print ''; print ''.$langs->trans("DraftContracts").($num ? ''.$num.'' : '').''; if ($num) { - $companystatic = new Societe($db); - $i = 0; //$tot_ttc = 0; while ($i < $num) { @@ -276,22 +274,29 @@ if (isModEnabled('contrat') && $user->rights->contrat->lire) { $staticcontrat->ref = $obj->ref; $staticcontrat->id = $obj->rowid; - $companystatic->id = $obj->socid; - $companystatic->name = $obj->name; - $companystatic->client = 1; + $staticcompany->id = $obj->socid; + $staticcompany->name = $obj->name; + $staticcompany->name_alias = $obj->name_alias; + $staticcompany->photo = 1; + $staticcompany->code_client = $obj->code_client; + $staticcompany->code_fournisseur = $obj->code_fournisseur; + $staticcompany->code_compta = $obj->code_compta; + $staticcompany->code_compta_fournisseur = $obj->code_compta_fournisseur; + $staticcompany->client = $obj->client; + $staticcompany->fournisseur = $obj->fournisseur; print ''; print $staticcontrat->getNomUrl(1, ''); print ''; print ''; - print $companystatic->getNomUrl(1, '', 16); + print $staticcompany->getNomUrl(1, '', 16); print ''; print ''; //$tot_ttc+=$obj->total_ttc; $i++; } } else { - print ''.$langs->trans("NoContracts").''; + print ''.$langs->trans("NoContracts").''; } print "

"; $db->free($resql); @@ -312,7 +317,8 @@ $sql .= " sum(".$db->ifsql("cd.statut=4 AND (cd.date_fin_validite IS NULL OR cd. $sql .= " sum(".$db->ifsql("cd.statut=4 AND (cd.date_fin_validite IS NOT NULL AND cd.date_fin_validite < '".$db->idate($now)."')", 1, 0).') as nb_expired,'; $sql .= " sum(".$db->ifsql("cd.statut=4 AND (cd.date_fin_validite IS NOT NULL AND cd.date_fin_validite < '".$db->idate($now - $conf->contrat->services->expires->warning_delay)."')", 1, 0).') as nb_late,'; $sql .= " sum(".$db->ifsql("cd.statut=5", 1, 0).') as nb_closed,'; -$sql .= " c.rowid as cid, c.ref, c.datec, c.tms, c.statut, s.nom as name, s.rowid as socid"; +$sql .= " c.rowid as cid, c.ref, c.datec, c.tms, c.statut,"; +$sql .= " s.nom as name, s.name_alias, s.logo, s.rowid as socid, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur"; $sql .= " FROM ".MAIN_DB_PREFIX."societe as s,"; if (empty($user->rights->societe->client->voir) && !$socid) { $sql .= " ".MAIN_DB_PREFIX."societe_commerciaux as sc,"; @@ -328,7 +334,8 @@ if (empty($user->rights->societe->client->voir) && !$socid) { if ($socid) { $sql .= " AND s.rowid = ".((int) $socid); } -$sql .= " GROUP BY c.rowid, c.ref, c.datec, c.tms, c.statut, s.nom, s.rowid"; +$sql .= " GROUP BY c.rowid, c.ref, c.datec, c.tms, c.statut,"; +$sql .= " s.nom, s.name_alias, s.logo, s.rowid, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur"; $sql .= " ORDER BY c.tms DESC"; $sql .= $db->plimit($max); @@ -356,6 +363,14 @@ if ($result) { $staticcompany->id = $obj->socid; $staticcompany->name = $obj->name; + $staticcompany->name_alias = $obj->name_alias; + $staticcompany->photo = 1; + $staticcompany->code_client = $obj->code_client; + $staticcompany->code_fournisseur = $obj->code_fournisseur; + $staticcompany->code_compta = $obj->code_compta; + $staticcompany->code_compta_fournisseur = $obj->code_compta_fournisseur; + $staticcompany->client = $obj->client; + $staticcompany->fournisseur = $obj->fournisseur; print ''; print ''; @@ -389,9 +404,9 @@ if ($result) { print '
'; // Last modified services -$sql = "SELECT c.ref, c.fk_soc, "; +$sql = "SELECT c.ref, c.fk_soc as socid,"; $sql .= " cd.rowid as cid, cd.statut, cd.label, cd.fk_product, cd.description as note, cd.fk_contrat, cd.date_fin_validite,"; -$sql .= " s.nom as name,"; +$sql .= " s.nom as name, s.name_alias, s.logo, s.rowid as socid, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; $sql .= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype, p.entity as pentity"; $sql .= " FROM (".MAIN_DB_PREFIX."contrat as c"; $sql .= ", ".MAIN_DB_PREFIX."societe as s"; @@ -427,9 +442,23 @@ if ($resql) { print ''; print ''; + $staticcontrat->ref = ($obj->ref ? $obj->ref : $obj->fk_contrat); $staticcontrat->id = $obj->fk_contrat; + + $staticcompany->id = $obj->socid; + $staticcompany->name = $obj->name; + $staticcompany->name_alias = $obj->name_alias; + $staticcompany->photo = 1; + $staticcompany->code_client = $obj->code_client; + $staticcompany->code_fournisseur = $obj->code_fournisseur; + $staticcompany->code_compta = $obj->code_compta; + $staticcompany->code_compta_fournisseur = $obj->code_compta_fournisseur; + $staticcompany->client = $obj->client; + $staticcompany->fournisseur = $obj->fournisseur; + print $staticcontrat->getNomUrl(1, 16); + //if (1 == 1) print img_warning($langs->trans("Late")); print ''; print ''; @@ -449,8 +478,6 @@ if ($resql) { } print ''; print ''; - $staticcompany->id = $obj->fk_soc; - $staticcompany->name = $obj->name; print $staticcompany->getNomUrl(1, '', 20); print ''; print ''; @@ -471,7 +498,7 @@ print '
'; // Not activated services $sql = "SELECT c.ref, c.fk_soc, cd.rowid as cid, cd.statut, cd.label, cd.fk_product, cd.description as note, cd.fk_contrat,"; -$sql .= " s.nom as name,"; +$sql .= " s.nom as name, s.name_alias, s.logo, s.rowid as socid, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; $sql .= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype, p.entity as pentity"; $sql .= " FROM (".MAIN_DB_PREFIX."contrat as c"; $sql .= ", ".MAIN_DB_PREFIX."societe as s"; @@ -507,19 +534,32 @@ if ($resql) { while ($i < $num) { $obj = $db->fetch_object($resql); + $staticcompany->id = $obj->fk_soc; + $staticcompany->name = $obj->name; + $staticcompany->name_alias = $obj->name_alias; + $staticcompany->photo = 1; + $staticcompany->code_client = $obj->code_client; + $staticcompany->code_fournisseur = $obj->code_fournisseur; + $staticcompany->code_compta = $obj->code_compta; + $staticcompany->code_compta_fournisseur = $obj->code_compta_fournisseur; + $staticcompany->client = $obj->client; + $staticcompany->fournisseur = $obj->fournisseur; + + $staticcontrat->ref = ($obj->ref ? $obj->ref : $obj->fk_contrat); + $staticcontrat->id = $obj->fk_contrat; + + $productstatic->id = $obj->fk_product; + $productstatic->type = $obj->ptype; + $productstatic->ref = $obj->pref; + $productstatic->entity = $obj->pentity; + print ''; print ''; - $staticcontrat->ref = ($obj->ref ? $obj->ref : $obj->fk_contrat); - $staticcontrat->id = $obj->fk_contrat; print $staticcontrat->getNomUrl(1, 16); print ''; print ''; if ($obj->fk_product > 0) { - $productstatic->id = $obj->fk_product; - $productstatic->type = $obj->ptype; - $productstatic->ref = $obj->pref; - $productstatic->entity = $obj->pentity; print $productstatic->getNomUrl(1, '', 20); } else { print '
'.img_object($langs->trans("ShowService"), "service"); @@ -531,8 +571,6 @@ if ($resql) { } print ''; print ''; - $staticcompany->id = $obj->fk_soc; - $staticcompany->name = $obj->name; print $staticcompany->getNomUrl(1, '', 20); print ''; print ''; @@ -553,7 +591,7 @@ print '
'; // Expired services $sql = "SELECT c.ref, c.fk_soc, cd.rowid as cid, cd.statut, cd.label, cd.fk_product, cd.description as note, cd.fk_contrat,"; -$sql .= " s.nom as name,"; +$sql .= " s.nom as name, s.name_alias, s.logo, s.rowid as socid, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; $sql .= " p.rowid as pid, p.ref as pref, p.label as plabel, p.fk_product_type as ptype, p.entity as pentity"; $sql .= " FROM (".MAIN_DB_PREFIX."contrat as c"; $sql .= ", ".MAIN_DB_PREFIX."societe as s"; @@ -590,19 +628,32 @@ if ($resql) { while ($i < $num) { $obj = $db->fetch_object($resql); + $staticcompany->id = $obj->fk_soc; + $staticcompany->name = $obj->name; + $staticcompany->name_alias = $obj->name_alias; + $staticcompany->photo = 1; + $staticcompany->code_client = $obj->code_client; + $staticcompany->code_fournisseur = $obj->code_fournisseur; + $staticcompany->code_compta = $obj->code_compta; + $staticcompany->code_compta_fournisseur = $obj->code_compta_fournisseur; + $staticcompany->client = $obj->client; + $staticcompany->fournisseur = $obj->fournisseur; + + $staticcontrat->ref = ($obj->ref ? $obj->ref : $obj->fk_contrat); + $staticcontrat->id = $obj->fk_contrat; + + $productstatic->id = $obj->fk_product; + $productstatic->type = $obj->ptype; + $productstatic->ref = $obj->pref; + $productstatic->entity = $obj->pentity; + print ''; print ''; - $staticcontrat->ref = ($obj->ref ? $obj->ref : $obj->fk_contrat); - $staticcontrat->id = $obj->fk_contrat; print $staticcontrat->getNomUrl(1, 16); print ''; print ''; if ($obj->fk_product > 0) { - $productstatic->id = $obj->fk_product; - $productstatic->type = $obj->ptype; - $productstatic->ref = $obj->pref; - $productstatic->entity = $obj->pentity; print $productstatic->getNomUrl(1, '', 20); } else { print '
'.img_object($langs->trans("ShowService"), "service"); @@ -614,8 +665,6 @@ if ($resql) { } print ''; print ''; - $staticcompany->id = $obj->fk_soc; - $staticcompany->name = $obj->name; print $staticcompany->getNomUrl(1, '', 20); print ''; print ''; From 3026842467387790c57cfb42f4bf3dc78f28fc08 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 11:39:38 +0100 Subject: [PATCH 579/816] trans --- htdocs/langs/en_US/companies.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index d31ecb077ff..38b6892dbae 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -499,5 +499,5 @@ OutOfEurope=Out of Europe (EEC) CurrentOutstandingBillLate=Current outstanding bill late BecarefullChangeThirdpartyBeforeAddProductToInvoice=Be carefull, depending on your product price settings, you should change thirdparty before adding product to POS. EmailAlreadyExistsPleaseRewriteYourCompanyName=email already exists please rewrite your company name -TwoRecordsOfCompanyName=more than one record exists for this company please contact us to complete your partnership request" +TwoRecordsOfCompanyName=more than one record exists for this company, please contact us to complete your partnership request CompanySection=Company section \ No newline at end of file From d842d0394d28db95428f5057dfdd6755a624d23f Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Sun, 15 Jan 2023 12:51:21 +0100 Subject: [PATCH 580/816] Revert "FIX re-open supplier order should not be allowed when there is a reception." This reverts commit c52fab09e608d7eede0ece3f314304db147234d8. --- htdocs/fourn/commande/card.php | 46 ++++++++++++++-------------------- htdocs/langs/en_US/orders.lang | 1 - 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index ffb2e834db7..644469a257d 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -2440,19 +2440,6 @@ if ($action == 'create') { if (empty($reshook)) { $object->fetchObjectLinked(); // Links are used to show or not button, so we load them now. - // check if reception - $hasreception = 0; - if ($conf->reception->enabled) { - if (!empty($object->linkedObjects['reception'])) { - foreach ($object->linkedObjects['reception'] as $element) { - if ($element->statut >= 0) { - $hasreception = 1; - break; - } - } - } - } - // Validate if ($object->statut == 0 && $num > 0) { if ($usercanvalidate) { @@ -2528,21 +2515,17 @@ if ($action == 'create') { // Reopen if (in_array($object->statut, array(CommandeFournisseur::STATUS_ACCEPTED))) { $buttonshown = 0; - if ($hasreception) { - print ''.$langs->trans("Disapprove").''; - } else { - if (!$buttonshown && $usercanapprove) { - if (empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY) - || (!empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY) && $user->id == $object->user_approve_id)) { - print ''.$langs->trans("Disapprove").''; - $buttonshown++; - } + if (!$buttonshown && $usercanapprove) { + if (empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY) + || (!empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER_ONLY) && $user->id == $object->user_approve_id)) { + print ''.$langs->trans("Disapprove").''; + $buttonshown++; } - if (!$buttonshown && $usercanapprovesecond && !empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED)) { - if (empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY) - || (!empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY) && $user->id == $object->user_approve_id2)) { - print ''.$langs->trans("Disapprove").''; - } + } + if (!$buttonshown && $usercanapprovesecond && !empty($conf->global->SUPPLIER_ORDER_3_STEPS_TO_BE_APPROVED)) { + if (empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY) + || (!empty($conf->global->SUPPLIER_ORDER_REOPEN_BY_APPROVER2_ONLY) && $user->id == $object->user_approve_id2)) { + print ''.$langs->trans("Disapprove").''; } } } @@ -2553,10 +2536,19 @@ if ($action == 'create') { } // Ship + $hasreception = 0; if (isModEnabled('stock') && (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE))) { $labelofbutton = $langs->trans('ReceiveProducts'); if ($conf->reception->enabled) { $labelofbutton = $langs->trans("CreateReception"); + if (!empty($object->linkedObjects['reception'])) { + foreach ($object->linkedObjects['reception'] as $element) { + if ($element->statut >= 0) { + $hasreception = 1; + break; + } + } + } } if (in_array($object->statut, array(3, 4, 5))) { diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index 0accaadfa62..f988cd62f19 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -204,4 +204,3 @@ StatusSupplierOrderApproved=Approved StatusSupplierOrderRefused=Refused StatusSupplierOrderReceivedPartially=Partially received StatusSupplierOrderReceivedAll=All products received -NeedAtLeastOneInvoice = There has to be at least one Invoice From f45ec82904c9fc4c0aabe40760535675d687ee20 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Sun, 15 Jan 2023 13:13:49 +0100 Subject: [PATCH 581/816] Disallow line delete if already dispatched --- htdocs/fourn/class/fournisseur.commande.class.php | 13 ++++++++++++- htdocs/langs/en_US/orders.lang | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index a08f2046790..8b539138bfb 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2139,6 +2139,16 @@ class CommandeFournisseur extends CommonOrder return 0; } + // check if not yet received + $dispatchedLines = $this->getDispachedLines(); + foreach ($dispatchedLines as $dispatchLine) { + if ($dispatchLine['orderlineid'] == $idline) { + $this->error = "LineAlreadyDispatched"; + $this->errors[] = $this->error; + return -3; + } + } + if ($line->delete($notrigger) > 0) { $this->update_price(1); return 1; @@ -2327,7 +2337,7 @@ class CommandeFournisseur extends CommonOrder // List of already dispatched lines $sql = "SELECT p.ref, p.label,"; $sql .= " e.rowid as warehouse_id, e.ref as entrepot,"; - $sql .= " cfd.rowid as dispatchedlineid, cfd.fk_product, cfd.qty, cfd.eatby, cfd.sellby, cfd.batch, cfd.comment, cfd.status"; + $sql .= " cfd.rowid as dispatchedlineid, cfd.fk_product, cfd.qty, cfd.eatby, cfd.sellby, cfd.batch, cfd.comment, cfd.status, cfd.fk_commandefourndet"; $sql .= " FROM ".MAIN_DB_PREFIX."product as p,"; $sql .= " ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e ON cfd.fk_entrepot = e.rowid"; @@ -2351,6 +2361,7 @@ class CommandeFournisseur extends CommonOrder 'productid' => $objp->fk_product, 'warehouseid' => $objp->warehouse_id, 'qty' => $objp->qty, + 'orderlineid' => $objp->fk_commandefourndet ); } diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index f988cd62f19..4be2b34fd73 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -204,3 +204,5 @@ StatusSupplierOrderApproved=Approved StatusSupplierOrderRefused=Refused StatusSupplierOrderReceivedPartially=Partially received StatusSupplierOrderReceivedAll=All products received +NeedAtLeastOneInvoice = There has to be at least one Invoice +LineAlreadyDispatched = The order line is already received. \ No newline at end of file From 2d2164550f2744d15ba8a757f532414868edc727 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Jan 2023 20:48:29 +0100 Subject: [PATCH 582/816] Fix warnings --- htdocs/accountancy/customer/index.php | 7 +++++-- htdocs/accountancy/expensereport/index.php | 7 +++++-- htdocs/accountancy/supplier/index.php | 7 +++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 69702d8b10e..5f603a973c2 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -121,6 +121,7 @@ if (($action == 'clean' || $action == 'validatehistory') && $user->hasRight('acc if ($action == 'validatehistory') { $error = 0; $nbbinddone = 0; + $nbbindfailed = 0; $notpossible = 0; $db->begin(); @@ -266,12 +267,14 @@ if ($action == 'validatehistory') { if (!$resqlupdate) { $error++; setEventMessages($db->lasterror(), null, 'errors'); + $nbbindfailed++; break; } else { $nbbinddone++; } } else { $notpossible++; + $nbbindfailed++; } $i++; @@ -286,8 +289,8 @@ if ($action == 'validatehistory') { } else { $db->commit(); setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, ($notpossible ? 'warnings' : 'mesgs')); - if ($notpossible) { - setEventMessages($langs->trans('DoManualBindingForFailedRecord', $notpossible), null, 'warnings'); + if ($nbbindfailed) { + setEventMessages($langs->trans('DoManualBindingForFailedRecord', $nbbindfailed), null, 'warnings'); } } } diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index d256d13252a..0929c9c9e24 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -101,6 +101,7 @@ if (($action == 'clean' || $action == 'validatehistory') && $user->rights->accou if ($action == 'validatehistory') { $error = 0; $nbbinddone = 0; + $nbbindfailed = 0; $notpossible = 0; $db->begin(); @@ -143,12 +144,14 @@ if ($action == 'validatehistory') { if (!$resqlupdate) { $error++; setEventMessages($db->lasterror(), null, 'errors'); + $nbbindfailed++; break; } else { $nbbinddone++; } } else { $notpossible++; + $nbbindfailed++; } $i++; @@ -163,8 +166,8 @@ if ($action == 'validatehistory') { } else { $db->commit(); setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, ($notpossible ? 'warnings' : 'mesgs')); - if ($notpossible) { - setEventMessages($langs->trans('DoManualBindingForFailedRecord', $notpossible), null, 'warnings'); + if ($nbbindfailed) { + setEventMessages($langs->trans('DoManualBindingForFailedRecord', $nbbindfailed), null, 'warnings'); } } } diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index 3e0f4fbd784..87e67bbfcb6 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -119,6 +119,7 @@ if (($action == 'clean' || $action == 'validatehistory') && $user->rights->accou if ($action == 'validatehistory') { $error = 0; $nbbinddone = 0; + $nbbindfailed = 0; $notpossible = 0; $db->begin(); @@ -264,12 +265,14 @@ if ($action == 'validatehistory') { if (!$resqlupdate) { $error++; setEventMessages($db->lasterror(), null, 'errors'); + $nbbindfailed++; break; } else { $nbbinddone++; } } else { $notpossible++; + $nbbindfailed++; } $i++; @@ -284,8 +287,8 @@ if ($action == 'validatehistory') { } else { $db->commit(); setEventMessages($langs->trans('AutomaticBindingDone', $nbbinddone, $notpossible), null, ($notpossible ? 'warnings' : 'mesgs')); - if ($notpossible) { - setEventMessages($langs->trans('DoManualBindingForFailedRecord', $notpossible), null, 'warnings'); + if ($nbbindfailed) { + setEventMessages($langs->trans('DoManualBindingForFailedRecord', $nbbindfailed), null, 'warnings'); } } } From 70f3a6d84701dc212a905a27d4edadf64e440e36 Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sun, 15 Jan 2023 22:53:17 +0100 Subject: [PATCH 583/816] load bom class file. --- htdocs/mrp/mo_list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/mrp/mo_list.php b/htdocs/mrp/mo_list.php index 99e91fec184..c3ae9247c9d 100644 --- a/htdocs/mrp/mo_list.php +++ b/htdocs/mrp/mo_list.php @@ -27,6 +27,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php'; // load mrp libraries require_once __DIR__.'/class/mo.class.php'; From 70bec953075d5f2873bd5a14f4c10f0cb8ec4d1b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Jan 2023 10:44:39 +0100 Subject: [PATCH 584/816] Fix regression test --- htdocs/core/class/hookmanager.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index 7a6af7b88ec..bcd5a506946 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -164,7 +164,7 @@ class HookManager // Define type of hook ('output' or 'addreplace'). $hooktype = 'addreplace'; // TODO Remove hooks with type 'output' (exemple createFrom). All hooks must be converted into 'addreplace' hooks. - if (!in_array($method, array( + if (in_array($method, array( 'createFrom', 'dashboardMembers', 'dashboardEmailings', From acc30da1fe2c25e221d01b6f5e5876aacf30a7e9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Jan 2023 10:57:31 +0100 Subject: [PATCH 585/816] Fix do not change password if same --- .../triggers/interface_50_modAgenda_ActionsAuto.class.php | 2 +- htdocs/langs/en_US/users.lang | 3 ++- htdocs/user/card.php | 2 +- htdocs/user/class/user.class.php | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index be78b6ecc18..ae53b01e19b 100644 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php @@ -931,7 +931,7 @@ class InterfaceActionsAuto extends DolibarrTriggers $object->sendtoid = 0; } else { // TODO Merge all previous cases into this generic one - // $action = BILL_DELETE, TICKET_CREATE, TICKET_MODIFY, TICKET_DELETE, CONTACT_SENTBYMAIL, RECRUITMENTCANDIDATURE_MODIFY, ... + // $action = PASSWORD, BILL_DELETE, TICKET_CREATE, TICKET_MODIFY, TICKET_DELETE, CONTACT_SENTBYMAIL, RECRUITMENTCANDIDATURE_MODIFY, ... // Can also be a value defined by an external module like SENTBYSMS, COMPANY_SENTBYSMS, MEMBER_SENTBYSMS, ... // Note: We are here only if $conf->global->MAIN_AGENDA_ACTIONAUTO_action is on (tested at begining of this function). // Note that these key can be set in agenda setup, only if defined into llx_c_action_trigger diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index 2f691153292..05c9ebb339d 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -66,7 +66,8 @@ LinkedToDolibarrUser=Link to user LinkedToDolibarrThirdParty=Link to third party CreateDolibarrLogin=Create a user CreateDolibarrThirdParty=Create a third party -LoginAccountDisableInDolibarr=Account disabled in Dolibarr. +LoginAccountDisableInDolibarr=Account disabled in Dolibarr +PASSWORDInDolibarr=Password modified in Dolibarr UsePersonalValue=Use personal value ExportDataset_user_1=Users and their properties DomainUser=Domain user %s diff --git a/htdocs/user/card.php b/htdocs/user/card.php index ea47ba10beb..b7254def46a 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -521,7 +521,7 @@ if (empty($reshook)) { } if (!$error) { - $ret = $object->update($user); + $ret = $object->update($user); // This may include call to setPassword if password has changed if ($ret < 0) { $error++; if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 7e342e64337..d7b93d323e1 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2031,9 +2031,9 @@ class User extends CommonObject // Update password if (!empty($this->pass)) { - if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) { + if ($this->pass != $this->pass_indatabase && !dol_verifyHash($this->pass, $this->pass_indatabase_crypted)) { // If a new value for password is set and different than the one crypted into database - $result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass); + $result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass, 0, 1); if ($result < 0) { return -5; } From 5867b6249661cbd15873e4ec3a9a63a8ffb772c9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Jan 2023 10:57:31 +0100 Subject: [PATCH 586/816] Fix do not change password if same --- .../triggers/interface_50_modAgenda_ActionsAuto.class.php | 2 +- htdocs/langs/en_US/users.lang | 3 ++- htdocs/user/card.php | 2 +- htdocs/user/class/user.class.php | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index e3f798dec62..686f59a70c7 100644 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php @@ -920,7 +920,7 @@ class InterfaceActionsAuto extends DolibarrTriggers $object->sendtoid = 0; } else { // TODO Merge all previous cases into this generic one - // $action = BILL_DELETE, TICKET_CREATE, TICKET_MODIFY, TICKET_DELETE, CONTACT_SENTBYMAIL, RECRUITMENTCANDIDATURE_MODIFY, ... + // $action = PASSWORD, BILL_DELETE, TICKET_CREATE, TICKET_MODIFY, TICKET_DELETE, CONTACT_SENTBYMAIL, RECRUITMENTCANDIDATURE_MODIFY, ... // Can also be a value defined by an external module like SENTBYSMS, COMPANY_SENTBYSMS, MEMBER_SENTBYSMS, ... // Note: We are here only if $conf->global->MAIN_AGENDA_ACTIONAUTO_action is on (tested at begining of this function). // Note that these key can be set in agenda setup, only if defined into llx_c_action_trigger diff --git a/htdocs/langs/en_US/users.lang b/htdocs/langs/en_US/users.lang index 757e9f1dedf..cfd8cbb0362 100644 --- a/htdocs/langs/en_US/users.lang +++ b/htdocs/langs/en_US/users.lang @@ -66,7 +66,8 @@ LinkedToDolibarrUser=Link to user LinkedToDolibarrThirdParty=Link to third party CreateDolibarrLogin=Create a user CreateDolibarrThirdParty=Create a third party -LoginAccountDisableInDolibarr=Account disabled in Dolibarr. +LoginAccountDisableInDolibarr=Account disabled in Dolibarr +PASSWORDInDolibarr=Password modified in Dolibarr UsePersonalValue=Use personal value ExportDataset_user_1=Users and their properties DomainUser=Domain user %s diff --git a/htdocs/user/card.php b/htdocs/user/card.php index aa8460ec9d5..775a4db05dc 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -516,7 +516,7 @@ if (empty($reshook)) { } if (!$error) { - $ret = $object->update($user); + $ret = $object->update($user); // This may include call to setPassword if password has changed if ($ret < 0) { $error++; if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index e90252877d1..1f179758d57 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2032,9 +2032,9 @@ class User extends CommonObject // Update password if (!empty($this->pass)) { - if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) { + if ($this->pass != $this->pass_indatabase && !dol_verifyHash($this->pass, $this->pass_indatabase_crypted)) { // If a new value for password is set and different than the one crypted into database - $result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass); + $result = $this->setPassword($user, $this->pass, 0, $notrigger, $nosyncmemberpass, 0, 1); if ($result < 0) { return -5; } From f2f4cdbe6ab8381efa86db1c7dd5eda37e79e554 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Jan 2023 11:48:34 +0100 Subject: [PATCH 587/816] NEW Invalidate all sessions of a user when password is modified. --- htdocs/core/login/functions_dolibarr.php | 12 ------------ htdocs/langs/en_US/errors.lang | 2 ++ htdocs/main.inc.php | 21 +++++++++++++++------ htdocs/user/card.php | 14 ++++++++++++++ htdocs/user/class/user.class.php | 3 +++ 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/htdocs/core/login/functions_dolibarr.php b/htdocs/core/login/functions_dolibarr.php index b732d2ef64b..5f4b722ea1c 100644 --- a/htdocs/core/login/functions_dolibarr.php +++ b/htdocs/core/login/functions_dolibarr.php @@ -91,18 +91,6 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes dol_syslog("functions_dolibarr::check_user_password_dolibarr bad date end validity", LOG_WARNING); return '--bad-login-validity--'; } - // If there is an invalidation date, check that the current session date is not before this date - if ($obj->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"])) { - dol_syslog("functions_dolibarr::check_user_password_dolibarr user has a date for session invalidation = ".$obj->flagdelsessionsbefore." and session date = ".$_SESSION["dol_logindate"]); - $datetmp = $db->jdate($obj->flagdelsessionsbefore, 'gmt'); - if ($datetmp > $now) { - // Load translation files required by the page - $langs->loadLangs(array('main', 'errors')); - $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorSessionInvalidatedAfterPasswordChange"); - dol_syslog("functions_dolibarr::check_user_password_dolibarr session was invalidated", LOG_WARNING); - return '--bad-login-validity--'; - } - } $passclear = $obj->pass; $passcrypted = $obj->pass_crypted; diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index b3eeae4606b..b779c901b54 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -303,6 +303,7 @@ ErrorValueForTooLow=Value for %s is too low ErrorValueCantBeNull=Value for %s can't be null ErrorDateOfMovementLowerThanDateOfFileTransmission=The date of the bank transaction can't be lower than the date of the file transmission ErrorTooMuchFileInForm=Too much files in form, the maximum number is %s file(s) +ErrorSessionInvalidatedAfterPasswordChange=The session was invalidated after a password change. Please relogin. # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. @@ -325,6 +326,7 @@ WarningPaymentDateLowerThanInvoiceDate=Payment date (%s) is earlier than invoice WarningTooManyDataPleaseUseMoreFilters=Too many data (more than %s lines). Please use more filters or set the constant %s to a higher limit. WarningSomeLinesWithNullHourlyRate=Some times were recorded by some users while their hourly rate was not defined. A value of 0 %s per hour was used but this may result in wrong valuation of time spent. WarningYourLoginWasModifiedPleaseLogin=Your login was modified. For security purpose you will have to login with your new login before next action. +WarningYourPasswordWasModifiedPleaseLogin=Your password was modified. For security purpose you will have to login now with your new password. WarningAnEntryAlreadyExistForTransKey=An entry already exists for the translation key for this language WarningNumberOfRecipientIsRestrictedInMassAction=Warning, number of different recipient is limited to %s when using the mass actions on lists WarningDateOfLineMustBeInExpenseReportRange=Warning, the date of line is not in the range of the expense report diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 7d764d4a105..b53688de6e7 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -943,26 +943,35 @@ if (!defined('NOLOGIN')) { dol_syslog("- This is an already logged session. _SESSION['dol_login']=".$login." _SESSION['dol_entity']=".$entity, LOG_DEBUG); $resultFetchUser = $user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1)); - if ($resultFetchUser <= 0) { - // Account has been removed after login - dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING); + if ($resultFetchUser <= 0 || ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"])) { + if ($resultFetchUser <= 0) { + // Account has been removed after login + dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING); + } else { + // Session is no more valid + dol_syslog("The user has a date for session invalidation = ".$user->flagdelsessionsbefore." and a session date = ".$_SESSION["dol_logindate"].". We must invalidate its sessions."); + } session_destroy(); session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie session_name($sessionname); session_start(); if ($resultFetchUser == 0) { - // Load translation files required by page $langs->loadLangs(array('main', 'errors')); $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorCantLoadUserFromDolibarrDatabase", $login); $user->trigger_mesg = 'ErrorCantLoadUserFromDolibarrDatabase - login='.$login; - } - if ($resultFetchUser < 0) { + } elseif ($resultFetchUser < 0) { $_SESSION["dol_loginmesg"] = $user->error; $user->trigger_mesg = $user->error; + } else { + $langs->loadLangs(array('main', 'errors')); + + $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorSessionInvalidatedAfterPasswordChange"); + + $user->trigger_mesg = 'ErrorUserSessionWasInvalidated - login='.$login; } // Call trigger diff --git a/htdocs/user/card.php b/htdocs/user/card.php index b7254def46a..602bc25eb3a 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -521,6 +521,13 @@ if (empty($reshook)) { } if (!$error) { + $passwordismodified = 0; + if (!empty($object->pass)) { + if ($object->pass != $object->pass_indatabase && !dol_verifyHash($object->pass, $object->pass_indatabase_crypted)) { + $passwordismodified = 1; + } + } + $ret = $object->update($user); // This may include call to setPassword if password has changed if ($ret < 0) { $error++; @@ -615,6 +622,13 @@ if (empty($reshook)) { $langs->load("errors"); setEventMessages($langs->transnoentitiesnoconv("WarningYourLoginWasModifiedPleaseLogin"), null, 'warnings'); } + if ($passwordismodified && $object->login == $user->login) { // Current user has changed its password + $error++; + $langs->load("errors"); + setEventMessages($langs->transnoentitiesnoconv("WarningYourPasswordWasModifiedPleaseLogin"), null, 'warnings'); + header("Location: ".DOL_URL_ROOT.'/user/card.php?id='.$object->id); + exit; + } } else { $db->rollback(); } diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index d7b93d323e1..22556d3e1c2 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -276,6 +276,7 @@ class User extends CommonObject public $datelastlogin; public $datepreviouslogin; + public $flagdelsessionsbefore; public $iplastlogin; public $ippreviouslogin; public $datestartvalidity; @@ -441,6 +442,7 @@ class User extends CommonObject $sql .= " u.tms as datem,"; $sql .= " u.datelastlogin as datel,"; $sql .= " u.datepreviouslogin as datep,"; + $sql .= " u.flagdelsessionsbefore,"; $sql .= " u.iplastlogin,"; $sql .= " u.ippreviouslogin,"; $sql .= " u.datelastpassvalidation,"; @@ -575,6 +577,7 @@ class User extends CommonObject $this->datem = $this->db->jdate($obj->datem); $this->datelastlogin = $this->db->jdate($obj->datel); $this->datepreviouslogin = $this->db->jdate($obj->datep); + $this->flagdelsessionsbefore = $this->db->jdate($obj->flagdelsessionsbefore, 'gmt'); $this->iplastlogin = $obj->iplastlogin; $this->ippreviouslogin = $obj->ippreviouslogin; $this->datestartvalidity = $this->db->jdate($obj->datestartvalidity); From 6af49ff2165712d4789d2265c2b6927d803f46fd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Jan 2023 12:33:54 +0100 Subject: [PATCH 588/816] Fix warning php8 --- htdocs/main.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index b53688de6e7..2904f576bf7 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -984,7 +984,7 @@ if (!defined('NOLOGIN')) { // Hooks on failed login $action = ''; $hookmanager->initHooks(array('login')); - $parameters = array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]); + $parameters = array('dol_authmode' => (isset($dol_authmode) ? $dol_authmode : ''), 'dol_loginmesg' => $_SESSION["dol_loginmesg"]); $reshook = $hookmanager->executeHooks('afterLoginFailed', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { $error++; From 3fc2f9273d02a2104210546b36ac3ec69902091c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Jan 2023 12:33:54 +0100 Subject: [PATCH 589/816] Fix warning php8 --- htdocs/main.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 1188dd023ab..2ed8b1a012f 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -975,7 +975,7 @@ if (!defined('NOLOGIN')) { // Hooks on failed login $action = ''; $hookmanager->initHooks(array('login')); - $parameters = array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]); + $parameters = array('dol_authmode' => (isset($dol_authmode) ? $dol_authmode : ''), 'dol_loginmesg' => $_SESSION["dol_loginmesg"]); $reshook = $hookmanager->executeHooks('afterLoginFailed', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { $error++; From 481215eef45175bafcada49258666abd7a2ec2f1 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Mon, 16 Jan 2023 14:40:35 +0100 Subject: [PATCH 590/816] FIX Multicompany use "element" name and not "table_element" --- htdocs/asset/class/asset.class.php | 2 +- htdocs/asset/class/assetmodel.class.php | 2 +- htdocs/bom/class/bom.class.php | 4 ++-- htdocs/core/class/commonobject.class.php | 2 +- htdocs/eventorganization/class/conferenceorbooth.class.php | 2 +- .../class/conferenceorboothattendee.class.php | 2 +- htdocs/hrm/class/evaluation.class.php | 2 +- htdocs/hrm/class/evaluationdet.class.php | 2 +- htdocs/hrm/class/job.class.php | 2 +- htdocs/hrm/class/position.class.php | 2 +- htdocs/hrm/class/skill.class.php | 2 +- htdocs/hrm/class/skilldet.class.php | 2 +- htdocs/hrm/class/skillrank.class.php | 2 +- htdocs/knowledgemanagement/class/knowledgerecord.class.php | 2 +- htdocs/mrp/class/mo.class.php | 4 ++-- htdocs/partnership/class/partnership.class.php | 2 +- htdocs/partnership/class/partnership_type.class.php | 2 +- .../product/stock/stocktransfer/class/stocktransfer.class.php | 2 +- .../stock/stocktransfer/class/stocktransferline.class.php | 2 +- htdocs/recruitment/class/recruitmentcandidature.class.php | 2 +- htdocs/recruitment/class/recruitmentjobposition.class.php | 2 +- htdocs/ticket/class/cticketcategory.class.php | 2 +- htdocs/webhook/class/target.class.php | 2 +- htdocs/workstation/class/workstation.class.php | 2 +- 24 files changed, 26 insertions(+), 26 deletions(-) diff --git a/htdocs/asset/class/asset.class.php b/htdocs/asset/class/asset.class.php index 7c2b55c045e..c01f4b967c4 100644 --- a/htdocs/asset/class/asset.class.php +++ b/htdocs/asset/class/asset.class.php @@ -410,7 +410,7 @@ class Asset extends CommonObject $sql .= $this->getFieldList('t'); $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= " WHERE t.entity IN (".getEntity($this->table_element).")"; + $sql .= " WHERE t.entity IN (".getEntity($this->element).")"; } else { $sql .= " WHERE 1 = 1"; } diff --git a/htdocs/asset/class/assetmodel.class.php b/htdocs/asset/class/assetmodel.class.php index fb574e6ea18..a973abc3764 100644 --- a/htdocs/asset/class/assetmodel.class.php +++ b/htdocs/asset/class/assetmodel.class.php @@ -348,7 +348,7 @@ class AssetModel extends CommonObject $sql .= $this->getFieldList('t'); $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= " WHERE t.entity IN (".getEntity($this->table_element).")"; + $sql .= " WHERE t.entity IN (".getEntity($this->element).")"; } else { $sql .= " WHERE 1 = 1"; } diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index cd5b119cabf..b819e438161 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -476,7 +476,7 @@ class BOM extends CommonObject $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if ($this->ismultientitymanaged) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } @@ -1736,7 +1736,7 @@ class BOMLine extends CommonObjectLine $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if ($this->ismultientitymanaged) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index f1920c74931..471d835f4a3 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -9331,7 +9331,7 @@ abstract class CommonObject $sql .= ' WHERE 1 = 1'; // usage with empty id and empty ref is very rare } if (empty($id) && isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' AND t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' AND t.entity IN ('.getEntity($this->element).')'; } if ($morewhere) { $sql .= $morewhere; diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index db0928efc7d..bc21d7bb1c5 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -284,7 +284,7 @@ class ConferenceOrBooth extends ActionComm $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."c_actioncomm as cact ON cact.id=t.fk_action AND cact.module LIKE '%@eventorganization'"; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/eventorganization/class/conferenceorboothattendee.class.php b/htdocs/eventorganization/class/conferenceorboothattendee.class.php index 595eaf67eeb..be06f70979e 100644 --- a/htdocs/eventorganization/class/conferenceorboothattendee.class.php +++ b/htdocs/eventorganization/class/conferenceorboothattendee.class.php @@ -423,7 +423,7 @@ class ConferenceOrBoothAttendee extends CommonObject $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."actioncomm as a on a.id = t.fk_actioncomm"; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/hrm/class/evaluation.class.php b/htdocs/hrm/class/evaluation.class.php index 23ccc6c9fd2..51f8c8bc985 100644 --- a/htdocs/hrm/class/evaluation.class.php +++ b/htdocs/hrm/class/evaluation.class.php @@ -404,7 +404,7 @@ class Evaluation extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/hrm/class/evaluationdet.class.php b/htdocs/hrm/class/evaluationdet.class.php index 5489065e52d..50d2fac8821 100644 --- a/htdocs/hrm/class/evaluationdet.class.php +++ b/htdocs/hrm/class/evaluationdet.class.php @@ -373,7 +373,7 @@ class Evaluationline extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php index 93950979a1a..076e223679d 100644 --- a/htdocs/hrm/class/job.class.php +++ b/htdocs/hrm/class/job.class.php @@ -374,7 +374,7 @@ class Job extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index 98b5fd89be9..b685147a9b9 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -385,7 +385,7 @@ class Position extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN (' . getEntity($this->table_element) . ')'; + $sql .= ' WHERE t.entity IN (' . getEntity($this->element) . ')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/hrm/class/skill.class.php b/htdocs/hrm/class/skill.class.php index 3f56294a7b2..ec994a35746 100644 --- a/htdocs/hrm/class/skill.class.php +++ b/htdocs/hrm/class/skill.class.php @@ -443,7 +443,7 @@ class Skill extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/hrm/class/skilldet.class.php b/htdocs/hrm/class/skilldet.class.php index 4dface42230..3db74d26da1 100644 --- a/htdocs/hrm/class/skilldet.class.php +++ b/htdocs/hrm/class/skilldet.class.php @@ -366,7 +366,7 @@ class Skilldet extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/hrm/class/skillrank.class.php b/htdocs/hrm/class/skillrank.class.php index 2d75425823e..a08a647ca03 100644 --- a/htdocs/hrm/class/skillrank.class.php +++ b/htdocs/hrm/class/skillrank.class.php @@ -405,7 +405,7 @@ class SkillRank extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/knowledgemanagement/class/knowledgerecord.class.php b/htdocs/knowledgemanagement/class/knowledgerecord.class.php index bf2bf38bbef..1cdb3aff9f5 100644 --- a/htdocs/knowledgemanagement/class/knowledgerecord.class.php +++ b/htdocs/knowledgemanagement/class/knowledgerecord.class.php @@ -381,7 +381,7 @@ class KnowledgeRecord extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 13d0f67316c..68523ace9da 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -451,7 +451,7 @@ class Mo extends CommonObject $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } @@ -1717,7 +1717,7 @@ class MoLine extends CommonObjectLine $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index d7242f4e16c..a9645efaae2 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -483,7 +483,7 @@ class Partnership extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/partnership/class/partnership_type.class.php b/htdocs/partnership/class/partnership_type.class.php index 0c42dae87d2..ba0f2c2a1ab 100644 --- a/htdocs/partnership/class/partnership_type.class.php +++ b/htdocs/partnership/class/partnership_type.class.php @@ -168,7 +168,7 @@ class PartnershipType extends CommonObject $sql .= $this->getFieldList('t'); $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= " WHERE t.entity IN (".getEntity($this->table_element).")"; + $sql .= " WHERE t.entity IN (".getEntity($this->element).")"; } else { $sql .= " WHERE 1 = 1"; } diff --git a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php index 60f13396b80..0711815da15 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php @@ -428,7 +428,7 @@ class StockTransfer extends CommonObject $sql = 'SELECT '; $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; - if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; else $sql .= ' WHERE 1 = 1'; // Manage filter $sqlwhere = array(); diff --git a/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php b/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php index 4ee2f1db631..0460430c337 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php @@ -338,7 +338,7 @@ class StockTransferLine extends CommonObjectLine $sql = 'SELECT '; $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; - if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; else $sql .= ' WHERE 1 = 1'; // Manage filter $sqlwhere = array(); diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index 1690f13da56..25d8b352a81 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -374,7 +374,7 @@ class RecruitmentCandidature extends CommonObject $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/recruitment/class/recruitmentjobposition.class.php b/htdocs/recruitment/class/recruitmentjobposition.class.php index 7a9d077f910..6b3fcf7eeb8 100644 --- a/htdocs/recruitment/class/recruitmentjobposition.class.php +++ b/htdocs/recruitment/class/recruitmentjobposition.class.php @@ -391,7 +391,7 @@ class RecruitmentJobPosition extends CommonObject $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/ticket/class/cticketcategory.class.php b/htdocs/ticket/class/cticketcategory.class.php index dd8b75292ad..334ea7cd1ab 100644 --- a/htdocs/ticket/class/cticketcategory.class.php +++ b/htdocs/ticket/class/cticketcategory.class.php @@ -384,7 +384,7 @@ class CTicketCategory extends CommonObject $sql .= $this->getFieldList('t'); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } diff --git a/htdocs/webhook/class/target.class.php b/htdocs/webhook/class/target.class.php index 51a2a1beffa..701c74fbf4d 100644 --- a/htdocs/webhook/class/target.class.php +++ b/htdocs/webhook/class/target.class.php @@ -385,7 +385,7 @@ class Target extends CommonObject $sql .= $this->getFieldList('t'); $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= " WHERE t.entity IN (".getEntity($this->table_element).")"; + $sql .= " WHERE t.entity IN (".getEntity($this->element).")"; } else { $sql .= " WHERE 1 = 1"; } diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php index d3b098784da..58f326e3749 100644 --- a/htdocs/workstation/class/workstation.class.php +++ b/htdocs/workstation/class/workstation.class.php @@ -419,7 +419,7 @@ class Workstation extends CommonObject $sql .= $this->getFieldList(); $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { - $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')'; } else { $sql .= ' WHERE 1 = 1'; } From 20633aa7747bfb38aa508839515585e19c9b3025 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 16 Jan 2023 15:03:01 +0100 Subject: [PATCH 591/816] fix checkbox by mergin two class --- htdocs/hrm/class/job.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php index 85845e557ab..fdeebe484eb 100644 --- a/htdocs/hrm/class/job.class.php +++ b/htdocs/hrm/class/job.class.php @@ -1071,7 +1071,7 @@ class Job extends CommonObject $return .= ''; $return .= '
'; $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; - $return .= ''; + $return .= ''; if (property_exists($this, 'deplacement')) { $return .= '
'.$langs->trans("Type").''; $return .= ' : '.$this->fields['deplacement']['arrayofkeyval'][$this->deplacement].''; From 902351cbaa2d15b4f050509e506ec8e2288f3738 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Jan 2023 15:45:17 +0100 Subject: [PATCH 592/816] Fix phpunit --- test/phpunit/UserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index f318ae4cbac..9963007af15 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -204,7 +204,7 @@ class UserTest extends PHPUnit\Framework\TestCase $newlocalobject=new User($this->savdb); $newlocalobject->initAsSpecimen(); $this->changeProperties($newlocalobject); - $this->assertEquals($this->objCompare($localobject, $newlocalobject, true, array('id','socid','societe_id','specimen','note','ref','pass','pass_indatabase','pass_indatabase_crypted','pass_temp','datec','datem','datelastlogin','datepreviouslogin','iplastlogin','ippreviouslogin','trackid')), array()); // Actual, Expected + $this->assertEquals($this->objCompare($localobject, $newlocalobject, true, array('id','socid','societe_id','specimen','note','ref','pass','pass_indatabase','pass_indatabase_crypted','pass_temp','datec','datem','datelastlogin','datepreviouslogin','flagdelsessionsbefore','iplastlogin','ippreviouslogin','trackid')), array()); // Actual, Expected return $localobject; } From 6983ef95846949955b5591ca918de5b353cab546 Mon Sep 17 00:00:00 2001 From: lamrani abdelwadoud Date: Mon, 16 Jan 2023 15:53:57 +0100 Subject: [PATCH 593/816] Update product.class.php fix style error --- htdocs/product/class/product.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 96e3ac7c7f5..b0882e95632 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -6291,7 +6291,6 @@ class Product extends CommonObject $return .= '
'; $return .= '
'; $label = ''; - if ($this->is_photo_available($conf->product->multidir_output[$this->entity])) { $label .= $this->show_photos('product', $conf->product->multidir_output[$this->entity]); $return .= $label; @@ -6303,7 +6302,6 @@ class Product extends CommonObject } $return .= $label; } - $return .= '
'; $return .= '
'; $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; From 690646b7da0d151a1662f7333a9b462cfb915e3c Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 16 Jan 2023 16:12:27 +0100 Subject: [PATCH 594/816] fix errors in info-box.css --- htdocs/theme/eldy/info-box.inc.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/htdocs/theme/eldy/info-box.inc.php b/htdocs/theme/eldy/info-box.inc.php index 5c010e21e26..99e8e5e2ca1 100644 --- a/htdocs/theme/eldy/info-box.inc.php +++ b/htdocs/theme/eldy/info-box.inc.php @@ -491,12 +491,9 @@ if (GETPOSTISSET('THEME_SATURATE_RATIO')) { min-width: 350px; max-width: 350px; } - -/**for make a checkbox in the right of the box in mode kanban */ .fright { float:right; } - @media only screen and (max-width: 1740px) { .info-box-module { min-width: 315px; From 6f93cac359f875dd97cead8973135ad1f4548e5d Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 16 Jan 2023 17:10:26 +0100 Subject: [PATCH 595/816] fix style error --- htdocs/loan/list.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/loan/list.php b/htdocs/loan/list.php index 5acd2532bef..1225f5304be 100644 --- a/htdocs/loan/list.php +++ b/htdocs/loan/list.php @@ -66,8 +66,7 @@ $search_amount = GETPOST('search_amount', 'alpha'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'loanlist'; // To manage different context of search $optioncss = GETPOST('optioncss', 'alpha'); -$mode = GETPOST('mode', 'alpha'); // mode view result - +$mode = GETPOST('mode', 'alpha'); // mode view result /* From 931ce8be4a78871015e723839400b19b1e1d97bd Mon Sep 17 00:00:00 2001 From: marc Date: Mon, 16 Jan 2023 18:06:23 +0100 Subject: [PATCH 596/816] NEW #23436 Group social networks field Group social networks field on a thirdparty creation into one link --- htdocs/contact/card.php | 75 ++++++++++++++++++++++++---------------- htdocs/societe/card.php | 76 +++++++++++++++++++++++++---------------- 2 files changed, 91 insertions(+), 60 deletions(-) diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 6cf7d3051f3..e0c263572cb 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -864,21 +864,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if (isModEnabled('socialnetworks')) { - foreach ($socialnetworks as $key => $value) { - if ($value['active']) { - print ''; - print ''; - print ''; - if (!empty($value['icon'])) { - print ''; - } - print ''; - print ''; - print ''; - } elseif (!empty($object->socialnetworks[$key])) { - print ''; - } - } + showSocialNetwork(); } // Visibility @@ -1151,21 +1137,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } if (isModEnabled('socialnetworks')) { - foreach ($socialnetworks as $key => $value) { - if ($value['active']) { - print ''; - print ''; - print ''; - if (!empty($value['icon'])) { - print ''; - } - print ''; - print ''; - print ''; - } elseif (!empty($object->socialnetworks[$key])) { - print ''; - } - } + showSocialNetwork(); } // Visibility @@ -1620,6 +1592,49 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } } +function showSocialNetwork() { + global $socialnetworks, $object, $form, $object, $langs; + echo ''; + + print ' '; + foreach ($socialnetworks as $key => $value) { + if ($value['active']) { + print ''; + print ''; + print ''; + if (!empty($value['icon'])) { + print ''; + } + print ''; + print ''; + print ''; + } elseif (!empty($object->socialnetworks[$key])) { + print ''; + } + } + + print ''; +} + llxFooter(); diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 8b5dcd251d2..2d6356394dd 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1663,21 +1663,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Social networks if (isModEnabled('socialnetworks')) { - foreach ($socialnetworks as $key => $value) { - if ($value['active']) { - print ''; - print ''; - print ''; - if (!empty($value['icon'])) { - print ''; - } - print ''; - print ''; - print ''; - } elseif (!empty($object->socialnetworks[$key])) { - print ''; - } - } + showSocialNetwork(); } // Prof ids @@ -2395,21 +2381,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Social network if (isModEnabled('socialnetworks')) { - foreach ($socialnetworks as $key => $value) { - if ($value['active']) { - print ''; - print ''; - print ''; - if (!empty($value['icon'])) { - print ''; - } - print ''; - print ''; - print ''; - } elseif (!empty($object->socialnetworks[$key])) { - print ''; - } - } + showSocialNetwork(); } // Prof ids @@ -3326,6 +3298,50 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; } } + +function showSocialNetwork() { + global $socialnetworks, $object, $form, $object, $langs; + echo ''; + + print ' '; + foreach ($socialnetworks as $key => $value) { + if ($value['active']) { + print ''; + print ''; + print ''; + if (!empty($value['icon'])) { + print ''; + } + print ''; + print ''; + print ''; + } elseif (!empty($object->socialnetworks[$key])) { + print ''; + } + } + + print ''; +} + // End of page llxFooter(); $db->close(); From b2df3e47f84c87388590fb77dfb401a8916b9670 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 16 Jan 2023 17:09:34 +0000 Subject: [PATCH 597/816] Fixing style errors. --- htdocs/contact/card.php | 3 ++- htdocs/societe/card.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index e0c263572cb..8c061020dc3 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -1592,7 +1592,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } } -function showSocialNetwork() { +function showSocialNetwork() +{ global $socialnetworks, $object, $form, $object, $langs; echo ''; diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 2d6356394dd..f06a4c14eee 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -3299,7 +3299,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } } -function showSocialNetwork() { +function showSocialNetwork() +{ global $socialnetworks, $object, $form, $object, $langs; echo ''; From 9b164b907c1a9e9b641ff7bd9d4c308e9e36ba83 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Mon, 16 Jan 2023 19:25:54 +0100 Subject: [PATCH 598/816] Add warehouse modify and create triggers. Clean and remove deprecated vars. --- htdocs/product/stock/class/entrepot.class.php | 52 ++++++++++++------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index 065883e7a2c..ce5bef9c939 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -182,16 +182,17 @@ class Entrepot extends CommonObject /** * Creation d'un entrepot en base * - * @param User $user Object user that create the warehouse + * @param User $user Object user that create the warehouse + * @param bool $notrigger false=launch triggers after, true=disable triggers * @return int >0 if OK, =<0 if KO */ - public function create($user) + public function create($user, $notrigger = false) { global $conf; $error = 0; - $this->label = trim(!empty($this->label) ? $this->label : $this->libelle); + $this->label = trim($this->label); // Error if label not defined if ($this->label == '') { @@ -222,14 +223,21 @@ class Entrepot extends CommonObject // Actions on extra fields if (!$error) { - if (!$error) { - $result = $this->insertExtraFields(); - if ($result < 0) { - $error++; - } + $result = $this->insertExtraFields(); + if ($result < 0) { + $error++; } } + if (!$error && !$notrigger) { + // Call triggers + $result = $this->call_trigger('WAREHOUSE_CREATE', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + if (!$error) { $this->db->commit(); return $id; @@ -254,11 +262,12 @@ class Entrepot extends CommonObject /** * Update properties of a warehouse * - * @param int $id id of warehouse to modify - * @param User $user User object + * @param int $id id of warehouse to modify + * @param User $user User object + * @param bool $notrigger false=launch triggers after, true=disable trigge * @return int >0 if OK, <0 if KO */ - public function update($id, $user) + public function update($id, $user, $notrigger = false) { global $conf; @@ -267,9 +276,6 @@ class Entrepot extends CommonObject if (empty($id)) { $id = $this->id; } - if (empty($this->label)) { - $this->label = $this->libelle; // For backward compatibility - } // Check if new parent is already a child of current warehouse if (!empty($this->fk_parent)) { @@ -281,7 +287,7 @@ class Entrepot extends CommonObject } } - $this->label = trim(!empty($this->label) ? $this->label : $this->libelle); + $this->label = trim($this->label); $this->description = trim($this->description); @@ -324,6 +330,15 @@ class Entrepot extends CommonObject } } + if (!$error && !$notrigger) { + // Call triggers + $result = $this->call_trigger('WAREHOUSE_MODIFY', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + if (!$error) { $this->db->commit(); return 1; @@ -461,7 +476,6 @@ class Entrepot extends CommonObject $this->fk_project = $obj->fk_project; $this->ref = $obj->label; $this->label = $obj->label; - $this->libelle = $obj->label; // deprecated $this->description = $obj->description; $this->statut = $obj->statut; $this->lieu = $obj->lieu; @@ -705,7 +719,7 @@ class Entrepot extends CommonObject if (isset($this->statut)) { $label .= ' '.$this->getLibStatut(5); } - $label .= '
'.$langs->trans('Ref').': '.(empty($this->ref) ? (empty($this->label) ? $this->libelle : $this->label) : $this->ref); + $label .= '
'.$langs->trans('Ref').': '.(empty($this->ref) ? $this->label : $this->ref); if (!empty($this->lieu)) { $label .= '
'.$langs->trans('LocationSummary').': '.$this->lieu; } @@ -742,7 +756,7 @@ class Entrepot extends CommonObject $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); } if ($withpicto != 2) { - $result .= (($showfullpath || !empty($conf->global->STOCK_ALWAYS_SHOW_FULL_ARBO)) ? $this->get_full_arbo() : (empty($this->label) ? $this->libelle : $this->label)); + $result .= (($showfullpath || !empty($conf->global->STOCK_ALWAYS_SHOW_FULL_ARBO)) ? $this->get_full_arbo() : $this->label); } $result .= $linkend; @@ -798,7 +812,7 @@ class Entrepot extends CommonObject // phpcs:enable global $user, $langs, $conf; - $TArbo = array(empty($this->label) ? $this->libelle : $this->label); + $TArbo = array($this->label); $protection = 100; // We limit depth of warehouses to 100 From 73f4b80a0588a787f55e786dbc6b8f8062519d7c Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Mon, 16 Jan 2023 19:47:32 +0100 Subject: [PATCH 599/816] Update changelog for removed libelle --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 1a3e96b18ce..fe39e1c1497 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ Following changes may create regressions for some external modules, but were nec * The deprecated method "escapeunderscore()" of database handlers has been removed. You must use "escapeforlike()" instead. * The method "nb_expedition()" has been renamed into "countNbOfShipments()" * Revert default type of hooks. Default is now 'addreplace' hooks (and exception become 'output' hooks, that become deprecated). +* Deprecated property libelle removed from entrepot class. From 4cf4da973cac0cda9ca70558f8020c683fcf32f5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Jan 2023 20:38:03 +0100 Subject: [PATCH 600/816] Add a method for test/dev purpose --- htdocs/core/login/functions_http.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/htdocs/core/login/functions_http.php b/htdocs/core/login/functions_http.php index a23047c8f1c..73f5824c3cd 100644 --- a/htdocs/core/login/functions_http.php +++ b/htdocs/core/login/functions_http.php @@ -63,3 +63,25 @@ function check_user_password_http($usertotest, $passwordtotest, $entitytotest) return $login; } + + +/** + * Decode the value found into the Authorization HTTP header. + * Ex: "Authorization: Basic bG9naW46cGFzcw==", $value is "Basic bG9naW46cGFzcw==" and after base64decode is "login:pass" + * Note: the $_SERVER["REMOTE_USER"] contains only the login used in the HTTP Basic form + * Method not used yet, but we keep it for some dev/test purposes. + * + * @param string $value Ex: $_SERVER["REMOTE_USER"] + * @return Object object.login & object.password + */ +function decodeHttpBasicAuth($value) +{ + $encoded_basic_auth = substr($value, 6); // Remove the "Basic " string + $decoded_basic_auth = base64_decode($encoded_basic_auth); + $credentials_basic_auth = explode(':', $decoded_basic_auth); + + return (object) [ + 'username'=> $credentials_basic_auth[0], + 'password' => $credentials_basic_auth[1] + ]; +} From 90137268a126be6e29adbe24d461ecb45f9d4be1 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 16 Jan 2023 22:15:02 +0100 Subject: [PATCH 601/816] FIX: missing tokan on Supplier proposal links --- htdocs/supplier_proposal/card.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 399d1271037..d09b6793dd0 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1968,30 +1968,30 @@ if ($action == 'create') { // Create an order if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) && $object->statut == SupplierProposal::STATUS_SIGNED) { if ($usercancreateorder) { - print ''; + print ''; } } // Set accepted/refused if ($object->statut == SupplierProposal::STATUS_VALIDATED && $usercanclose) { - print '
global->MAIN_JUMP_TAG) ? '' : '#acceptedrefused').'"'; + print ''; } // Close if ($object->statut == SupplierProposal::STATUS_SIGNED && $usercanclose) { - print '
global->MAIN_JUMP_TAG) ? '' : '#close').'"'; + print ''; } // Clone if ($usercancreate) { - print ''; + print ''; } // Delete if (($object->statut == SupplierProposal::STATUS_DRAFT && $usercancreate) || $usercandelete) { - print ''; } } From dbc9ca981628577dea9245ff7d6823c3e48b5142 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Mon, 16 Jan 2023 22:17:22 +0100 Subject: [PATCH 602/816] FIX: missing token on Supplier proposal links --- htdocs/supplier_proposal/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index d09b6793dd0..d4bb56b3304 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1986,7 +1986,7 @@ if ($action == 'create') { // Clone if ($usercancreate) { - print ''; + print ''; } // Delete From ce0c69ae96d589d91b3eef113ccc15d6ad65d231 Mon Sep 17 00:00:00 2001 From: Randall Mora <50120822+randallmoraes@users.noreply.github.com> Date: Mon, 16 Jan 2023 23:15:51 -0600 Subject: [PATCH 603/816] Restrict by supplier instead of customer restrict permissions if user does not have access to view providers --- htdocs/core/menus/standard/eldy.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index a671ea31756..d354bc2445c 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1273,7 +1273,7 @@ function get_left_menu_thridparties($mainmenu, &$newmenu, $usemenuhider = 1, $le $newmenu->add("/contact/list.php?leftmenu=contacts&type=c", $langs->trans("Customers"), 2, $user->hasRight('societe', 'contact', 'lire')); } if ((isModEnabled('fournisseur') && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled('supplier_order') || isModEnabled('supplier_invoice')) { - $newmenu->add("/contact/list.php?leftmenu=contacts&type=f", $langs->trans("Suppliers"), 2, $user->hasRight('societe', 'contact', 'lire')); + $newmenu->add("/contact/list.php?leftmenu=contacts&type=f", $langs->trans("Suppliers"), 2, $user->hasRight('fournisseur', 'lire') ); } $newmenu->add("/contact/list.php?leftmenu=contacts&type=o", $langs->trans("ContactOthers"), 2, $user->hasRight('societe', 'contact', 'lire')); //$newmenu->add("/contact/list.php?userid=$user->id", $langs->trans("MyContacts"), 1, $user->hasRight('societe', 'contact', 'lire')); From 95b391ae0a944e83b4f3d393a54a803c35e485da Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 17 Jan 2023 10:21:00 +0100 Subject: [PATCH 604/816] Fix - pos total qty --- htdocs/commande/list_det.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index fd36f229e5c..a763394b15b 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -1509,10 +1509,7 @@ if ($resql) { } // Product QtyOrdered if (!empty($arrayfields['cdet.qty']['checked'])) { - print ''.$obj->qty.''; - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'cdet.qty'; - } + print ''.$obj->qty.''; if (isset($totalarray['val']['cdet.qty'])) { $totalarray['val']['cdet.qty'] += $obj->qty; } else { @@ -1521,6 +1518,9 @@ if ($resql) { if (!$i) { $totalarray['nbfield']++; } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'cdet.qty'; + } } // Ref From 7668233d0ce6b0cee0984c266e432d48b3f28603 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Jan 2023 10:22:23 +0100 Subject: [PATCH 605/816] NEW Tooltip to explain how to add a photo on product --- htdocs/core/class/commonobject.class.php | 36 +++++++++++++----------- htdocs/core/lib/functions.lib.php | 4 +-- htdocs/langs/en_US/main.lang | 3 +- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 93a3e1b5536..d6be7c463a1 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -8583,21 +8583,21 @@ abstract class CommonObject /** * Show photos of an object (nbmax maximum), into several columns * - * @param string $modulepart 'product', 'ticket', ... - * @param string $sdir Directory to scan (full absolute path) - * @param int $size 0=original size, 1='small' use thumbnail if possible - * @param int $nbmax Nombre maximum de photos (0=pas de max) - * @param int $nbbyrow Number of image per line or -1 to use div separator or 0 to use no separator. Used only if size=1 or 'small'. - * @param int $showfilename 1=Show filename - * @param int $showaction 1=Show icon with action links (resize, delete) - * @param int $maxHeight Max height of original image when size='small' (so we can use original even if small requested). If 0, always use 'small' thumb image. - * @param int $maxWidth Max width of original image when size='small' - * @param int $nolink Do not add a href link to view enlarged imaged into a new tab - * @param int $notitle Do not add title tag on image - * @param int $usesharelink Use the public shared link of image (if not available, the 'nophoto' image will be shown instead) - * @return string Html code to show photo. Number of photos shown is saved in this->nbphoto + * @param string $modulepart 'product', 'ticket', ... + * @param string $sdir Directory to scan (full absolute path) + * @param int $size 0=original size, 1='small' use thumbnail if possible + * @param int $nbmax Nombre maximum de photos (0=pas de max) + * @param int $nbbyrow Number of image per line or -1 to use div separator or 0 to use no separator. Used only if size=1 or 'small'. + * @param int $showfilename 1=Show filename + * @param int $showaction 1=Show icon with action links (resize, delete) + * @param int $maxHeight Max height of original image when size='small' (so we can use original even if small requested). If 0, always use 'small' thumb image. + * @param int $maxWidth Max width of original image when size='small' + * @param int $nolink Do not add a href link to view enlarged imaged into a new tab + * @param int|string $overwritetitle Do not add title tag on image + * @param int $usesharelink Use the public shared link of image (if not available, the 'nophoto' image will be shown instead) + * @return string Html code to show photo. Number of photos shown is saved in this->nbphoto */ - public function show_photos($modulepart, $sdir, $size = 0, $nbmax = 0, $nbbyrow = 5, $showfilename = 0, $showaction = 0, $maxHeight = 120, $maxWidth = 160, $nolink = 0, $notitle = 0, $usesharelink = 0) + public function show_photos($modulepart, $sdir, $size = 0, $nbmax = 0, $nbbyrow = 5, $showfilename = 0, $showaction = 0, $maxHeight = 120, $maxWidth = 160, $nolink = 0, $overwritetitle = 0, $usesharelink = 0) { // phpcs:enable global $conf, $user, $langs; @@ -8700,8 +8700,12 @@ abstract class CommonObject // Si fichier vignette disponible et image source trop grande, on utilise la vignette, sinon on utilise photo origine $alt = $langs->transnoentitiesnoconv('File').': '.$relativefile; $alt .= ' - '.$langs->transnoentitiesnoconv('Size').': '.$imgarray['width'].'x'.$imgarray['height']; - if ($notitle) { - $alt = ''; + if ($overwritetitle) { + if (is_numeric($overwritetitle)) { + $alt = ''; + } else { + $alt = $overwritetitle; + } } $addphotorefcss = 1; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 3e3a87c7bd0..a25d083c251 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2122,14 +2122,14 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi $maxvisiblephotos = 1; } if ($showimage) { - $morehtmlleft .= '
'.$object->show_photos('product', $conf->product->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, $width, 0).'
'; + $morehtmlleft .= '
'.$object->show_photos('product', $conf->product->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, 0, $width, 0, '').'
'; } else { if (!empty($conf->global->PRODUCT_NODISPLAYIFNOPHOTO)) { $nophoto = ''; $morehtmlleft .= '
'; } else { // Show no photo link $nophoto = '/public/theme/common/nophoto.png'; - $morehtmlleft .= '
No photo
'; + $morehtmlleft .= '
transnoentitiesnoconv("Documents"))).'" alt="No photo"'.($width ? ' style="width: '.$width.'px"' : '').' src="'.DOL_URL_ROOT.$nophoto.'">
'; } } } elseif ($object->element == 'ticket') { diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index e7c7e010266..f65a05ce455 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1219,4 +1219,5 @@ NoSpecificContactAddress=No specific contact or address NoSpecificContactAddressBis=This tab is dedicated to force specific contacts or addresses for the current object. Use it only if you want to define one or several specific contacts or addresses for the object when the information on the thirdparty is not enough or not accurate. HideOnVCard=Hide %s AddToContacts=Add address to my contacts -LastAccess=Last access \ No newline at end of file +LastAccess=Last access +UploadAnImageToSeeAPhotoHere=Upload an image from the tab %s to see a photo here \ No newline at end of file From 756a971dadf049ded467dc4e5fca14747331e32c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Jan 2023 11:23:19 +0100 Subject: [PATCH 606/816] NEW Bank name no more mandatory on creation. Can be generated if empty. --- htdocs/societe/paymentmodes.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 0166a3a5635..bf4e1135f96 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -257,13 +257,8 @@ if (empty($reshook)) { if ($action == 'add') { $error = 0; - if (!GETPOST('label', 'alpha') || !GETPOST('bank', 'alpha')) { - if (!GETPOST('label', 'alpha')) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label")), null, 'errors'); - } - if (!GETPOST('bank', 'alpha')) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankName")), null, 'errors'); - } + if (!GETPOST('label', 'alpha')) { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label")), null, 'errors'); $action = 'create'; $error++; } @@ -274,6 +269,8 @@ if (empty($reshook)) { $companybankaccount->socid = $object->id; + $companybankaccount->fetch_thirdparty(); + $companybankaccount->bank = GETPOST('bank', 'alpha'); $companybankaccount->label = GETPOST('label', 'alpha'); $companybankaccount->courant = GETPOST('courant', 'alpha'); @@ -293,6 +290,12 @@ if (empty($reshook)) { $companybankaccount->datec = dol_now(); $companybankaccount->status = 1; + $companybankaccount->bank = trim($companybankaccount->bank); + if (empty($companybankaccount->bank) && !empty($companybankaccount->thirdparty)) { + $companybankaccount->bank = $langs->trans("Bank").' '.$companybankaccount->thirdparty->name; + } + $companybankaccount->bic = str_replace(' ', '', $companybankaccount->bic); + $db->begin(); // This test can be done only once properties were set @@ -1980,7 +1983,7 @@ if ($socid && $action == 'create' && $permissiontoaddupdatepaymentinformation) { print ''.$langs->trans("Label").''; print ''; - print ''.$langs->trans("Bank").''; + print ''.$langs->trans("Bank").''; print ''; // Show fields of bank account From eb6b42d1e34f8f177f58f62e473b26a59bb6b017 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 17 Jan 2023 11:25:16 +0100 Subject: [PATCH 607/816] NEW - Add sub total in order list det --- htdocs/commande/list_det.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index fd36f229e5c..e638e56ff9a 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -1402,6 +1402,7 @@ if ($resql) { $total_ht = 0; $total_margin = 0; + // Détail commande $totalqty = 0; @@ -1419,6 +1420,15 @@ if ($resql) { $text_warning = ''; $nbprod = 0; + // Print SubTotal + if (empty($i)) { + $oldref = $obj->product_ref; + } + if ($oldref != $obj->product_ref) { + include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + $oldref = $obj->product_ref; + } + $companystatic->id = $obj->socid; $companystatic->name = $obj->name; $companystatic->name_alias = $obj->alias; From 9c082d5df26e89494225b96aec026162b700cc0b Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 17 Jan 2023 11:31:40 +0100 Subject: [PATCH 608/816] kanban mode for liste of expensereport --- .../class/expensereport.class.php | 37 ++ htdocs/expensereport/list.php | 373 ++++++++++-------- 2 files changed, 237 insertions(+), 173 deletions(-) diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 63cbeaad67b..e0b10319b45 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -2675,6 +2675,43 @@ class ExpenseReport extends CommonObject return -1; } } + + /** + * Return clicable link of object (with eventually picto) + * + * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @return string HTML Code for Kanban thumb. + */ + public function getKanbanView($option = '') + { + global $langs, $selected,$arrayofselected; + $return = '
'; + $return .= '
'; + $return .= ''; + $return .= img_picto('', $this->picto); + $return .= ''; + $return .= '
'; + $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; + if (in_array($this->id, $arrayofselected)) { + $selected = 1; + } + $return .= ''; + if (property_exists($this, 'fk_user_author') && !empty($this->id)) { + $return .= '
'.$this->fk_user_author.''; + } + if (property_exists($this, 'date_debut') && property_exists($this, 'date_fin')) { + $return .= '
'.dol_print_date($this->date_debut, 'day').''; + $return .= ' '.$langs->trans("To").' '; + $return .= ''.dol_print_date($this->date_fin, 'day').''; + } + if (method_exists($this, 'getLibStatut')) { + $return .= '
'.$this->getLibStatut(5).'
'; + } + $return .= '
'; + $return .= '
'; + $return .= '
'; + return $return; + } } diff --git a/htdocs/expensereport/list.php b/htdocs/expensereport/list.php index ad16d5fb09f..918c916a52c 100644 --- a/htdocs/expensereport/list.php +++ b/htdocs/expensereport/list.php @@ -50,6 +50,7 @@ $confirm = GETPOST('confirm', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'expensereportlist'; +$mode = GETPOST('mode', 'alpha'); $childids = $user->getAllChildIds(1); @@ -378,6 +379,9 @@ if ($resql) { $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); } @@ -471,6 +475,7 @@ if ($resql) { print ''; print ''; print ''; + print ''; if ($id > 0) { print ''; } @@ -512,7 +517,10 @@ if ($resql) { if (!empty($socid)) { $url .= '&socid='.$socid; } - $newcardbutton = dolGetButtonTitle($langs->trans('NewTrip'), '', 'fa fa-plus-circle', $url, '', $user->rights->expensereport->creer); + $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')); + $newcardbutton .= dolGetButtonTitle($langs->trans('NewTrip'), '', 'fa fa-plus-circle', $url, '', $user->rights->expensereport->creer); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'trip', 0, $newcardbutton, '', $limit, 0, 0, 1); } @@ -739,185 +747,204 @@ if ($resql) { $expensereportstatic->note_private = $obj->note_private; $expensereportstatic->note_public = $obj->note_public; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; + print '
'; + } + $usertmp->fetch($obj->id_user); + $expensereportstatic->fk_user_author = $usertmp->getNomUrl(1); - print ''; - // 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->rowid, $arrayofselected)) { - $selected = 1; + // Output Kanban + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { + if ($massactionbutton || $massaction) { + $selected = 0; + + print $expensereportstatic->getKanbanView(''); } - print ''; } - print ''; - } - // Ref - if (!empty($arrayfields['d.ref']['checked'])) { - print ''; - print ''; - print ''; - // Warning late icon and note - print ''; } - if ($expensereportstatic->status == 5 && $expensereportstatic->hasDelay('topay')) { - print img_warning($langs->trans("Late")); - } - if (!empty($obj->note_private) || !empty($obj->note_public)) { - print ' '; - print ''.img_picto($langs->trans("ViewPrivateNote"), 'object_generic').''; - print ''; - } - print ''; - print ''; - print '
'; - print $expensereportstatic->getNomUrl(1); - print ''; - if ($expensereportstatic->status == 2 && $expensereportstatic->hasDelay('toappove')) { - print img_warning($langs->trans("Late")); + if ($i == (min($num, $limit) - 1)) { + print ''; + print '
'; - $filename = dol_sanitizeFileName($obj->ref); - $filedir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($obj->ref); - $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; - print $formfile->getDocumentsLink($expensereportstatic->element, $filename, $filedir); - print '
'; - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // User - if (!empty($arrayfields['user']['checked'])) { - print ''; - $usertmp->id = $obj->id_user; - $usertmp->lastname = $obj->lastname; - $usertmp->firstname = $obj->firstname; - $usertmp->login = $obj->login; - $usertmp->statut = $obj->statut; - $usertmp->photo = $obj->photo; - $usertmp->email = $obj->email; - print $usertmp->getNomUrl(-1); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Start date - if (!empty($arrayfields['d.date_debut']['checked'])) { - print ''.($obj->date_debut > 0 ? dol_print_date($db->jdate($obj->date_debut), 'day') : '').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // End date - if (!empty($arrayfields['d.date_fin']['checked'])) { - print ''.($obj->date_fin > 0 ? dol_print_date($db->jdate($obj->date_fin), 'day') : '').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date validation - if (!empty($arrayfields['d.date_valid']['checked'])) { - print ''.($obj->date_valid > 0 ? dol_print_date($db->jdate($obj->date_valid), 'day') : '').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date approval - if (!empty($arrayfields['d.date_approve']['checked'])) { - print ''.($obj->date_approve > 0 ? dol_print_date($db->jdate($obj->date_approve), 'day') : '').''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Amount HT - if (!empty($arrayfields['d.total_ht']['checked'])) { - print ''.price($obj->total_ht)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'd.total_ht'; - } - $totalarray['val']['d.total_ht'] += $obj->total_ht; - } - // Amount VAT - if (!empty($arrayfields['d.total_vat']['checked'])) { - print ''.price($obj->total_tva)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'd.total_tva'; - } - $totalarray['val']['d.total_tva'] += $obj->total_tva; - } - // Amount TTC - if (!empty($arrayfields['d.total_ttc']['checked'])) { - print ''.price($obj->total_ttc)."\n"; - if (!$i) { - $totalarray['nbfield']++; - } - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 'd.total_ttc'; - } - $totalarray['val']['d.total_ttc'] += $obj->total_ttc; - } - - // Extra fields - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; - // Fields from hook - $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); - $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook - print $hookmanager->resPrint; - - // Date creation - if (!empty($arrayfields['d.date_create']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_create), 'dayhour'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Date modification - if (!empty($arrayfields['d.tms']['checked'])) { - print ''; - print dol_print_date($db->jdate($obj->date_modif), 'dayhour'); - print ''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // Status - if (!empty($arrayfields['d.fk_statut']['checked'])) { - print ''.$expensereportstatic->getLibStatut(5).''; - if (!$i) { - $totalarray['nbfield']++; - } - } - // 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->rowid, $arrayofselected)) { - $selected = 1; + } else { + print ''; + // 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; } - print ''; + print ''; } - print ''; + // Ref + if (!empty($arrayfields['d.ref']['checked'])) { + print ''; + print ''; + print ''; + // Warning late icon and note + print ''; + print ''; + print '
'; + print $expensereportstatic->getNomUrl(1); + print ''; + if ($expensereportstatic->status == 2 && $expensereportstatic->hasDelay('toappove')) { + print img_warning($langs->trans("Late")); + } + if ($expensereportstatic->status == 5 && $expensereportstatic->hasDelay('topay')) { + print img_warning($langs->trans("Late")); + } + if (!empty($obj->note_private) || !empty($obj->note_public)) { + print ' '; + print ''.img_picto($langs->trans("ViewPrivateNote"), 'object_generic').''; + print ''; + } + print ''; + $filename = dol_sanitizeFileName($obj->ref); + $filedir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($obj->ref); + $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; + print $formfile->getDocumentsLink($expensereportstatic->element, $filename, $filedir); + print '
'; + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // User + if (!empty($arrayfields['user']['checked'])) { + print ''; + $usertmp->id = $obj->id_user; + $usertmp->lastname = $obj->lastname; + $usertmp->firstname = $obj->firstname; + $usertmp->login = $obj->login; + $usertmp->statut = $obj->statut; + $usertmp->photo = $obj->photo; + $usertmp->email = $obj->email; + print $usertmp->getNomUrl(-1); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Start date + if (!empty($arrayfields['d.date_debut']['checked'])) { + print ''.($obj->date_debut > 0 ? dol_print_date($db->jdate($obj->date_debut), 'day') : '').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // End date + if (!empty($arrayfields['d.date_fin']['checked'])) { + print ''.($obj->date_fin > 0 ? dol_print_date($db->jdate($obj->date_fin), 'day') : '').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date validation + if (!empty($arrayfields['d.date_valid']['checked'])) { + print ''.($obj->date_valid > 0 ? dol_print_date($db->jdate($obj->date_valid), 'day') : '').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date approval + if (!empty($arrayfields['d.date_approve']['checked'])) { + print ''.($obj->date_approve > 0 ? dol_print_date($db->jdate($obj->date_approve), 'day') : '').''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Amount HT + if (!empty($arrayfields['d.total_ht']['checked'])) { + print ''.price($obj->total_ht)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'd.total_ht'; + } + $totalarray['val']['d.total_ht'] += $obj->total_ht; + } + // Amount VAT + if (!empty($arrayfields['d.total_vat']['checked'])) { + print ''.price($obj->total_tva)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'd.total_tva'; + } + $totalarray['val']['d.total_tva'] += $obj->total_tva; + } + // Amount TTC + if (!empty($arrayfields['d.total_ttc']['checked'])) { + print ''.price($obj->total_ttc)."\n"; + if (!$i) { + $totalarray['nbfield']++; + } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'd.total_ttc'; + } + $totalarray['val']['d.total_ttc'] += $obj->total_ttc; + } + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + + // Date creation + if (!empty($arrayfields['d.date_create']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_create), 'dayhour'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Date modification + if (!empty($arrayfields['d.tms']['checked'])) { + print ''; + print dol_print_date($db->jdate($obj->date_modif), 'dayhour'); + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // Status + if (!empty($arrayfields['d.fk_statut']['checked'])) { + print ''.$expensereportstatic->getLibStatut(5).''; + if (!$i) { + $totalarray['nbfield']++; + } + } + // 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->rowid, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + + print "\n"; } - if (!$i) { - $totalarray['nbfield']++; - } - - print "\n"; - - $total_total_ht = $total_total_ht + $obj->total_ht; - $total_total_tva = $total_total_tva + $obj->total_tva; - $total_total_ttc = $total_total_ttc + $obj->total_ttc; - + $total_total_ht = $total_total_ht + $obj->total_ht; + $total_total_tva = $total_total_tva + $obj->total_tva; + $total_total_ttc = $total_total_ttc + $obj->total_ttc; $i++; } } else { From 957e8538a4b7768a60d7495331eaad3d33d31b49 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 17 Jan 2023 11:36:03 +0100 Subject: [PATCH 609/816] FIX - Order list det sortfield default --- htdocs/commande/list_det.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index fd36f229e5c..c05ff36e9d2 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -137,10 +137,10 @@ $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; if (!$sortfield) { - $sortfield = 'c.ref'; + $sortfield = 'pr.ref'; } if (!$sortorder) { - $sortorder = 'DESC'; + $sortorder = 'ASSC'; } $show_shippable_command = GETPOST('show_shippable_command', 'aZ09'); From a165489237b8dc5da4b8213b247d33365d779e74 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Tue, 17 Jan 2023 11:46:39 +0100 Subject: [PATCH 610/816] Move checkbox --- htdocs/commande/list_det.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index fd36f229e5c..385408663fd 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -830,10 +830,6 @@ if ($resql) { print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'order', 0, $newcardbutton, '', $limit, 0, 0, 1); - print ''; - print ''; - print ''; - $topicmail = "SendOrderRef"; $modelmail = "order_send"; $objecttmp = new Commande($db); @@ -849,6 +845,11 @@ if ($resql) { $moreforfilter = ''; + $moreforfilter .= ''; + $moreforfilter .= ''; + $moreforfilter .= ''; + $moreforfilter .= '
'; + // If the user can view prospects other than his' if ($user->rights->user->user->lire) { $langs->load("commercial"); @@ -888,6 +889,8 @@ if ($resql) { $moreforfilter .= img_picto($tmptitle, 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($search_warehouse, 'search_warehouse', '', 1, 0, 0, $tmptitle, 0, 0, array(), 'maxwidth250 widthcentpercentminusx'); $moreforfilter .= '
'; } + + $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook if (empty($reshook)) { From 8ced6d52e745f0ee6ae95f093e24298f2d01df55 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Jan 2023 11:47:16 +0100 Subject: [PATCH 611/816] FIX Component js to generate password --- htdocs/core/ajax/security.php | 9 +++++---- htdocs/core/lib/security2.lib.php | 7 ++++--- htdocs/user/card.php | 14 ++++++++------ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/htdocs/core/ajax/security.php b/htdocs/core/ajax/security.php index e5dc91c05d1..b01c952662e 100644 --- a/htdocs/core/ajax/security.php +++ b/htdocs/core/ajax/security.php @@ -36,9 +36,10 @@ if (!defined('NOREQUIREAJAX')) { if (!defined('NOREQUIRESOC')) { define('NOREQUIRESOC', '1'); } -if (!defined('NOREQUIRETRAN')) { +// We need langs because the getRandomPassword may use user language to define some rules of pass generation +/*if (!defined('NOREQUIRETRAN')) { define('NOREQUIRETRAN', '1'); -} +}*/ // Load Dolibarr environment require '../../main.inc.php'; @@ -55,9 +56,9 @@ top_httphead(); //print ''."\n"; -// Registering the location of boxes +// Return a new generated password if ($action) { - if ($action == 'getrandompassword' && ($user->admin || $user->rights->api->apikey->generate)) { + if ($action == 'getrandompassword') { require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; $generic = GETPOST('generic') ? true : false; echo getRandomPassword($generic); diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index 5e4d58103d8..f450d390dff 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -560,10 +560,11 @@ function getRandomPassword($generic = false, $replaceambiguouschars = null, $len * * @param string $htmlname HTML name of element to insert key into * @param string $htmlnameofbutton HTML name of button + * @param int $generic 1=Return a generic pass, 0=Return a pass following setup rules * @return string HTML javascript code to set a password * @see getRandomPassword() */ -function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token') +function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token', $generic = 1) { global $conf; @@ -571,10 +572,10 @@ function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token print "\n".' - \n"; From 947365fabfabd96a198952de5acfa24dfe5bf99d Mon Sep 17 00:00:00 2001 From: Anthony Berton <34568357+BB2A-Anthony@users.noreply.github.com> Date: Tue, 17 Jan 2023 17:48:37 +0100 Subject: [PATCH 632/816] Update list_det.php --- htdocs/commande/list_det.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/list_det.php b/htdocs/commande/list_det.php index c05ff36e9d2..48d21abf4a3 100644 --- a/htdocs/commande/list_det.php +++ b/htdocs/commande/list_det.php @@ -140,7 +140,7 @@ if (!$sortfield) { $sortfield = 'pr.ref'; } if (!$sortorder) { - $sortorder = 'ASSC'; + $sortorder = 'ASC'; } $show_shippable_command = GETPOST('show_shippable_command', 'aZ09'); From e5d4ea1b7cc6184bafa1aa0ccda8ee829af0f14d Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Tue, 17 Jan 2023 18:30:06 +0100 Subject: [PATCH 633/816] FIX error with dol_banner_tab, ref is needed --- htdocs/contrat/agenda.php | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/htdocs/contrat/agenda.php b/htdocs/contrat/agenda.php index d654ac38d9f..3e51e9a1de5 100644 --- a/htdocs/contrat/agenda.php +++ b/htdocs/contrat/agenda.php @@ -54,7 +54,11 @@ $ref = GETPOST('ref', 'alpha'); if ($user->socid) { $socid = $user->socid; } -$result = restrictedArea($user, 'contrat', $id, ''); + +// Security check +$fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : '')); +$fieldtype = (!empty($id) ? 'rowid' : 'ref'); +$result = restrictedArea($user, 'contrat', $fieldvalue, '', '', '', $fieldtype); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); @@ -73,6 +77,13 @@ if (!$sortorder) { $sortorder = 'DESC,DESC'; } + +$object = new Contrat($db); + +if ($id > 0 || !empty($ref)) { + $result = $object->fetch($id, $ref); +} + // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('agendacontract', 'globalcard')); @@ -81,7 +92,7 @@ $hookmanager->initHooks(array('agendacontract', 'globalcard')); * Actions */ -$parameters = array('id'=>$id); +$parameters = array('id' => $id, 'ref' => $ref); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -102,8 +113,6 @@ if (empty($reshook)) { } - - /* * View */ @@ -114,7 +123,7 @@ if (!empty($conf->projet->enabled)) { $formproject = new FormProjets($db); } -if ($id > 0) { +if ($object->id > 0) { // Load object modContract $module = (!empty($conf->global->CONTRACT_ADDON) ? $conf->global->CONTRACT_ADDON : 'mod_contract_serpis'); if (substr($module, 0, 13) == 'mod_contract_' && substr($module, -3) == 'php') { @@ -128,8 +137,6 @@ if ($id > 0) { require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; - $object = new Contrat($db); - $result = $object->fetch($id); $object->fetch_thirdparty(); $title = $langs->trans("Agenda"); @@ -205,13 +212,13 @@ if ($id > 0) { } $morehtmlref .= '
'; - dol_banner_tab($object, 'id', $linkback, 1, 'ref', 'none', $morehtmlref); + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'none', $morehtmlref); print '
'; print '
'; - $object->info($id); + $object->info($object->id); dol_print_object_info($object, 1); print '
'; @@ -254,7 +261,7 @@ if ($id > 0) { if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { print '
'; - $param = '&id='.$id; + $param = '&id='.$object->id; if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { $param .= '&contextpage='.$contextpage; } From 82cccc82f58a342b52b3ce2d33bf81fda3abf6be Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 17 Jan 2023 19:23:01 +0000 Subject: [PATCH 634/816] Fixing style errors. --- htdocs/bom/tpl/objectline_view.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index be12ec460ba..2c18ffbd87f 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -170,7 +170,7 @@ $total_cost = 0; $tmpbom->calculateCosts(); print ''; $coldisplay++; -if(!empty($line->fk_bom_child)) { +if (!empty($line->fk_bom_child)) { echo ''.price($tmpbom->total_cost).''; } else { echo ''.price($line->total_cost).''; From 26972c55a8c9ea716b5af46bd2e1f002779c20db Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Jan 2023 23:56:22 +0100 Subject: [PATCH 635/816] Fix warnings --- htdocs/filefunc.inc.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index aca15e9d7a3..a5b5264052d 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -138,10 +138,10 @@ if (!empty($dolibarr_main_prod)) { } // Clean parameters -$dolibarr_main_data_root = trim($dolibarr_main_data_root); -$dolibarr_main_url_root = trim(preg_replace('/\/+$/', '', $dolibarr_main_url_root)); +$dolibarr_main_data_root = (empty($dolibarr_main_data_root) ? '' : trim($dolibarr_main_data_root)); +$dolibarr_main_url_root = trim(preg_replace('/\/+$/', '', empty($dolibarr_main_url_root) ? '' : $dolibarr_main_url_root)); $dolibarr_main_url_root_alt = (empty($dolibarr_main_url_root_alt) ? '' : trim($dolibarr_main_url_root_alt)); -$dolibarr_main_document_root = trim($dolibarr_main_document_root); +$dolibarr_main_document_root = (empty($dolibarr_main_document_root) ? '' : trim($dolibarr_main_document_root)); $dolibarr_main_document_root_alt = (empty($dolibarr_main_document_root_alt) ? '' : trim($dolibarr_main_document_root_alt)); if (empty($dolibarr_main_db_port)) { From 708e284381f15d06da6fbf9591fc89f5ed73831a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 00:13:21 +0100 Subject: [PATCH 636/816] Enhance backward compatibility --- htdocs/societe/class/societe.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 5876e8aff4a..2b233f3e0f6 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -794,6 +794,9 @@ class Societe extends CommonObject public $partnerships = array(); + const STATUS_CEASED = 0; + const STATUS_INACTIVITY = 1; + /** * @var Account|string Default BAN account From 29966d8499b59a9f01562979c7f472f1ab1cd44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Courtier?= Date: Wed, 18 Jan 2023 09:29:11 +0100 Subject: [PATCH 637/816] FIX: Add missing token when deleting template inn order_supplier admin menu --- htdocs/admin/supplier_order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/supplier_order.php b/htdocs/admin/supplier_order.php index 7cf64e4800d..5b7a9845c10 100644 --- a/htdocs/admin/supplier_order.php +++ b/htdocs/admin/supplier_order.php @@ -381,7 +381,7 @@ foreach ($dirmodels as $reldir) { if (in_array($name, $def)) { print ''."\n"; if ($conf->global->COMMANDE_SUPPLIER_ADDON_PDF != "$name") { - print 'scandir.'&label='.urlencode($module->name).'&type=order_supplier">'; + print 'scandir.'&label='.urlencode($module->name).'&type=order_supplier">'; print img_picto($langs->trans("Enabled"), 'switch_on'); print ''; } else { From d344e108c95d29e2d6d4101148ce9fae4f37baab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Courtier?= Date: Wed, 18 Jan 2023 09:44:23 +0100 Subject: [PATCH 638/816] FIX: Errors Handling for CreateFrom Hooks --- htdocs/comm/action/class/actioncomm.class.php | 2 ++ htdocs/comm/propal/card.php | 1 + htdocs/comm/propal/class/propal.class.php | 2 ++ htdocs/commande/card.php | 1 + htdocs/commande/class/commande.class.php | 4 ++++ htdocs/compta/facture/class/facture.class.php | 4 ++++ htdocs/contrat/card.php | 1 + htdocs/contrat/class/contrat.class.php | 2 ++ htdocs/expensereport/class/expensereport.class.php | 2 ++ htdocs/fichinter/class/fichinter.class.php | 2 ++ htdocs/fourn/class/fournisseur.commande.class.php | 2 ++ htdocs/fourn/commande/card.php | 1 + htdocs/supplier_proposal/card.php | 1 + htdocs/supplier_proposal/class/supplier_proposal.class.php | 2 ++ 14 files changed, 27 insertions(+) diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 769bd9ddd50..8032ead20ba 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -708,6 +708,8 @@ class ActionComm extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index da4c756705f..ea2ab40db42 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -567,6 +567,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been // modified by hook if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index f36b8027461..6567e11cdbf 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -1412,6 +1412,8 @@ class Propal extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index d394df997ff..b74114164b0 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -445,6 +445,7 @@ if (empty($reshook)) { // Note that $action and $object may be modified by hook $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 33de271b45d..bd3be625561 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1252,6 +1252,8 @@ class Commande extends CommonOrder $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } @@ -1406,6 +1408,8 @@ class Commande extends CommonOrder $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 862a86e9e16..ba5eab04d16 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1299,6 +1299,8 @@ class Facture extends CommonInvoice $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } @@ -1432,6 +1434,8 @@ class Facture extends CommonInvoice $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 624d59b0d94..2acf59593ff 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -341,6 +341,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been // modified by hook if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 309df80605e..3d397fcb6c1 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2564,6 +2564,8 @@ class Contrat extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $clonedObj, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 3f62087dd0b..fa69245dc58 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -455,6 +455,8 @@ class ExpenseReport extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 000b654bf72..d8e213d31e8 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -1211,6 +1211,8 @@ class Fichinter extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index e78dd9dd02a..c5f700dd6a7 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1654,6 +1654,8 @@ class CommandeFournisseur extends CommonOrder $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 86e34ce39a1..f7e339c6c9a 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1314,6 +1314,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 4ad5fa9ff56..2f4dd6e0540 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -407,6 +407,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been // modified by hook if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 78fc1c7fd15..dc18f7dcb2b 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -1160,6 +1160,8 @@ class SupplierProposal extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } From 4ee0ede6d8e8205e9431da95463de6ef886312f6 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Wed, 18 Jan 2023 08:53:28 +0000 Subject: [PATCH 639/816] Fixing style errors. --- htdocs/comm/action/class/actioncomm.class.php | 4 ++-- htdocs/comm/propal/card.php | 2 +- htdocs/comm/propal/class/propal.class.php | 4 ++-- htdocs/commande/card.php | 2 +- htdocs/commande/class/commande.class.php | 8 ++++---- htdocs/compta/facture/class/facture.class.php | 8 ++++---- htdocs/contrat/card.php | 2 +- htdocs/contrat/class/contrat.class.php | 4 ++-- htdocs/expensereport/class/expensereport.class.php | 4 ++-- htdocs/fichinter/class/fichinter.class.php | 4 ++-- htdocs/fourn/class/fournisseur.commande.class.php | 4 ++-- htdocs/fourn/commande/card.php | 2 +- htdocs/supplier_proposal/card.php | 2 +- .../supplier_proposal/class/supplier_proposal.class.php | 4 ++-- 14 files changed, 27 insertions(+), 27 deletions(-) diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 8032ead20ba..f5e1fe40b1f 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -708,8 +708,8 @@ class ActionComm extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index ea2ab40db42..e575195799c 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -567,7 +567,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been // modified by hook if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 6567e11cdbf..edd443c1b58 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -1412,8 +1412,8 @@ class Propal extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index b74114164b0..e099aafc9ca 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -445,7 +445,7 @@ if (empty($reshook)) { // Note that $action and $object may be modified by hook $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index bd3be625561..c636b4e905d 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1252,8 +1252,8 @@ class Commande extends CommonOrder $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } @@ -1408,8 +1408,8 @@ class Commande extends CommonOrder $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index ba5eab04d16..2af2b35240d 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1299,8 +1299,8 @@ class Facture extends CommonInvoice $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } @@ -1434,8 +1434,8 @@ class Facture extends CommonInvoice $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 2acf59593ff..a63e8d7c6ca 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -341,7 +341,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been // modified by hook if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 3d397fcb6c1..f16b26646bc 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2564,8 +2564,8 @@ class Contrat extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $clonedObj, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index fa69245dc58..a0fe9fa8335 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -455,8 +455,8 @@ class ExpenseReport extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index d8e213d31e8..0205fec9e39 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -1211,8 +1211,8 @@ class Fichinter extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index c5f700dd6a7..112708a92b7 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1654,8 +1654,8 @@ class CommandeFournisseur extends CommonOrder $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index f7e339c6c9a..a8ee29fc974 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1314,7 +1314,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 2f4dd6e0540..01f9ad5e2dd 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -407,7 +407,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been // modified by hook if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); $error++; } } else { diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index dc18f7dcb2b..088594f6ab4 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -1160,8 +1160,8 @@ class SupplierProposal extends CommonObject $action = ''; $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { - $this->errors += $hookmanager->errors; - $this->error = $hookmanager->error; + $this->errors += $hookmanager->errors; + $this->error = $hookmanager->error; $error++; } } From 98356222c18786336ef9c421a2ac7b39b776ae01 Mon Sep 17 00:00:00 2001 From: kkhelifa Date: Wed, 18 Jan 2023 10:36:52 +0100 Subject: [PATCH 640/816] NEW: Can add any contact on events if global MAIN_ACTIONCOM_CAN_ADD_ANY_CONTACT is set at 1 --- htdocs/comm/action/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 91eb9f49516..e6205cd5317 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1446,7 +1446,7 @@ if ($action == 'create') { } if ($origin=='contact') $preselectedids[GETPOST('originid', 'int')] = GETPOST('originid', 'int'); print img_picto('', 'contact', 'class="paddingrightonly"'); - print $form->selectcontacts(GETPOST('socid', 'int'), $preselectedids, 'socpeopleassigned[]', 1, '', '', 0, 'minwidth300 quatrevingtpercent', false, 0, array(), false, 'multiple', 'contactid'); + print $form->selectcontacts(empty($conf->global->MAIN_ACTIONCOM_CAN_ADD_ANY_CONTACT) ? GETPOST('socid', 'int') : 0, $preselectedids, 'socpeopleassigned[]', 1, '', '', 0, 'minwidth300 quatrevingtpercent', false, 0, array(), false, 'multiple', 'contactid'); print ''; } @@ -1949,7 +1949,7 @@ if ($id > 0) { // related contact print ''.$langs->trans("ActionOnContact").''; print '
'; - print img_picto('', 'contact', 'class="paddingrightonly"').$form->selectcontacts($object->socid, array_keys($object->socpeopleassigned), 'socpeopleassigned[]', 1, '', '', 1, 'quatrevingtpercent', false, 0, 0, array(), 'multiple', 'contactid'); + print img_picto('', 'contact', 'class="paddingrightonly"').$form->selectcontacts(empty($conf->global->MAIN_ACTIONCOM_CAN_ADD_ANY_CONTACT) ? $object->socid : 0, array_keys($object->socpeopleassigned), 'socpeopleassigned[]', 1, '', '', 1, 'quatrevingtpercent', false, 0, 0, array(), 'multiple', 'contactid'); print '
'; print ''; print ''; From cb963780312edca5445f075d516eecd6955856a7 Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Wed, 18 Jan 2023 10:48:18 +0100 Subject: [PATCH 641/816] FIX: API access for deactivated users --- htdocs/api/class/api_access.class.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/api/class/api_access.class.php b/htdocs/api/class/api_access.class.php index 5a4097b089b..09bb46ed98e 100644 --- a/htdocs/api/class/api_access.class.php +++ b/htdocs/api/class/api_access.class.php @@ -1,6 +1,7 @@ * Copyright (C) 2016 Laurent Destailleur + * Copyright (C) 2023 Ferran Marcet * * 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 @@ -147,6 +148,9 @@ class DolibarrApiAccess implements iAuthenticate if ($result <= 0) { throw new RestException(503, 'Error when fetching user :'.$fuser->error.' (conf->entity='.$conf->entity.')'); } + if ($fuser->statut == 0) { + throw new RestException(503, 'Error when fetching user. This user has been locked or disabled'); + } $fuser->getrights(); From 1d50acb3cfdc083bc142d00d65c3f21808881143 Mon Sep 17 00:00:00 2001 From: GregM Date: Wed, 18 Jan 2023 12:10:58 +0100 Subject: [PATCH 642/816] Fix fieldvalue emailtemplate --- htdocs/core/class/html.formsetup.class.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 1cfddb588fd..0c9adf0be59 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -1069,16 +1069,18 @@ class FormSetupItem } elseif ($this->type == 'yesno') { $out.= ajax_constantonoff($this->confKey); } elseif (preg_match('/emailtemplate:/', $this->type)) { - include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; - $formmail = new FormMail($this->db); + if ($this->fieldValue > 0){ + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($this->db); - $tmp = explode(':', $this->type); + $tmp = explode(':', $this->type); - $template = $formmail->getEMailTemplate($this->db, $tmp[1], $user, $this->langs, $this->fieldValue); - if ($template<0) { - $this->setErrors($formmail->errors); + $template = $formmail->getEMailTemplate($this->db, $tmp[1], $user, $this->langs, $this->fieldValue); + if ($template<0) { + $this->setErrors($formmail->errors); + } + $out.= $this->langs->trans($template->label); } - $out.= $this->langs->trans($template->label); } elseif (preg_match('/category:/', $this->type)) { require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $c = new Categorie($this->db); From 289570ffe5ddc4e5010627500a4e7b3dc7f436f4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 12:57:18 +0100 Subject: [PATCH 643/816] Debug --- htdocs/compta/facture/prelevement.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 195b04a2ed5..896aecb1b8c 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -742,8 +742,8 @@ if ($object->id > 0) { print ''; print ''; - if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT_SHOW_BUTTON)) { - // TODO Replace this with a checkbox for each payment mode: "Send request to PaymentModeManager immediatly..." + if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT_SHOW_OLD_BUTTON)) { // This is hidden, prefer to use mode enabled with STRIPE_SEPA_DIRECT_DEBIT + // TODO Replace this with a checkbox for each payment mode: "Send request to XXX immediatly..." print "
"; //add stripe sepa button $buttonlabel = $langs->trans("MakeWithdrawRequestStripe"); From 330f2307bd850b34edcc14db2961d7ae3b894a12 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 12:59:48 +0100 Subject: [PATCH 644/816] Fix message --- htdocs/compta/facture/prelevement.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 896aecb1b8c..365fa59fdcb 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -742,7 +742,7 @@ if ($object->id > 0) { print ''; print ''; - if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT_SHOW_OLD_BUTTON)) { // This is hidden, prefer to use mode enabled with STRIPE_SEPA_DIRECT_DEBIT + if (getDolGlobalString('STRIPE_SEPA_DIRECT_DEBIT_SHOW_OLD_BUTTON')) { // This is hidden, prefer to use mode enabled with STRIPE_SEPA_DIRECT_DEBIT // TODO Replace this with a checkbox for each payment mode: "Send request to XXX immediatly..." print "
"; //add stripe sepa button @@ -781,14 +781,14 @@ if ($object->id > 0) { if ($type == 'bank-transfer') { print '
'.$langs->trans("DoCreditTransferBeforePayments"); - if (isModEnabled('stripe')) { + if (isModEnabled('stripe') && getDolGlobalString('STRIPE_SEPA_DIRECT_DEBIT')) { print ' '.$langs->trans("DoStandingOrdersBeforePayments2"); } print ' '.$langs->trans("DoStandingOrdersBeforePayments3"); print '

'; } else { print '
'.$langs->trans("DoStandingOrdersBeforePayments"); - if (isModEnabled('stripe')) { + if (isModEnabled('stripe') && getDolGlobalString('STRIPE_SEPA_DIRECT_DEBIT')) { print ' '.$langs->trans("DoStandingOrdersBeforePayments2"); } print ' '.$langs->trans("DoStandingOrdersBeforePayments3"); From a384bdecdcca3e05f781dee7224da2ff611f9531 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 14:36:46 +0100 Subject: [PATCH 645/816] Debug payment SEPA from backoffice with Stripe --- htdocs/compta/facture/prelevement.php | 18 +- htdocs/core/class/commoninvoice.class.php | 202 +++++++--------------- 2 files changed, 77 insertions(+), 143 deletions(-) diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 365fa59fdcb..39e6446b573 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -807,13 +807,13 @@ if ($object->id > 0) { print ''.$langs->trans("User").''; print ''.$langs->trans("Amount").''; print ''.$langs->trans("DateProcess").''; - print ' '; if ($type == 'bank-transfer') { print ''.$langs->trans("BankTransferReceipt").''; } else { print ''.$langs->trans("WithdrawalReceipt").''; } print ' '; + print ' '; print ''; $sql = "SELECT pfd.rowid, pfd.traite, pfd.date_demande as date_demande,"; @@ -864,9 +864,10 @@ if ($object->id > 0) { // Amount print ''.price($obj->amount).''; - // Ref of SEPA request + // Date process print ''.$langs->trans("OrderWaiting").''; + // Link to make payment now print ''; if (!empty($conf->global->STRIPE_SEPA_DIRECT_DEBIT)) { $langs->load("stripe"); @@ -874,8 +875,10 @@ if ($object->id > 0) { } print ''; + // print '-'; + // Actions print ''; print ''; print img_delete(); @@ -929,14 +932,21 @@ if ($object->id > 0) { print ''; + // Date print ''.dol_print_date($db->jdate($obj->date_demande), 'day')."\n"; + // User print ''; print $tmpuser->getNomUrl(1, '', 0, 0, 0, 0, 'login'); print ''; + // Amount print ''.price($obj->amount).''; + // Date process + print ''.dol_print_date($db->jdate($obj->date_traite), 'day')."\n"; + + // Link to payment request done print ''; if ($obj->fk_prelevement_bons > 0) { $withdrawreceipt = new BonPrelevement($db); @@ -946,10 +956,10 @@ if ($object->id > 0) { } print "\n"; + // print ' '; - print ''.dol_print_date($db->jdate($obj->date_traite), 'day')."\n"; - + // Actions print ' '; print "\n"; diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 3f53c3c4e94..7a8b5e3cbf7 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -865,7 +865,7 @@ abstract class CommonInvoice extends CommonObject /** - * Create a withdrawal request for a direct debit order or a credit transfer order. + * Create a withdrawal request at Stripe for a direct debit order or a credit transfer order. * Use the remain to pay excluding all existing open direct debit requests. * * @param User $fuser User asking the direct debit transfer @@ -900,6 +900,7 @@ abstract class CommonInvoice extends CommonObject $sql = "SELECT rowid, date_demande, amount, fk_facture, fk_facture_fourn"; $sql .= " FROM ".$this->db->prefix()."prelevement_demande"; + $sql .= " AND fk_facture = ".((int) $this->fk_facture); // Add a protection to not pay another invoice than current one $sql .= " WHERE rowid = ".((int) $did); dol_syslog(get_class($this)."::makeStripeSepaRequest 1", LOG_DEBUG); @@ -1035,9 +1036,9 @@ abstract class CommonInvoice extends CommonObject } - dol_syslog("makeStripeSepaRequest get stripe account", LOG_DEBUG); + dol_syslog("makeStripeSepaRequest get stripe connet account", LOG_DEBUG); $stripeacc = $stripe->getStripeAccount($service, $this->socid); // Get Stripe OAuth connect account if it exists (no network access here) - dol_syslog("makeStripeSepaRequest get stripe account return " . json_encode($stripeacc), LOG_DEBUG); + dol_syslog("makeStripeSepaRequest get stripe connect account return " . json_encode($stripeacc), LOG_DEBUG); if ($foundalternativestripeaccount) { if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage @@ -1072,101 +1073,64 @@ abstract class CommonInvoice extends CommonObject } if (!$error) { // Payment was not canceled - //erics card or sepa ? $sepaMode = false; + $stripecard = null; if ($companypaymentmode->type == 'ban') { $sepaMode = true; $stripecard = $stripe->sepaStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0); - } else { - $stripecard = $stripe->cardStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0); } - if ($stripecard) { // Can be card_... (old mode) or pm_... (new mode) + if ($stripecard) { // Can be src_... (for sepa) - Other card_... (old mode) or pm_... (new mode) should not happen here. $FULLTAG = 'INV=' . $this->id . '-CUS=' . $thirdparty->id; - $description = 'Stripe payment from doTakePaymentStripeForThirdparty: ' . $FULLTAG . ' ref=' . $this->ref; + $description = 'Stripe payment from makeStripeSepaRequest: ' . $FULLTAG . ' ref=' . $this->ref; $stripefailurecode = ''; $stripefailuremessage = ''; $stripefailuredeclinecode = ''; - if (preg_match('/^card_/', $stripecard->id)) { // Using old method - dol_syslog("* Create charge on card " . $stripecard->id . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG); + // Using new SCA method + dol_syslog("* Create payment on SEPA " . $stripecard->id . ", amounttopay=" . $amounttopay . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG); - $ipaddress = getUserRemoteIP(); + // Create payment intent and charge payment (confirmnow = true) + $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $this, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1); - $charge = null; // Force reset of $charge, so, if already set from a previous fetch, it will be empty even if there is an exception at next step - try { - $charge = \Stripe\Charge::create([ - 'amount' => price2num($amountstripe, 'MU'), - 'currency' => $currency, - 'capture' => true, // Charge immediatly - 'description' => $description, - 'metadata' => ["FULLTAG" => $FULLTAG, 'Recipient' => $mysoc->name, 'dol_version' => DOL_VERSION, 'dol_entity' => $conf->entity, 'ipaddress' => $ipaddress], - 'customer' => $customer->id, - //'customer' => 'bidon_to_force_error', // To use to force a stripe error - 'source' => $stripecard, - 'statement_descriptor' => dol_trunc('INV=' . $this->id, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - ]); - } catch (\Stripe\Error\Card $e) { - // Since it's a decline, Stripe_CardError will be caught - $body = $e->getJsonBody(); - $err = $body['error']; + $charge = new stdClass(); + //erics add processing sepa is like success ? + if ($paymentintent->status === 'succeeded' || $paymentintent->status === 'processing') { + $charge->status = 'ok'; + $charge->id = $paymentintent->id; + $charge->customer = $customer->id; + } elseif ($paymentintent->status === 'requires_action') { + //paymentintent->status may be => 'requires_action' (no error in such a case) + dol_syslog(var_export($paymentintent, true), LOG_DEBUG); - $stripefailurecode = $err['code']; - $stripefailuremessage = $err['message']; - $stripefailuredeclinecode = $err['decline_code']; - } catch (Exception $e) { - $stripefailurecode = 'UnknownChargeError'; - $stripefailuremessage = $e->getMessage(); - } - } else { // Using new SCA method - if ($sepaMode) { - dol_syslog("* Create payment on SEPA " . $stripecard->id . ", amounttopay=" . $amounttopay . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG); - } else { - dol_syslog("* Create payment on card " . $stripecard->id . ", amounttopay=" . $amounttopay . ", amountstripe=" . $amountstripe . ", FULLTAG=" . $FULLTAG, LOG_DEBUG); - } + $charge->status = 'failed'; + $charge->customer = $customer->id; + $charge->failure_code = $stripe->code; + $charge->failure_message = $stripe->error; + $charge->failure_declinecode = $stripe->declinecode; + $stripefailurecode = $stripe->code; + $stripefailuremessage = 'Action required. Contact the support at ';// . $conf->global->SELLYOURSAAS_MAIN_EMAIL; + $stripefailuredeclinecode = $stripe->declinecode; + } else { + dol_syslog(var_export($paymentintent, true), LOG_DEBUG); - // Create payment intent and charge payment (confirmnow = true) - $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $invoice, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1); - - $charge = new stdClass(); - //erics add processing sepa is like success ? - if ($paymentintent->status === 'succeeded' || $paymentintent->status === 'processing') { - $charge->status = 'ok'; - $charge->id = $paymentintent->id; - $charge->customer = $customer->id; - } elseif ($paymentintent->status === 'requires_action') { - //paymentintent->status may be => 'requires_action' (no error in such a case) - dol_syslog(var_export($paymentintent, true), LOG_DEBUG); - - $charge->status = 'failed'; - $charge->customer = $customer->id; - $charge->failure_code = $stripe->code; - $charge->failure_message = $stripe->error; - $charge->failure_declinecode = $stripe->declinecode; - $stripefailurecode = $stripe->code; - $stripefailuremessage = 'Action required. Contact the support at ';// . $conf->global->SELLYOURSAAS_MAIN_EMAIL; - $stripefailuredeclinecode = $stripe->declinecode; - } else { - dol_syslog(var_export($paymentintent, true), LOG_DEBUG); - - $charge->status = 'failed'; - $charge->customer = $customer->id; - $charge->failure_code = $stripe->code; - $charge->failure_message = $stripe->error; - $charge->failure_declinecode = $stripe->declinecode; - $stripefailurecode = $stripe->code; - $stripefailuremessage = $stripe->error; - $stripefailuredeclinecode = $stripe->declinecode; - } - - //var_dump("stripefailurecode=".$stripefailurecode." stripefailuremessage=".$stripefailuremessage." stripefailuredeclinecode=".$stripefailuredeclinecode); - //exit; + $charge->status = 'failed'; + $charge->customer = $customer->id; + $charge->failure_code = $stripe->code; + $charge->failure_message = $stripe->error; + $charge->failure_declinecode = $stripe->declinecode; + $stripefailurecode = $stripe->code; + $stripefailuremessage = $stripe->error; + $stripefailuredeclinecode = $stripe->declinecode; } + //var_dump("stripefailurecode=".$stripefailurecode." stripefailuremessage=".$stripefailuremessage." stripefailuredeclinecode=".$stripefailuredeclinecode); + //exit; + // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) if (empty($charge) || $charge->status == 'failed') { - dol_syslog('Failed to charge card or payment mode ' . $stripecard->id . ' stripefailurecode=' . $stripefailurecode . ' stripefailuremessage=' . $stripefailuremessage . ' stripefailuredeclinecode=' . $stripefailuredeclinecode, LOG_WARNING); + dol_syslog('Failed to charge payment mode ' . $stripecard->id . ' stripefailurecode=' . $stripefailurecode . ' stripefailuremessage=' . $stripefailuremessage . ' stripefailuredeclinecode=' . $stripefailuredeclinecode, LOG_WARNING); // Save a stripe payment was in error $this->stripechargeerror++; @@ -1202,20 +1166,20 @@ abstract class CommonInvoice extends CommonObject $errmsg .= ($stripefailuredeclinecode ? ' - ' . $stripefailuredeclinecode : ''); } - $description = 'Stripe payment ERROR from doTakePaymentStripeForThirdparty: ' . $FULLTAG; + $description = 'Stripe payment ERROR from makeStripeSepaRequest: ' . $FULLTAG; $postactionmessages[] = $errmsg . ' (' . $stripearrayofkeys['publishable_key'] . ')'; $this->errors[] = $errmsg; } else { - dol_syslog('Successfuly charge card ' . $stripecard->id); + dol_syslog('Successfuly charge direct debit ' . $stripecard->id); - $postactionmessages[] = 'Success to charge card (' . $charge->id . ' with ' . $stripearrayofkeys['publishable_key'] . ')'; + $postactionmessages[] = 'Success to charge direct debit (' . $charge->id . ' with ' . $stripearrayofkeys['publishable_key'] . ')'; // Save a stripe payment was done in realy life so later we will be able to force a commit on recorded payments // even if in batch mode (method doTakePaymentStripe), we will always make all action in one transaction with a forced commit. $this->stripechargedone++; // Default description used for label of event. Will be overwrite by another value later. - $description = 'Stripe payment OK (' . $charge->id . ') from doTakePaymentStripeForThirdparty: ' . $FULLTAG; + $description = 'Stripe payment OK (' . $charge->id . ') from makeStripeSepaRequest: ' . $FULLTAG; $db = $this->db; @@ -1300,13 +1264,8 @@ abstract class CommonInvoice extends CommonObject if (!$errorforinvoice && isModEnabled('banque')) { dol_syslog('* Add payment to bank'); + // The bank used is the one defined into Stripe setup $bankaccountid = 0; - if ($paymentmethod == 'paybox') { - $bankaccountid = $conf->global->PAYBOX_BANK_ACCOUNT_FOR_PAYMENTS; - } - if ($paymentmethod == 'paypal') { - $bankaccountid = $conf->global->PAYPAL_BANK_ACCOUNT_FOR_PAYMENTS; - } if ($paymentmethod == 'stripe') { $bankaccountid = $conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS; } @@ -1323,7 +1282,7 @@ abstract class CommonInvoice extends CommonObject $error++; $errorforinvoice++; } else { - $postactionmessages[] = 'Bank transaction of payment created (by doTakePaymentStripeForThirdparty)'; + $postactionmessages[] = 'Bank transaction of payment created (by makeStripeSepaRequest)'; } } else { $postactionmessages[] = 'Setup of bank account to use in module ' . $paymentmethod . ' was not set. No way to record the payment.'; @@ -1334,55 +1293,24 @@ abstract class CommonInvoice extends CommonObject } if ($ispostactionok < 1) { - $description = 'Stripe payment OK (' . $charge->id . ' - ' . $amounttopay . ' ' . $conf->currency . ') but post action KO from doTakePaymentStripeForThirdparty: ' . $FULLTAG; + $description = 'Stripe payment OK (' . $charge->id . ' - ' . $amounttopay . ' ' . $conf->currency . ') but post action KO from makeStripeSepaRequest: ' . $FULLTAG; } else { - $description = 'Stripe payment+post action OK (' . $charge->id . ' - ' . $amounttopay . ' ' . $conf->currency . ') from doTakePaymentStripeForThirdparty: ' . $FULLTAG; + $description = 'Stripe payment+post action OK (' . $charge->id . ' - ' . $amounttopay . ' ' . $conf->currency . ') from makeStripeSepaRequest: ' . $FULLTAG; } } $object = $invoice; - // Send emails - $labeltouse = 'InvoicePaymentSuccess'; - $sendemailtocustomer = 1; - - if (empty($charge) || $charge->status == 'failed') { - $labeltouse = 'InvoicePaymentFailure'; - if ($noemailtocustomeriferror) { - $sendemailtocustomer = 0; - } // $noemailtocustomeriferror is set when error already reported on myaccount screen - } - - // Track an event - if (empty($charge) || $charge->status == 'failed') { - $actioncode = 'PAYMENT_STRIPE_KO'; - $extraparams = $stripefailurecode; - $extraparams .= (($extraparams && $stripefailuremessage) ? ' - ' : '') . $stripefailuremessage; - $extraparams .= (($extraparams && $stripefailuredeclinecode) ? ' - ' : '') . $stripefailuredeclinecode; - } else { - $actioncode = 'PAYMENT_STRIPE_OK'; - $extraparams = ''; - } + $actioncode = ''; + $extraparams = ''; } else { $error++; $errorforinvoice++; - dol_syslog("No card or payment method found for this stripe customer " . $customer->id, LOG_WARNING); - $this->errors[] = 'Failed to get card | payment method for stripe customer = ' . $customer->id; - - $labeltouse = 'InvoicePaymentFailure'; - $sendemailtocustomer = 1; - if ($noemailtocustomeriferror) { - $sendemailtocustomer = 0; - } // $noemailtocustomeriferror is set when error already reported on myaccount screen - - $description = 'Failed to find or use the payment mode - no credit card defined for the customer account'; - $stripefailurecode = 'BADPAYMENTMODE'; - $stripefailuremessage = 'Failed to find or use the payment mode - no credit card defined for the customer account'; - $postactionmessages[] = $description . ' (' . $stripearrayofkeys['publishable_key'] . ')'; - + dol_syslog("No direct debit payment method found for this stripe customer " . $customer->id, LOG_WARNING); + $this->errors[] = 'Failed to get direct debit payment method for stripe customer = ' . $customer->id; $object = $invoice; - $actioncode = 'PAYMENT_STRIPE_KO'; + $actioncode = ''; $extraparams = ''; } } else { @@ -1427,6 +1355,7 @@ abstract class CommonInvoice extends CommonObject $extraparams = ''; } + /* // Send email + create action after if ($sendemailtocustomer && $labeltouse) { dol_syslog("* Send email with result of payment - " . $labeltouse); @@ -1537,6 +1466,7 @@ abstract class CommonInvoice extends CommonObject } } } + */ if ($description) { dol_syslog("* Record event for payment result - " . $description); @@ -1588,18 +1518,12 @@ abstract class CommonInvoice extends CommonObject $this->errors[] = "Remain to pay is null for the invoice " . $this->id . " " . $this->ref . ". Why is the invoice not classified 'Paid' ?"; } - $sql = "INSERT INTO ".MAIN_DB_PREFIX."prelevement_demande("; - $sql .= "fk_facture, "; - $sql .= " amount, date_demande, fk_user_demande, ext_payment_id, ext_payment_site, sourcetype, entity)"; - $sql .= " VALUES (".$this->id; - $sql .= ",".((float) price2num($amount)); - $sql .= ",'".$this->db->idate($now)."'"; - $sql .= ",".((int) $fuser->id); - $sql .= ",'".$this->db->escape($stripe_id)."'"; - $sql .= ",'".$this->db->escape($stripe_uri)."'"; - $sql .= ",'".$this->db->escape($sourcetype)."'"; - $sql .= ",".$conf->entity; - $sql .= ")"; + // TODO Create a prelevement_bon ? + // For the moment no + + // We must update the direct debit payment request as "done" + $sql = "UPDATE".MAIN_DB_PREFIX."prelevement_demande SET traite = 1, date_traite = '".$this->db->idate(dol_now())."'"; + $sql .= "WHERE rowid = ".((int) $did); dol_syslog(get_class($this)."::makeStripeSepaRequest", LOG_DEBUG); $resql = $this->db->query($sql); From 1fe589ac3e2d67effa6b8722fe47a8e17309b58b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 14:43:09 +0100 Subject: [PATCH 646/816] Fix debug payment using SEPA Stripe --- htdocs/core/class/commoninvoice.class.php | 45 +++++++++++++++++++---- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 7a8b5e3cbf7..93d125291ef 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -1299,18 +1299,49 @@ abstract class CommonInvoice extends CommonObject } } - $object = $invoice; + $object = $this; - $actioncode = ''; - $extraparams = ''; + // Send emails + $labeltouse = 'InvoicePaymentSuccess'; + $sendemailtocustomer = 1; + + if (empty($charge) || $charge->status == 'failed') { + $labeltouse = 'InvoicePaymentFailure'; + if ($noemailtocustomeriferror) { + $sendemailtocustomer = 0; + } // $noemailtocustomeriferror is set when error already reported on myaccount screen + } + + // Track an event + if (empty($charge) || $charge->status == 'failed') { + $actioncode = 'PAYMENT_STRIPE_KO'; + $extraparams = $stripefailurecode; + $extraparams .= (($extraparams && $stripefailuremessage) ? ' - ' : '') . $stripefailuremessage; + $extraparams .= (($extraparams && $stripefailuredeclinecode) ? ' - ' : '') . $stripefailuredeclinecode; + } else { + $actioncode = 'PAYMENT_STRIPE_OK'; + $extraparams = ''; + } } else { $error++; $errorforinvoice++; dol_syslog("No direct debit payment method found for this stripe customer " . $customer->id, LOG_WARNING); $this->errors[] = 'Failed to get direct debit payment method for stripe customer = ' . $customer->id; - $object = $invoice; - $actioncode = ''; + $labeltouse = 'InvoicePaymentFailure'; + $sendemailtocustomer = 1; + if ($noemailtocustomeriferror) { + $sendemailtocustomer = 0; + } // $noemailtocustomeriferror is set when error already reported on myaccount screen + + $description = 'Failed to find or use the payment mode - no credit card defined for the customer account'; + $stripefailurecode = 'BADPAYMENTMODE'; + $stripefailuremessage = 'Failed to find or use the payment mode - no credit card defined for the customer account'; + $postactionmessages[] = $description . ' (' . $stripearrayofkeys['publishable_key'] . ')'; + + $object = $this; + + $actioncode = 'PAYMENT_STRIPE_KO'; $extraparams = ''; } } else { @@ -1322,7 +1353,7 @@ abstract class CommonInvoice extends CommonObject $stripefailurecode = ''; $stripefailuremessage = ''; - $object = $invoice; + $object = $this; $actioncode = ''; $extraparams = ''; @@ -1349,7 +1380,7 @@ abstract class CommonInvoice extends CommonObject $stripefailuremessage = 'Failed to find or use your payment mode (no payment mode for this customer id)'; $postactionmessages = []; - $object = $invoice; + $object = $this; $actioncode = 'PAYMENT_STRIPE_KO'; $extraparams = ''; From 6d8f80d46e778dc65b5edbad47d0e3ae69a95b18 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 18 Jan 2023 16:10:21 +0100 Subject: [PATCH 647/816] fix: module builder, backport workgin solution form 15.0 --- htdocs/modulebuilder/index.php | 50 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 25034194119..fcfea65dd83 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1295,33 +1295,35 @@ if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors'); } - } - if (!$error) { - $addfieldentry = array( - 'name'=>GETPOST('propname', 'aZ09'), - 'label'=>GETPOST('proplabel', 'alpha'), - 'type'=>GETPOST('proptype', 'alpha'), - 'arrayofkeyval'=>GETPOST('proparrayofkeyval', 'restricthtml'), // Example json string '{"0":"Draft","1":"Active","-1":"Cancel"}' - 'visible'=>GETPOST('propvisible', 'int'), - 'enabled'=>GETPOST('propenabled', 'int'), - 'position'=>GETPOST('propposition', 'int'), - 'notnull'=>GETPOST('propnotnull', 'int'), - 'index'=>GETPOST('propindex', 'int'), - 'searchall'=>GETPOST('propsearchall', 'int'), - 'isameasure'=>GETPOST('propisameasure', 'int'), - 'comment'=>GETPOST('propcomment', 'alpha'), - 'help'=>GETPOST('prophelp', 'alpha'), - 'css'=>GETPOST('propcss', 'aZ09'), - 'cssview'=>GETPOST('propcssview', 'aZ09'), - 'csslist'=>GETPOST('propcsslist', 'aZ09'), - 'default'=>GETPOST('propdefault', 'restricthtml'), - 'noteditable'=>intval(GETPOST('propnoteditable', 'int')), - ); + if (!$error && !GETPOST('regenerateclasssql')&& !GETPOST('regeneratemissing')) { + $addfieldentry = array( + 'name'=>GETPOST('propname', 'aZ09'), + 'label'=>GETPOST('proplabel', 'alpha'), + 'type'=>GETPOST('proptype', 'alpha'), + 'arrayofkeyval'=>GETPOST('proparrayofkeyval', 'restricthtml'), // Example json string '{"0":"Draft","1":"Active","-1":"Cancel"}' + 'visible'=>GETPOST('propvisible', 'int'), + 'enabled'=>GETPOST('propenabled', 'int'), + 'position'=>GETPOST('propposition', 'int'), + 'notnull'=>GETPOST('propnotnull', 'int'), + 'index'=>GETPOST('propindex', 'int'), + 'searchall'=>GETPOST('propsearchall', 'int'), + 'isameasure'=>GETPOST('propisameasure', 'int'), + 'comment'=>GETPOST('propcomment', 'alpha'), + 'help'=>GETPOST('prophelp', 'alpha'), + 'css'=>GETPOST('propcss', 'aZ09'), + 'cssview'=>GETPOST('propcssview', 'aZ09'), + 'csslist'=>GETPOST('propcsslist', 'aZ09'), + 'default'=>GETPOST('propdefault', 'restricthtml'), + 'noteditable'=>intval(GETPOST('propnoteditable', 'int')), + ); - if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) { - $addfieldentry['arrayofkeyval'] = json_decode($addfieldentry['arrayofkeyval'], true); + if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) { + $addfieldentry['arrayofkeyval'] = json_decode($addfieldentry['arrayofkeyval'], true); + } } + } else { + $addfieldentry = array(); } /*if (GETPOST('regeneratemissing')) From a00fa5a192dd339c8ca49e7f489ce4ecb31a5feb Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Wed, 18 Jan 2023 16:11:22 +0100 Subject: [PATCH 648/816] FIX: Do not convert negative line to discount if variable is active --- htdocs/commande/list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index eb8b824ef3e..2211422f3c5 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -9,7 +9,7 @@ * Copyright (C) 2015-2018 Frédéric France * Copyright (C) 2015 Marcos García * Copyright (C) 2015 Jean-François Ferry - * Copyright (C) 2016-2021 Ferran Marcet + * Copyright (C) 2016-2023 Ferran Marcet * Copyright (C) 2018 Charlene Benke * Copyright (C) 2021 Anthony Berton * @@ -403,7 +403,7 @@ if (empty($reshook)) { $desc = dol_concatdesc($desc, $langs->trans("Order").' '.$cmd->ref.' - '.dol_print_date($cmd->date, 'day')); } - if ($lines[$i]->subprice < 0) { + if ($lines[$i]->subprice < 0 && empty($conf->global->INVOICE_KEEP_DISCOUNT_LINES_AS_IN_ORIGIN)) { // Negative line, we create a discount line $discount = new DiscountAbsolute($db); $discount->fk_soc = $objecttmp->socid; From a3d4eb404df858202eeacf5f872d6fc3d7b1cd3d Mon Sep 17 00:00:00 2001 From: GregM Date: Wed, 18 Jan 2023 17:36:05 +0100 Subject: [PATCH 649/816] Fix contact firstname lastname extrafields --- htdocs/core/class/extrafields.class.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 1d5bd8dc7ef..6644548d87c 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1457,15 +1457,15 @@ class ExtraFields $labeltoshow = dol_trunc($labeltoshow, 45); if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) { + $labeltoshow = ''; foreach ($fields_label as $field_toshow) { $translabel = $langs->trans($obj->$field_toshow); if ($translabel != $obj->$field_toshow) { - $labeltoshow = dol_trunc($translabel, 18).' '; + $labeltoshow .= ' '.dol_trunc($translabel, 18).' '; } else { - $labeltoshow = dol_trunc($obj->$field_toshow, 18).' '; + $labeltoshow .= ' '.dol_trunc($obj->$field_toshow, 18).' '; } } - $data[$obj->rowid] = $labeltoshow; } else { if (!$notrans) { @@ -1774,17 +1774,20 @@ class ExtraFields $fields_label = explode('|', $InfoFieldList[1]); if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) { if (is_array($fields_label) && count($fields_label) > 1) { + $label = '
  • '; foreach ($fields_label as $field_toshow) { $translabel = ''; if (!empty($obj->$field_toshow)) { $translabel = $langs->trans($obj->$field_toshow); } if ($translabel != $field_toshow) { - $toprint[] = '
  • '.dol_trunc($translabel, 18).'
  • '; + $label .= ' '.dol_trunc($translabel, 18); } else { - $toprint[] = '
  • '.$obj->$field_toshow.'
  • '; + $label .= ' '.$obj->$field_toshow; } } + $label .= ''; + $toprint[] = $label; } else { $translabel = ''; if (!empty($obj->{$InfoFieldList[1]})) { From 4637f8a65e900a61e3f64bcc796e7ad882a004cf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 19:11:15 +0100 Subject: [PATCH 650/816] Fix security --- SECURITY.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index b121b606180..e095b64fdff 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -53,16 +53,17 @@ ONLY vulnerabilities discovered, when the following setup on test platform is us * $dolibarr_nocsrfcheck must be kept to the value 0 into conf.php (this is the default value) * $dolibarr_main_force_https must be set to something else than 0. * The constant MAIN_SECURITY_CSRF_WITH_TOKEN must be set to 3 into backoffice menu Home - Setup - Other (this protection should be set to 3 soon by default) -* The module DebugBar and ModuleBuilder must NOT be enabled (by default, these modules are not enabled. They are developer tools) * ONLY security reports on modules provided by default and with the "stable" status are valid (troubles into "experimental", "developement" or external modules are not valid vulnerabilities). * The root of web server must link to htdocs and the documents directory must be outside of the web server root (this is the default when using the default installer but may differs with external installer). * The web server setup must be done so that only the documents directory is in write mode. The root directory called htdocs must be read-only. * CSRF attacks are accepted but double check that you have set MAIN_SECURITY_CSRF_WITH_TOKEN to value 3. +* The module DebugBar and ModuleBuilder must NOT be enabled (by default, these modules are not enabled. They are developer tools) * Ability for a high level user to edit web site pages into the CMS by including HTML or Javascript is an expected feature. Vulnerabilities into the website module are validated only if HTML or Javascript injection can be done by a non allowed user. +* Fail2ban rules for rate limit on the login page,password forgotten page and all public pages (/public/*) must be installed as recommendend into the section "About - Admin tools - Section Access limits and mitigation". Scope is the web application (back office) and the APIs. -## Qualifying vulnerabilities for reporting +## Example of vulnerabilities Qualified for reporting. * Remote code execution (RCE) * Local files access and manipulation (LFI, RFI, XXE, SSRF, XSPA) @@ -78,7 +79,7 @@ Scope is the web application (back office) and the APIs. * Software version disclosure (for non admin users only) * Stack traces or path disclosure (for non admin users only) -## Non-qualifying vulnerabilities for reporting +## Example of vulnerabilities non Non-qualified for reporting. * "Self" XSS * SSL/TLS best practices @@ -95,3 +96,4 @@ Scope is the web application (back office) and the APIs. * Software version or private IP disclosure when logged user is admin * Stack traces or path disclosure when logged user is admin * Any vulnerabilities due to a configuration different than the one defined into chapter "Scope for qualified vulnerabilities". +* Brute force attacks on login page, password forgotten page or any public pages (/public/*) are not qualified if the fail2ban recommended fail2ban rules were not installed. From 40e007bb6195735ebc4410d413916594247fd3cd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 19:54:38 +0100 Subject: [PATCH 651/816] More generic error message --- htdocs/api/class/api_access.class.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/htdocs/api/class/api_access.class.php b/htdocs/api/class/api_access.class.php index f885677225e..37b7b079716 100644 --- a/htdocs/api/class/api_access.class.php +++ b/htdocs/api/class/api_access.class.php @@ -142,12 +142,28 @@ class DolibarrApiAccess implements iAuthenticate if (!$login) { throw new RestException(503, 'Error when searching login user from api key'); } + + $genericmessageerroruser = 'Error user not valid (not found or bad status or bad validity dates) (conf->entity='.$conf->entity.')'; + $fuser = new User($this->db); $result = $fuser->fetch('', $login, '', 0, (empty($userentity) ? -1 : $conf->entity)); // If user is not entity 0, we search in working entity $conf->entity (that may have been forced to a different value than user entity) if ($result <= 0) { - throw new RestException(503, 'Error when fetching user :'.$fuser->error.' (conf->entity='.$conf->entity.')'); + throw new RestException(503, $genericmessageerroruser); } + $now = dol_now(); + + // Check date start validity + if ($fuser->datestartvalidity && $this->db->jdate($fuser->datestartvalidity) > $now) { + throw new RestException(503, $genericmessageerroruser); + } + // Check date end validity + if ($fuser->dateendvalidity && $this->db->jdate($fuser->dateendvalidity) < dol_get_first_hour($now)) { + throw new RestException(503, $genericmessageerroruser); + } + + + // User seems valid $fuser->getrights(); // Set the property $user to the $user of API From aa273d215572d896ba26f1dae8489edd1238e4c2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 20:11:12 +0100 Subject: [PATCH 652/816] Update index.php --- htdocs/modulebuilder/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index fcfea65dd83..052b1189b3d 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -1296,7 +1296,7 @@ if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors'); } - if (!$error && !GETPOST('regenerateclasssql')&& !GETPOST('regeneratemissing')) { + if (!$error && !GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) { $addfieldentry = array( 'name'=>GETPOST('propname', 'aZ09'), 'label'=>GETPOST('proplabel', 'alpha'), From c31aee2e27f004486945586a9d65c899d19dd689 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 20:42:29 +0100 Subject: [PATCH 653/816] Doc --- htdocs/core/class/html.formticket.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index be515a2abf3..5692a285dda 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -49,12 +49,12 @@ class FormTicket public $db; /** - * @var string The track_id of the ticket. Used also for the $keytoavoidconflict to name session vars to upload files. + * @var string A hash value of the ticket. Duplicate of ref but for public purposes. */ public $track_id; /** - * @var string trackid + * @var string Email $trackid. Used also for the $keytoavoidconflict to name session vars to upload files. */ public $trackid; From ea6964ccd059de8382ccec91d4f2ad2f3cc506ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Wed, 18 Jan 2023 22:03:38 +0100 Subject: [PATCH 654/816] fix undeclared properties for php 8.2 --- htdocs/adherents/class/adherent.class.php | 15 ++++++++++++++- htdocs/adherents/class/adherent_type.class.php | 13 +++++++++++++ htdocs/core/class/commonobject.class.php | 9 +++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 225261e8f9f..99e84d61026 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -7,7 +7,7 @@ * Copyright (C) 2009-2017 Regis Houssin * Copyright (C) 2014-2018 Alexandre Spangaro * Copyright (C) 2015 Marcos García - * Copyright (C) 2015-2022 Frédéric France + * Copyright (C) 2015-2023 Frédéric France * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Juanjo Menent * Copyright (C) 2018-2019 Thibault FOUCART @@ -89,6 +89,11 @@ class Adherent extends CommonObject */ public $pass_indatabase_crypted; + /** + * @var string fullname + */ + public $fullname; + /** * @var string company name * @deprecated @@ -292,6 +297,10 @@ class Adherent extends CommonObject public $first_subscription_date; + public $first_subscription_date_start; + + public $first_subscription_date_end; + public $first_subscription_amount; public $last_subscription_date; @@ -304,6 +313,10 @@ class Adherent extends CommonObject public $subscriptions = array(); + /** + * @var string ip + */ + public $ip; // Fields loaded by fetchPartnerships() from partnership table diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 0a4663f8149..915502a9e96 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -129,6 +129,19 @@ class AdherentType extends CommonObject /** @var string string other */ public $other = array(); + /** + * @var string description + */ + public $description; + + /** + * @var string email + */ + public $email; + + /** + * @var array multilangs + */ public $multilangs = array(); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ecf03696d7a..9f28f6c0d70 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -593,6 +593,15 @@ abstract class CommonObject protected $labelStatus; protected $labelStatusShort; + /** + * @var array nb used in load_stateboard + */ + public $nb = array(); + + /** + * @var string output + */ + public $output; /** * @var array List of child tables. To test if we can delete object. From cccba873a8f5eaf49e45ffa61eb43cb3635c6ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Wed, 18 Jan 2023 22:20:25 +0100 Subject: [PATCH 655/816] fix undeclared properties for php 8.2 --- htdocs/adherents/class/adherent.class.php | 7 +++++++ htdocs/contact/class/contact.class.php | 15 +++++++++++++++ htdocs/user/class/user.class.php | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 99e84d61026..2d8433de0c4 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -94,6 +94,13 @@ class Adherent extends CommonObject */ public $fullname; + /** + * @var string The civility code, not an integer + */ + public $civility_id; + public $civility_code; + public $civility; + /** * @var string company name * @deprecated diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 67b3ce2a38a..8c3991cabaf 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -130,6 +130,16 @@ class Contact extends CommonObject public $civility_code; public $civility; + /** + * @var int egroupware_id + */ + public $egroupware_id; + + /** + * @var int birthday_alert + */ + public $birthday_alert; + /** * @var string The civilite code, not an integer * @deprecated @@ -137,6 +147,11 @@ class Contact extends CommonObject */ public $civilite; + /** + * @var string fullname + */ + public $fullname; + /** * @var string Address */ diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 22556d3e1c2..3dc74832503 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -76,6 +76,11 @@ class User extends CommonObject public $employee; public $civility_code; + /** + * @var string fullname + */ + public $fullname; + /** * @var string gender */ From 0f475783deb28af48e98141c9733f31c471a6114 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 22:27:52 +0100 Subject: [PATCH 656/816] Enhance method getKanbanView --- htdocs/adherents/class/adherent.class.php | 3 +- .../adherents/class/adherent_type.class.php | 5 +-- htdocs/adherents/class/subscription.class.php | 3 +- htdocs/bom/class/bom.class.php | 5 +-- htdocs/comm/propal/class/propal.class.php | 5 +-- htdocs/compta/bank/class/account.class.php | 5 +-- .../bank/class/paymentvarious.class.php | 5 +-- .../cashcontrol/class/cashcontrol.class.php | 5 +-- htdocs/compta/facture/class/facture.class.php | 5 +-- .../compta/localtax/class/localtax.class.php | 5 +-- .../cheque/class/remisecheque.class.php | 5 +-- .../class/bonprelevement.class.php | 5 +-- .../sociales/class/chargesociales.class.php | 5 +-- htdocs/compta/tva/class/tva.class.php | 5 +-- htdocs/contact/class/contact.class.php | 3 +- htdocs/contrat/class/contrat.class.php | 5 +-- htdocs/core/class/commonobject.class.php | 28 ---------------- htdocs/core/class/commonobjectline.class.php | 33 ------------------- htdocs/core/class/commonorder.class.php | 3 +- htdocs/don/class/don.class.php | 5 +-- .../class/expensereport.class.php | 5 +-- .../class/paymentexpensereport.class.php | 5 +-- htdocs/fichinter/class/fichinter.class.php | 5 +-- .../class/fournisseur.commande.class.php | 5 +-- .../fourn/class/fournisseur.facture.class.php | 5 +-- htdocs/holiday/class/holiday.class.php | 14 ++++---- htdocs/holiday/list.php | 13 ++++++-- htdocs/hrm/class/evaluation.class.php | 5 +-- htdocs/hrm/class/job.class.php | 5 +-- htdocs/hrm/class/skill.class.php | 5 +-- .../class/knowledgerecord.class.php | 5 +-- .../template/class/myobject.class.php | 5 ++- htdocs/mrp/class/mo.class.php | 5 +-- htdocs/product/stock/class/entrepot.class.php | 3 +- htdocs/projet/class/task.class.php | 5 +-- .../class/recruitmentcandidature.class.php | 5 +-- .../class/recruitmentjobposition.class.php | 5 +-- htdocs/salaries/class/paymentsalary.class.php | 5 +-- htdocs/salaries/class/salary.class.php | 5 +-- .../class/supplier_proposal.class.php | 5 +-- htdocs/ticket/class/ticket.class.php | 5 +-- htdocs/user/class/user.class.php | 3 +- htdocs/user/class/usergroup.class.php | 3 +- 43 files changed, 125 insertions(+), 144 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 225261e8f9f..fb72636ef1a 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -3208,9 +3208,10 @@ class Adherent extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Array of data * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { $return = '
    '; diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 0a4663f8149..ea60e9c1fcd 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -933,9 +933,10 @@ class AdherentType extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs,$user; $return = '
    '; diff --git a/htdocs/adherents/class/subscription.class.php b/htdocs/adherents/class/subscription.class.php index 12e19fd9c3a..b5079676603 100644 --- a/htdocs/adherents/class/subscription.class.php +++ b/htdocs/adherents/class/subscription.class.php @@ -510,9 +510,10 @@ class Subscription extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Array of data * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { $return = '
    '; $return .= '
    '; diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 1e28aafffe2..d7982a44069 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1523,9 +1523,10 @@ class BOM extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $db,$langs; $prod = new Product($db); diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 1541478a321..c4328328f18 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -3921,9 +3921,10 @@ class Propal extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index fe0a267dc83..e144677832f 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -1751,9 +1751,10 @@ class Account extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/compta/bank/class/paymentvarious.class.php b/htdocs/compta/bank/class/paymentvarious.class.php index 857b49d1576..d5888e0e7a1 100644 --- a/htdocs/compta/bank/class/paymentvarious.class.php +++ b/htdocs/compta/bank/class/paymentvarious.class.php @@ -773,9 +773,10 @@ class PaymentVarious extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/compta/cashcontrol/class/cashcontrol.class.php b/htdocs/compta/cashcontrol/class/cashcontrol.class.php index 01bebc35f5d..8cc3c93b59c 100644 --- a/htdocs/compta/cashcontrol/class/cashcontrol.class.php +++ b/htdocs/compta/cashcontrol/class/cashcontrol.class.php @@ -474,9 +474,10 @@ class CashControl extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 431c3b0a2a3..561ebf3e9ed 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -5758,9 +5758,10 @@ class Facture extends CommonInvoice * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { $return = '
    '; $return .= '
    '; diff --git a/htdocs/compta/localtax/class/localtax.class.php b/htdocs/compta/localtax/class/localtax.class.php index d2300128550..a6db785b779 100644 --- a/htdocs/compta/localtax/class/localtax.class.php +++ b/htdocs/compta/localtax/class/localtax.class.php @@ -634,9 +634,10 @@ class Localtax extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/compta/paiement/cheque/class/remisecheque.class.php b/htdocs/compta/paiement/cheque/class/remisecheque.class.php index 1e4e7d05a7d..6666f0fe1c4 100644 --- a/htdocs/compta/paiement/cheque/class/remisecheque.class.php +++ b/htdocs/compta/paiement/cheque/class/remisecheque.class.php @@ -1025,9 +1025,10 @@ class RemiseCheque extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 24db7fb5b64..b9d1fd7c54a 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -2412,9 +2412,10 @@ class BonPrelevement extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; diff --git a/htdocs/compta/sociales/class/chargesociales.class.php b/htdocs/compta/sociales/class/chargesociales.class.php index b5e98b3b62e..cacc2280f53 100644 --- a/htdocs/compta/sociales/class/chargesociales.class.php +++ b/htdocs/compta/sociales/class/chargesociales.class.php @@ -754,9 +754,10 @@ class ChargeSociales extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/compta/tva/class/tva.class.php b/htdocs/compta/tva/class/tva.class.php index 78fb178ff27..2ec1199dd29 100644 --- a/htdocs/compta/tva/class/tva.class.php +++ b/htdocs/compta/tva/class/tva.class.php @@ -911,9 +911,10 @@ class Tva extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 67b3ce2a38a..8c5c84a0d61 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -2123,9 +2123,10 @@ class Contact extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Array of data * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index ddec606a82c..539d7b63f31 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2796,9 +2796,10 @@ class Contrat extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ecf03696d7a..40c05e06b91 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -770,34 +770,6 @@ abstract class CommonObject } } - /** - * Return clicable link of object (with eventually picto) - * - * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. - */ - public function getKanbanView($option = '') - { - $return = '
    '; - $return .= '
    '; - $return .= ''; - $return .= img_picto('', $this->picto); - $return .= ''; - $return .= '
    '; - $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).''; - if (property_exists($this, 'label')) { - $return .= '
    '.$this->label.''; - } - if (method_exists($this, 'getLibStatut')) { - $return .= '
    '.$this->getLibStatut(5).'
    '; - } - $return .= '
    '; - $return .= '
    '; - $return .= '
    '; - - return $return; - } - /** * Return full address of contact * diff --git a/htdocs/core/class/commonobjectline.class.php b/htdocs/core/class/commonobjectline.class.php index b116519ad53..972ab7e4476 100644 --- a/htdocs/core/class/commonobjectline.class.php +++ b/htdocs/core/class/commonobjectline.class.php @@ -166,37 +166,4 @@ abstract class CommonObjectLine extends CommonObject { return 0; } - - /** - * Return clicable link of object (with eventually picto) - * - * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. - */ - public function getKanbanView($option = '') - { - global $langs; - $return = '
    '; - $return .= '
    '; - $return .= ''; - $return .= img_picto('', $this->picto); - //$return .= ''; // Can be image - $return .= ''; - $return .= '
    '; - $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : '').''; - if (property_exists($this, 'date_delivery')) { - $return .= '
    '.dol_print_date($this->db->jdate($this->date_delivery), "dayhour").''; - } - if (property_exists($this, 'town') && !empty($this->town)) { - $return .= '
    '.$langs->trans("Town").''; - $return .= ' : '.$this->town.''; - } - if (method_exists($this, 'getLibStatut')) { - $return .= '
    '.$this->getLibStatut(5).'
    '; - } - $return .= '
    '; - $return .= '
    '; - $return .= '
    '; - return $return; - } } diff --git a/htdocs/core/class/commonorder.class.php b/htdocs/core/class/commonorder.class.php index 9002d50ed39..65ae367c3b2 100644 --- a/htdocs/core/class/commonorder.class.php +++ b/htdocs/core/class/commonorder.class.php @@ -37,9 +37,10 @@ abstract class CommonOrder extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Array of data * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs, $conf; diff --git a/htdocs/don/class/don.class.php b/htdocs/don/class/don.class.php index c1d09a6cdd0..acd3b34961c 100644 --- a/htdocs/don/class/don.class.php +++ b/htdocs/don/class/don.class.php @@ -1146,9 +1146,10 @@ class Don extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index f56167651ab..06adcd92770 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -2682,9 +2682,10 @@ class ExpenseReport extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs, $selected,$arrayofselected; $return = '
    '; diff --git a/htdocs/expensereport/class/paymentexpensereport.class.php b/htdocs/expensereport/class/paymentexpensereport.class.php index 5ca4135dc30..053f46d20cf 100644 --- a/htdocs/expensereport/class/paymentexpensereport.class.php +++ b/htdocs/expensereport/class/paymentexpensereport.class.php @@ -718,9 +718,10 @@ class PaymentExpenseReport extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 4a7872b2859..450e2c63af3 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -1461,9 +1461,10 @@ class Fichinter extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 5355e969443..910cebdb38e 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -3551,9 +3551,10 @@ class CommandeFournisseur extends CommonOrder * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 9ca933b7c43..2c45a8d67d5 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -3237,9 +3237,10 @@ class FactureFournisseur extends CommonInvoice * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index e8f56659de9..e4a82be6ea7 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -2423,25 +2423,23 @@ class Holiday extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Label of holiday type (if known) * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { - global $langs, $selected; + global $langs; + $return = '
    '; $return .= '
    '; $return .= ''; $return .= img_picto('', $this->picto); $return .= ''; $return .= '
    '; - $return .= ''.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).''; - if (property_exists($this, 'fk_user') && !empty($this->id)) { - $return .= '| '.$this->fk_user.''; - $return .= ''; - } + $return .= ''.$arraydata['user']->getNomUrl(-1).''; if (property_exists($this, 'fk_type')) { $return .= '
    '.$langs->trans("Type").' : '; - $return .= ''.$langs->trans($this->getTypes(1, -1)[$this->fk_type]['code']).''; + $return .= ''.arraydata['labeltype'].''; } if (property_exists($this, 'date_debut') && property_exists($this, 'date_fin')) { $return .= '
    '.dol_print_date($this->date_debut, 'day').''; diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index 56dd3ff2d98..6166ffb3b4e 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -835,15 +835,22 @@ if ($resql) { print '
    '; } - $holidaystatic->fk_type = $holidaystatic->getTypes(1, -1)[$obj->fk_type]['rowid']; - $holidaystatic->fk_user = $userstatic->getNomUrl(1); + $holidaystatic->fk_type = $typeleaves[$obj->fk_type]['rowid']; + // Output Kanban if ($massactionbutton || $massaction) { $selected = 0; if (in_array($object->id, $arrayofselected)) { $selected = 1; } - print $holidaystatic->getKanbanView(''); + if (empty($typeleaves[$obj->fk_type])) { + $labeltypeleavetoshow = $langs->trans("TypeWasDisabledOrRemoved", $obj->fk_type); + } else { + $labeltypeleavetoshow = ($langs->trans($typeleaves[$obj->fk_type]['code']) != $typeleaves[$obj->fk_type]['code'] ? $langs->trans($typeleaves[$obj->fk_type]['code']) : $typeleaves[$obj->fk_type]['label']); + } + + $arraydata = array('user'=>$userstatic, 'labeltype'=>$labeltypeleavetoshow); + print $holidaystatic->getKanbanView('', $arraydata); } if ($i == (min($num, $limit) - 1)) { print '
    '; diff --git a/htdocs/hrm/class/evaluation.class.php b/htdocs/hrm/class/evaluation.class.php index 4a9dd0defde..48cb8cdd0c3 100644 --- a/htdocs/hrm/class/evaluation.class.php +++ b/htdocs/hrm/class/evaluation.class.php @@ -1060,9 +1060,10 @@ class Evaluation extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $selected, $langs; $return = '
    '; diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php index dfed55cebec..1afa8c75647 100644 --- a/htdocs/hrm/class/job.class.php +++ b/htdocs/hrm/class/job.class.php @@ -1059,9 +1059,10 @@ class Job extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $selected, $langs; $return = '
    '; diff --git a/htdocs/hrm/class/skill.class.php b/htdocs/hrm/class/skill.class.php index 5960ef8d351..8b7b6910f2b 100644 --- a/htdocs/hrm/class/skill.class.php +++ b/htdocs/hrm/class/skill.class.php @@ -1118,9 +1118,10 @@ class Skill extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $selected, $langs; $return = '
    '; diff --git a/htdocs/knowledgemanagement/class/knowledgerecord.class.php b/htdocs/knowledgemanagement/class/knowledgerecord.class.php index 4d9aa9d7ed4..3f9f1b40223 100644 --- a/htdocs/knowledgemanagement/class/knowledgerecord.class.php +++ b/htdocs/knowledgemanagement/class/knowledgerecord.class.php @@ -1071,9 +1071,10 @@ class KnowledgeRecord extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs, $selected,$arrayofselected; $return = '
    '; diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 4bee8d9529a..5ac7f8c30de 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -869,10 +869,10 @@ class MyObject extends CommonObject * Return a thumb for kanban views * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Array of data * @return string HTML Code for Kanban thumb. */ - /* - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { $return = '
    '; $return .= '
    '; @@ -893,7 +893,6 @@ class MyObject extends CommonObject return $return; } - */ /** * Return the label of the status diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index f95064454b7..9a7ba6007cc 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -1562,9 +1562,10 @@ class Mo extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index ce5bef9c939..3ce244a4bb1 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -921,9 +921,10 @@ class Entrepot extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Array of data * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { $return = '
    '; diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 6c2e8ad29a4..597e680f8f0 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -2330,9 +2330,10 @@ class Task extends CommonObjectLine * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs, $conf; $return = '
    '; diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index bdbcdb97811..e3dfd4bd135 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -1029,9 +1029,10 @@ class RecruitmentCandidature extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs, $selected,$arrayofselected; $return = '
    '; diff --git a/htdocs/recruitment/class/recruitmentjobposition.class.php b/htdocs/recruitment/class/recruitmentjobposition.class.php index 7ab290e691a..a63e6b012b2 100644 --- a/htdocs/recruitment/class/recruitmentjobposition.class.php +++ b/htdocs/recruitment/class/recruitmentjobposition.class.php @@ -1113,9 +1113,10 @@ class RecruitmentJobPosition extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs, $selected,$arrayofselected,$obj; $return = '
    '; diff --git a/htdocs/salaries/class/paymentsalary.class.php b/htdocs/salaries/class/paymentsalary.class.php index 4817abec6c8..0f141bc3023 100644 --- a/htdocs/salaries/class/paymentsalary.class.php +++ b/htdocs/salaries/class/paymentsalary.class.php @@ -767,9 +767,10 @@ class PaymentSalary extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs, $db; $return = '
    '; diff --git a/htdocs/salaries/class/salary.class.php b/htdocs/salaries/class/salary.class.php index 7f9ea31cdc9..2f7bb36869e 100644 --- a/htdocs/salaries/class/salary.class.php +++ b/htdocs/salaries/class/salary.class.php @@ -712,9 +712,10 @@ class Salary extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 5de7b1d851a..f2e6d19afa8 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -2732,9 +2732,10 @@ class SupplierProposal extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index d390fd6f351..e0f880264f9 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2937,9 +2937,10 @@ class Ticket extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) - * @return string HTML Code for Kanban thumb. + * @param array $arraydata Array of data + * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs, $selected,$arrayofselected,$obj; $return = '
    '; diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 22556d3e1c2..7f61ba2c7ab 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2996,9 +2996,10 @@ class User extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Array of data * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { $return = '
    '; $return .= '
    '; diff --git a/htdocs/user/class/usergroup.class.php b/htdocs/user/class/usergroup.class.php index 71339991172..a9884ca59d1 100644 --- a/htdocs/user/class/usergroup.class.php +++ b/htdocs/user/class/usergroup.class.php @@ -922,9 +922,10 @@ class UserGroup extends CommonObject * Return clicable link of object (with eventually picto) * * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) + * @param array $arraydata Array of data * @return string HTML Code for Kanban thumb. */ - public function getKanbanView($option = '') + public function getKanbanView($option = '', $arraydata = null) { global $langs; $return = '
    '; From 9cd6adb6c8df667dd63f1a1bed3ce1723aac31cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20France?= Date: Wed, 18 Jan 2023 22:28:43 +0100 Subject: [PATCH 657/816] use oldcopy only to retrieve old values instaed undeclared properties --- htdocs/contact/card.php | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 3e7f5fdb1f1..66cdc1ed1aa 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -322,9 +322,6 @@ if (empty($reshook)) { $result = $object->fetch($id); $object->oldcopy = clone $object; - $object->old_lastname = (string) GETPOST("old_lastname", 'alpha'); - $object->old_firstname = (string) GETPOST("old_firstname", 'alpha'); - $result = $object->delete(); // TODO Add $user as first param if ($result > 0) { setEventMessages("RecordDeleted", null, 'mesgs'); @@ -408,9 +405,6 @@ if (empty($reshook)) { $object->oldcopy = clone $object; - $object->old_lastname = (string) GETPOST("old_lastname", 'alpha'); - $object->old_firstname = (string) GETPOST("old_firstname", 'alpha'); - $object->socid = GETPOST("socid", 'int'); $object->lastname = (string) GETPOST("lastname", 'alpha'); $object->firstname = (string) GETPOST("firstname", 'alpha'); @@ -972,7 +966,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { /* set country at end because it will trigger page refresh */ console.log("Set country id to '.dol_escape_js($objsoc->country_id).'"); $(\'select[name="country_id"]\').val("'.dol_escape_js($objsoc->country_id).'").trigger("change"); /* trigger required to update select2 components */ - }); + }); })'."\n"; print ''."\n"; } @@ -982,8 +976,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''; print ''; print ''; - print ''; - print ''; if (!empty($backtopage)) { print ''; } @@ -1033,7 +1025,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print '
    '; print ''; print '
    '; - if ($conf->use_javascript_ajax) { + if (!empty($conf->use_javascript_ajax)) { print ''.$langs->trans('CopyAddressFromSoc').'
    '; } print '
    '; @@ -1636,7 +1628,7 @@ function showSocialNetwork() items.show(); lnk.text("'.dol_escape_js($langs->transnoentitiesnoconv("HideSocialNetwork")).'"); if(chgCookieState) {document.cookie = "DOLUSER_SOCIALNETWORKS_SHOW=true; SameSite=Strict";} - } + } } '; } From 9d314ac035d751cff8943e42e1eff3d68dc2bf3d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 22:34:59 +0100 Subject: [PATCH 658/816] Debug v17 --- htdocs/core/actions_addupdatedelete.inc.php | 2 +- htdocs/eventorganization/class/conferenceorbooth.class.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 49f3b2fa302..18ab3ac5eda 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -285,7 +285,7 @@ if ($action == 'update' && !empty($permissiontoadd)) { $action = 'view'; $urltogo = $backtopage ? str_replace('__ID__', $result, $backtopage) : $backurlforlist; $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $object->id, $urltogo); // New method to autoselect project after a New on another form object creation - if ($urltogo && !$noback) { + if ($urltogo && empty($noback)) { header("Location: " . $urltogo); exit; } diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index bc21d7bb1c5..92ec38981ba 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -108,7 +108,7 @@ class ConferenceOrBooth extends ActionComm 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax125', 'help'=>"OrganizationEvenLabelName", 'showoncombobox'=>'1', 'autofocusoncreate'=>1), 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500', 'csslist'=>'width100'), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:t.usage_organize_event=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'picto'=>'project', 'css'=>'tdoverflowmax150 maxwidth500', 'csslist'=>'width100'), - 'note' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>1), + 'note' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3), 'fk_action' => array('type'=>'sellist:c_actioncomm:libelle:id::module LIKE (\'%@eventorganization\')', 'label'=>'Format', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>1, 'css'=>'width100'), 'datep' => array('type'=>'datetime', 'label'=>'DateStart', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>1, 'showoncombobox'=>'2',), 'datep2' => array('type'=>'datetime', 'label'=>'DateEnd', 'enabled'=>'1', 'position'=>71, 'notnull'=>0, 'visible'=>1, 'showoncombobox'=>'3',), @@ -249,7 +249,7 @@ class ConferenceOrBooth extends ActionComm $link_subscription = $dolibarr_main_url_root.'/public/eventorganization/attendee_new.php?id='.urlencode($id).'&type=conf'; - $encodedsecurekey = dol_hash($conf->global->EVENTORGANIZATION_SECUREKEY.'conferenceorbooth'.$id, 2); + $encodedsecurekey = dol_hash(getDolGlobalString('EVENTORGANIZATION_SECUREKEY').'conferenceorbooth'.$id, 2); $link_subscription .= '&securekey='.urlencode($encodedsecurekey); /*$this->fields['pubregister'] = array('type'=>'url', 'label'=>$langs->trans("PublicAttendeeSubscriptionPage"), 'enabled'=>'1', 'position'=>72, 'notnull'=>0, 'visible'=>1); From 823a7ee72b5af6840a1197fa79882e4554e0eaef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 18 Jan 2023 22:37:08 +0100 Subject: [PATCH 659/816] fix undeclared properties --- htdocs/commande/class/commande.class.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 35ebda89c2c..2a462f77bc4 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -11,7 +11,7 @@ * Copyright (C) 2014-2015 Marcos García * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2016-2022 Ferran Marcet - * Copyright (C) 2021-2022 Frédéric France + * Copyright (C) 2021-2023 Frédéric France * Copyright (C) 2022 Gauthier VERDOL * * This program is free software; you can redistribute it and/or modify @@ -236,6 +236,11 @@ class Commande extends CommonOrder */ public $user_valid; + /** + * @var OrderLine one line of an order + */ + public $line; + /** * @var OrderLine[] */ From 20956e9b7deebbbffe8a323bfb986abe48841acf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 22:50:13 +0100 Subject: [PATCH 660/816] Fix data truncated --- htdocs/loan/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index c3c08b6cf2f..f1d845bcc41 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -100,7 +100,7 @@ if (empty($reshook)) { $datestart = dol_mktime(12, 0, 0, GETPOST('startmonth', 'int'), GETPOST('startday', 'int'), GETPOST('startyear', 'int')); $dateend = dol_mktime(12, 0, 0, GETPOST('endmonth', 'int'), GETPOST('endday', 'int'), GETPOST('endyear', 'int')); $capital = price2num(GETPOST('capital')); - $rate = GETPOST('rate'); + $rate = price2num(GETPOST('rate')); if (!$capital) { $error++; $action = 'create'; From 1a2b48c57560ac8677b493c383252a405621a9f8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 23:07:34 +0100 Subject: [PATCH 661/816] Fix kanban --- htdocs/bom/bom_list.php | 95 ++++++++++++------- .../modulebuilder/template/myobject_list.php | 14 +-- 2 files changed, 68 insertions(+), 41 deletions(-) diff --git a/htdocs/bom/bom_list.php b/htdocs/bom/bom_list.php index 1cb4946715a..601eb9b75b3 100644 --- a/htdocs/bom/bom_list.php +++ b/htdocs/bom/bom_list.php @@ -72,6 +72,7 @@ $search_array_options = $extrafields->getOptionalsFromPost($object->table_elemen // Default sort order (if not yet defined by previous GETPOST) if (!$sortfield) { + reset($object->fields); // Reset is required to avoid key() to return null. $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition. } if (!$sortorder) { @@ -79,7 +80,7 @@ if (!$sortorder) { } // Initialize array of search criterias -$search_all = GETPOST("search_all", 'alpha'); +$search_all = GETPOST('search_all', 'alphanohtml'); $search = array(); foreach ($object->fields as $key => $val) { if (GETPOST('search_'.$key, 'alpha') !== '') { @@ -108,7 +109,7 @@ foreach ($object->fields as $key => $val) { $arrayfields['t.'.$key] = array( 'label'=>$val['label'], 'checked'=>(($visible < 0) ? 0 : 1), - 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1, 1, '1')), + 'enabled'=>(abs($visible) != 3 && dol_eval($val['enabled'], 1)), 'position'=>$val['position'], 'help'=> isset($val['help']) ? $val['help'] : '' ); @@ -299,7 +300,7 @@ $sql .= $object->getFieldList('t'); // 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.' ' : ''); + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : ''); } } // Add fields from hooks @@ -336,17 +337,17 @@ foreach ($search as $key => $val) { $mode_search = 2; } if ($search[$key] != '') { - $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); + $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search)); } } else { if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') { $columnName=preg_replace('/(_dtstart|_dtend)$/', '', $key); if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) { if (preg_match('/_dtstart$/', $key)) { - $sql .= " AND t." . $columnName . " >= '" . $db->idate($search[$key]) . "'"; + $sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'"; } if (preg_match('/_dtend$/', $key)) { - $sql .= " AND t." . $columnName . " <= '" . $db->idate($search[$key]) . "'"; + $sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'"; } } } @@ -366,9 +367,8 @@ $sql .= $hookmanager->resPrint; /* If a group by is required $sql.= " GROUP BY "; -foreach($object->fields as $key => $val) -{ - $sql .= "t.".$key.", "; +foreach($object->fields as $key => $val) { + $sql .= "t.".$db->escape($key).", "; } // Add fields from extrafields if (!empty($extrafields->attributes[$object->table_element]['label'])) { @@ -445,11 +445,17 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } foreach ($search as $key => $val) { - if (is_array($search[$key]) && count($search[$key])) { + if (is_array($search[$key])) { foreach ($search[$key] as $skey) { - $param .= '&search_'.$key.'[]='.urlencode($skey); + if ($skey != '') { + $param .= '&search_'.$key.'[]='.urlencode($skey); + } } - } else { + } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) { + $param .= '&search_'.$key.'month='.((int) GETPOST('search_'.$key.'month', 'int')); + $param .= '&search_'.$key.'day='.((int) GETPOST('search_'.$key.'day', 'int')); + $param .= '&search_'.$key.'year='.((int) GETPOST('search_'.$key.'year', 'int')); + } elseif ($search[$key] != '') { $param .= '&search_'.$key.'='.urlencode($search[$key]); } } @@ -469,7 +475,7 @@ $arrayofmassactions = array( 'enable'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Enable"), 'disable'=>img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Disable"), ); -if ($permissiontodelete) { +if (!empty($permissiontodelete)) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { @@ -488,6 +494,7 @@ print ''; print ''; print ''; print ''; +print ''; print ''; $newcardbutton = ''; @@ -505,10 +512,13 @@ $trackid = 'bom'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; if ($search_all) { + $setupstring = ''; foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); + $setupstring .= $key."=".$val.";"; } - print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '; + print ''."\n"; + print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } $moreforfilter = ''; @@ -544,13 +554,14 @@ print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; + print ''; $searchpicto = $form->showFilterButtons('left'); print $searchpicto; print ''; } foreach ($object->fields as $key => $val) { + $searchkey = empty($search[$key]) ? '' : $search[$key]; $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if ($key == 'status') { $cssforfield .= ($cssforfield ? ' ' : '').'center'; @@ -558,13 +569,13 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } if (!empty($arrayfields['t.'.$key]['checked'])) { print ''; if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { - print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status onrightofpage' : ''), 1); + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1); } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', 'maxwidth125', 1); } elseif (!preg_match('/^(date|timestamp|datetime)/', $val['type'])) { @@ -576,6 +587,12 @@ foreach ($object->fields as $key => $val) { print '
    '; print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); print '
    '; + } elseif ($key == 'lang') { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($db); + print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth150 maxwidth200', 2); + } else { + print ''; } print ''; } @@ -589,20 +606,22 @@ $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $obje print $hookmanager->resPrint; // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; + print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; 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"; + print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; } foreach ($object->fields as $key => $val) { $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); @@ -612,23 +631,26 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } + $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label if (!empty($arrayfields['t.'.$key]['checked'])) { print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + $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); +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; + print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; } +$totalarray['nbfield']++; // For the column action print ''."\n"; @@ -646,9 +668,11 @@ if (isset($extrafields->attributes[$object->table_element]['computed']) && is_ar // 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 @@ -660,20 +684,19 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // mode view kanban if ($mode == 'kanban') { if ($i == 0) { - print ''; + print ''; print '
    '; } - + // Output kanban print $object->getKanbanView(''); - - - if ($i == min($num, $limit)-1) { + if ($i == ($imaxinloop - 1)) { print '
    '; print ''; } } else { // Show here line of result - print ''; + $j = 0; + print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; @@ -705,7 +728,11 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } if (!empty($arrayfields['t.'.$key]['checked'])) { - print ''; + print ''; if ($key == 'status') { print $object->getLibStatut(5); } elseif ($key == 'rowid') { @@ -754,9 +781,9 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } print ''."\n"; - - $i++; } + + $i++; } // Show total line @@ -771,14 +798,14 @@ if ($num == 0) { $colspan++; } } - print ''.$langs->trans("NoRecordFound").''; + print ''.$langs->trans("NoRecordFound").''; } $db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); -$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; print ''."\n"; diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 5ff0628bc8f..b28a7a5f955 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -136,7 +136,7 @@ if (!$sortorder) { } // Initialize array of search criterias -$search_all = GETPOST('search_all', 'alphanohtml') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'); +$search_all = GETPOST('search_all', 'alphanohtml'); $search = array(); foreach ($object->fields as $key => $val) { if (GETPOST('search_'.$key, 'alpha') !== '') { @@ -552,7 +552,7 @@ print ''; // Action column -if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; }*/ // Action column -if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; -if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; } foreach ($object->fields as $key => $val) { @@ -649,7 +649,7 @@ print $hookmanager->resPrint; $totalarray['nbfield']++; }*/ // Action column -if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; } $totalarray['nbfield']++; // For the column action @@ -699,7 +699,7 @@ while ($i < $imaxinloop) { $j = 0; print ''; // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; }*/ // Action column - if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print '
    '; $searchpicto = $form->showFilterButtons('left'); print $searchpicto; @@ -604,7 +604,7 @@ print $hookmanager->resPrint; print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; @@ -618,7 +618,7 @@ $totalarray['nbfield'] = 0; // Fields title label // -------------------------------------------------------------------- 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; @@ -770,7 +770,7 @@ while ($i < $imaxinloop) { print ''.$obj->anotherfield.''; 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; From 1f3fb86e9b002525c6e47b560864ae3d3ad9fe22 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 23:15:10 +0100 Subject: [PATCH 662/816] css --- .../class/conferenceorbooth.class.php | 2 +- .../conferenceorbooth_list.php | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index 92ec38981ba..76b1941fe69 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -106,7 +106,7 @@ class ConferenceOrBooth extends ActionComm 'id' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), 'ref' => array('type'=>'integer', 'label'=>'Ref', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>2, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'csslist'=>'left', 'comment'=>"Id"), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax125', 'help'=>"OrganizationEvenLabelName", 'showoncombobox'=>'1', 'autofocusoncreate'=>1), - 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'css'=>'tdoverflowmax150 maxwidth500', 'csslist'=>'width100'), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'picto'=>'company', 'csslist'=>'tdoverflowmax150', 'css'=>'maxwidth500'), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1:t.usage_organize_event=1', 'label'=>'Project', 'enabled'=>"isModEnabled('project')", 'position'=>52, 'notnull'=>-1, 'visible'=>-1, 'index'=>1, 'picto'=>'project', 'css'=>'tdoverflowmax150 maxwidth500', 'csslist'=>'width100'), 'note' => array('type'=>'text', 'label'=>'Description', 'enabled'=>'1', 'position'=>60, 'notnull'=>0, 'visible'=>3), 'fk_action' => array('type'=>'sellist:c_actioncomm:libelle:id::module LIKE (\'%@eventorganization\')', 'label'=>'Format', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>1, 'css'=>'width100'), diff --git a/htdocs/eventorganization/conferenceorbooth_list.php b/htdocs/eventorganization/conferenceorbooth_list.php index 1dd77122384..21172d774d9 100644 --- a/htdocs/eventorganization/conferenceorbooth_list.php +++ b/htdocs/eventorganization/conferenceorbooth_list.php @@ -757,7 +757,7 @@ print ''; // Action column -if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; -if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; } foreach ($object->fields as $key => $val) { @@ -831,7 +831,7 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $key != 'ref' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label @@ -847,7 +847,7 @@ $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$ $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; } $totalarray['nbfield']++; @@ -885,7 +885,7 @@ while ($i < $imaxinloop) { $j = 0; print ''; // Action column - if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; + print ''; } From a4c06a2188edad3fd08e609bff92a5368e50f4ca Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 23:19:09 +0100 Subject: [PATCH 663/816] css --- .../class/conferenceorbooth.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index 76b1941fe69..b3232f079f6 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -112,13 +112,13 @@ class ConferenceOrBooth extends ActionComm 'fk_action' => array('type'=>'sellist:c_actioncomm:libelle:id::module LIKE (\'%@eventorganization\')', 'label'=>'Format', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>1, 'css'=>'width100'), 'datep' => array('type'=>'datetime', 'label'=>'DateStart', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>1, 'showoncombobox'=>'2',), 'datep2' => array('type'=>'datetime', 'label'=>'DateEnd', 'enabled'=>'1', 'position'=>71, 'notnull'=>0, 'visible'=>1, 'showoncombobox'=>'3',), - 'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), - 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), - 'fk_user_author' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), - 'fk_user_mod' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2, 'csslist'=>'nowraponall'), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2, 'csslist'=>'nowraponall'), + 'fk_user_author' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid', 'csslist'=>'tdoverflowmax100'), + 'fk_user_mod' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2, 'csslist'=>'tdoverflowmax100'), + 'num_vote' => array('type'=>'smallint', 'label'=>'NbVotes', 'enabled'=>'1', 'position'=>800, 'notnull'=>-1, 'visible'=>5, 'default'=>'0', 'index'=>0), 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>1, 'default'=>'0', 'index'=>1, 'arrayofkeyval'=>array('0'=>'EvntOrgDraft', '1'=>'EvntOrgSuggested', '2'=> 'EvntOrgConfirmed', '3' =>'EvntOrgNotQualified', '4' =>'EvntOrgDone', '9'=>'EvntOrgCancelled'),), - 'num_vote' => array('type'=>'smallint', 'label'=>'NbVotes', 'enabled'=>'1', 'position'=>1001, 'notnull'=>-1, 'visible'=>5, 'default'=>'0', 'index'=>0), ); public $rowid; public $id; From ff7a666c2b2e53191198e4187466e98b854e3f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 18 Jan 2023 23:43:54 +0100 Subject: [PATCH 664/816] Update bonprelevement.class.php --- htdocs/compta/prelevement/class/bonprelevement.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index a1dcdba6f58..7d16bcd8136 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -1690,7 +1690,7 @@ class BonPrelevement extends CommonObject fclose($this->file); if (!empty($conf->global->MAIN_UMASK)) { - @chmod($this->file, octdec($conf->global->MAIN_UMASK)); + @chmod($this->filename, octdec($conf->global->MAIN_UMASK)); } return $result; From a33603b6aeb76b9e67d35744865c1639dea9a189 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Jan 2023 23:58:26 +0100 Subject: [PATCH 665/816] Doxygen --- .../fichinter/class/api_interventions.class.php | 16 ++++++---------- htdocs/reception/class/api_receptions.class.php | 15 +++++++-------- .../recruitment/class/api_recruitment.class.php | 8 ++++---- htdocs/societe/class/api_thirdparties.class.php | 13 +++++++------ .../class/api_supplier_proposals.class.php | 2 +- htdocs/zapier/class/api_zapier.class.php | 4 ++-- 6 files changed, 27 insertions(+), 31 deletions(-) diff --git a/htdocs/fichinter/class/api_interventions.class.php b/htdocs/fichinter/class/api_interventions.class.php index f96dc3d6aa7..14fc9f16fcf 100644 --- a/htdocs/fichinter/class/api_interventions.class.php +++ b/htdocs/fichinter/class/api_interventions.class.php @@ -64,11 +64,10 @@ class Interventions extends DolibarrApi /** * Get properties of a Expense Report object - * * Return an array with Expense Report information * * @param int $id ID of Expense Report - * @return array|mixed Data without useless information + * @return Object Object with cleaned properties * * @throws RestException */ @@ -93,7 +92,6 @@ class Interventions extends DolibarrApi /** * List of interventions - * * Return a list of interventions * * @param string $sortfield Sort field @@ -336,12 +334,11 @@ class Interventions extends DolibarrApi * "notrigger": 0 * } * - * @param int $id Intervention ID - * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @param int $id Intervention ID + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return Object Object with cleaned properties * * @url POST {id}/validate - * - * @return array */ public function validate($id, $notrigger = 0) { @@ -373,11 +370,10 @@ class Interventions extends DolibarrApi /** * Close an intervention * - * @param int $id Intervention ID + * @param int $id Intervention ID + * @return Object Object with cleaned properties * * @url POST {id}/close - * - * @return array */ public function closeFichinter($id) { diff --git a/htdocs/reception/class/api_receptions.class.php b/htdocs/reception/class/api_receptions.class.php index 473650161e2..ca46cb8909c 100644 --- a/htdocs/reception/class/api_receptions.class.php +++ b/htdocs/reception/class/api_receptions.class.php @@ -59,7 +59,7 @@ class Receptions extends DolibarrApi * Return an array with reception informations * * @param int $id ID of reception - * @return array|mixed data without useless information + * @return Object Object with cleaned properties * * @throws RestException */ @@ -497,12 +497,12 @@ class Receptions extends DolibarrApi * This may record stock movements if module stock is enabled and option to * decrease stock on reception is on. * - * @param int $id Reception ID - * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @param int $id Reception ID + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return Object Object with cleaned properties * * @url POST {id}/validate * - * @return array * \todo An error 403 is returned if the request has an empty body. * Error message: "Forbidden: Content type `text/plain` is not supported." * Workaround: send this in the body @@ -625,12 +625,11 @@ class Receptions extends DolibarrApi /** * Close a reception (Classify it as "Delivered") * - * @param int $id Reception ID - * @param int $notrigger Disabled triggers + * @param int $id Reception ID + * @param int $notrigger Disabled triggers + * @return Object Object with cleaned properties * * @url POST {id}/close - * - * @return int */ public function close($id, $notrigger = 0) { diff --git a/htdocs/recruitment/class/api_recruitment.class.php b/htdocs/recruitment/class/api_recruitment.class.php index cf4fa7a143e..9162a6250f3 100644 --- a/htdocs/recruitment/class/api_recruitment.class.php +++ b/htdocs/recruitment/class/api_recruitment.class.php @@ -66,8 +66,8 @@ class Recruitment extends DolibarrApi * * Return an array with jobposition informations * - * @param int $id ID of jobposition - * @return array|mixed data without useless information + * @param int $id ID of jobposition + * @return Object Object with cleaned properties * * @url GET jobposition/{id} * @@ -97,8 +97,8 @@ class Recruitment extends DolibarrApi * * Return an array with candidature informations * - * @param int $id ID of candidature - * @return array|mixed data without useless information + * @param int $id ID of candidature + * @return Object Object with cleaned properties * * @url GET candidature/{id} * diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index c4781c0df6a..10266b6f0ac 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -523,8 +523,8 @@ class Thirdparties extends DolibarrApi /** * Delete thirdparty * - * @param int $id Thirdparty ID - * @return integer + * @param int $id Thirdparty ID + * @return array */ public function delete($id) { @@ -1351,10 +1351,10 @@ class Thirdparties extends DolibarrApi /** * Generate a Document from a bank account record (like SEPA mandate) * - * @param int $id Thirdparty id - * @param int $companybankid Companybank id - * @param string $model Model of document to generate - * @return void + * @param int $id Thirdparty id + * @param int $companybankid Companybank id + * @param string $model Model of document to generate + * @return array * * @url GET {id}/generateBankAccountDocument/{companybankid}/{model} */ @@ -1375,6 +1375,7 @@ class Thirdparties extends DolibarrApi $this->company->setDocModel(DolibarrApiAccess::$user, $model); $this->company->fk_bank = $this->company->fk_account; + $this->company->fk_account = $this->company->fk_account; $outputlangs = $langs; $newlang = ''; diff --git a/htdocs/supplier_proposal/class/api_supplier_proposals.class.php b/htdocs/supplier_proposal/class/api_supplier_proposals.class.php index f2036edda88..496d67df829 100644 --- a/htdocs/supplier_proposal/class/api_supplier_proposals.class.php +++ b/htdocs/supplier_proposal/class/api_supplier_proposals.class.php @@ -58,7 +58,7 @@ class Supplierproposals extends DolibarrApi * Return an array with supplier proposal informations * * @param int $id ID of supplier proposal - * @return array|mixed data without useless information + * @return Object Object with cleaned properties * * @throws RestException */ diff --git a/htdocs/zapier/class/api_zapier.class.php b/htdocs/zapier/class/api_zapier.class.php index 56ab923435d..aac72a281f7 100644 --- a/htdocs/zapier/class/api_zapier.class.php +++ b/htdocs/zapier/class/api_zapier.class.php @@ -66,8 +66,8 @@ class Zapier extends DolibarrApi * * Return an array with hook informations * - * @param int $id ID of hook - * @return array|mixed data without useless information + * @param int $id ID of hook + * @return Object Object with cleaned properties * * @url GET /hooks/{id} * @throws RestException From 58645a1d4aadc575d5c965573d7dd56b3a1df0a6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 00:19:57 +0100 Subject: [PATCH 666/816] Debug v17 --- htdocs/admin/system/modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/system/modules.php b/htdocs/admin/system/modules.php index c2ad387d955..6ea79cf00eb 100644 --- a/htdocs/admin/system/modules.php +++ b/htdocs/admin/system/modules.php @@ -241,7 +241,7 @@ if ($arrayfields['version']['checked']) { } if ($arrayfields['id']['checked']) { print ''; } if ($arrayfields['permission']['checked']) { From e28fce631827f318431287ea71c20367b52f3542 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 01:16:39 +0100 Subject: [PATCH 667/816] Debug --- htdocs/bookcal/admin/about.php | 80 ------------------- .../admin/availabilities_extrafields.php | 4 +- htdocs/bookcal/admin/booking_extrafields.php | 4 +- htdocs/bookcal/admin/setup.php | 4 +- htdocs/bookcal/availabilities_agenda.php | 2 +- htdocs/bookcal/availabilities_card.php | 2 +- htdocs/bookcal/availabilities_contact.php | 2 +- htdocs/bookcal/availabilities_document.php | 2 +- htdocs/bookcal/availabilities_list.php | 4 +- htdocs/bookcal/availabilities_note.php | 2 +- htdocs/bookcal/bookcalindex.php | 2 +- htdocs/bookcal/booking_agenda.php | 2 +- htdocs/bookcal/booking_card.php | 2 +- htdocs/bookcal/booking_contact.php | 2 +- htdocs/bookcal/booking_document.php | 2 +- htdocs/bookcal/booking_list.php | 2 +- htdocs/bookcal/booking_note.php | 2 +- htdocs/bookcal/class/availabilities.class.php | 12 +-- htdocs/bookcal/class/booking.class.php | 6 +- htdocs/bookcal/lib/bookcal.lib.php | 7 +- .../lib/bookcal_availabilities.lib.php | 2 +- htdocs/bookcal/lib/bookcal_booking.lib.php | 2 +- htdocs/comm/action/index.php | 6 +- htdocs/core/class/commonobject.class.php | 19 +++-- htdocs/core/modules/modBookCal.class.php | 8 +- htdocs/langs/en_US/admin.lang | 2 + htdocs/societe/class/societe.class.php | 4 +- 27 files changed, 56 insertions(+), 132 deletions(-) delete mode 100644 htdocs/bookcal/admin/about.php diff --git a/htdocs/bookcal/admin/about.php b/htdocs/bookcal/admin/about.php deleted file mode 100644 index 2ff4e874450..00000000000 --- a/htdocs/bookcal/admin/about.php +++ /dev/null @@ -1,80 +0,0 @@ - - * Copyright (C) 2022 Alice Adminson - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * \file bookcal/admin/about.php - * \ingroup bookcal - * \brief About page of module BookCal. - */ - -// Load Dolibarr environment -require '../../main.inc.php'; - -// Libraries -require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; -require_once '../lib/bookcal.lib.php'; - -// Translations -$langs->loadLangs(array("errors", "admin", "bookcal@bookcal")); - -// Access control -if (!$user->admin) { - accessforbidden(); -} - -// Parameters -$action = GETPOST('action', 'aZ09'); -$backtopage = GETPOST('backtopage', 'alpha'); - - -/* - * Actions - */ - -// None - - -/* - * View - */ - -$form = new Form($db); - -$help_url = ''; -$page_name = "BookCalAbout"; - -llxHeader('', $langs->trans($page_name), $help_url); - -// Subheader -$linkback = ''.$langs->trans("BackToModuleList").''; - -print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); - -// Configuration header -$head = bookcalAdminPrepareHead(); -print dol_get_fiche_head($head, 'about', $langs->trans($page_name), 0, 'bookcal@bookcal'); - -dol_include_once('/bookcal/core/modules/modBookCal.class.php'); -$tmpmodule = new modBookCal($db); -print $tmpmodule->getDescLong(); - -// Page end -print dol_get_fiche_end(); -llxFooter(); -$db->close(); diff --git a/htdocs/bookcal/admin/availabilities_extrafields.php b/htdocs/bookcal/admin/availabilities_extrafields.php index ba7dca39570..190a44f339d 100644 --- a/htdocs/bookcal/admin/availabilities_extrafields.php +++ b/htdocs/bookcal/admin/availabilities_extrafields.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once '../lib/bookcal.lib.php'; // Load translation files required by the page -$langs->loadLangs(array('bookcal@bookcal', 'admin')); +$langs->loadLangs(array('agenda', 'admin')); $extrafields = new ExtraFields($db); $form = new Form($db); @@ -80,7 +80,7 @@ print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); $head = bookcalAdminPrepareHead(); -print dol_get_fiche_head($head, 'availabilities_extrafields', $langs->trans($page_name), -1, 'bookcal@bookcal'); +print dol_get_fiche_head($head, 'availabilities_extrafields', $langs->trans($page_name), -1, 'fa-calendar-check'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/bookcal/admin/booking_extrafields.php b/htdocs/bookcal/admin/booking_extrafields.php index 2e9163af158..b4029a99338 100644 --- a/htdocs/bookcal/admin/booking_extrafields.php +++ b/htdocs/bookcal/admin/booking_extrafields.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once '../lib/bookcal.lib.php'; // Load translation files required by the page -$langs->loadLangs(array('bookcal@bookcal', 'admin')); +$langs->loadLangs(array('agenda', 'admin')); $extrafields = new ExtraFields($db); $form = new Form($db); @@ -80,7 +80,7 @@ print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); $head = bookcalAdminPrepareHead(); -print dol_get_fiche_head($head, 'booking_extrafields', $langs->trans($page_name), -1, 'bookcal@bookcal'); +print dol_get_fiche_head($head, 'booking_extrafields', $langs->trans($page_name), -1, 'fa-calendar-check'); require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; diff --git a/htdocs/bookcal/admin/setup.php b/htdocs/bookcal/admin/setup.php index 9772ffbbbf0..e3addec83e3 100644 --- a/htdocs/bookcal/admin/setup.php +++ b/htdocs/bookcal/admin/setup.php @@ -33,7 +33,7 @@ require_once '../lib/bookcal.lib.php'; //require_once "../class/myclass.class.php"; // Translations -$langs->loadLangs(array("admin", "bookcal@bookcal")); +$langs->loadLangs(array("admin", "agenda")); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('bookcalsetup', 'globalsetup')); @@ -269,7 +269,7 @@ print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup'); // Configuration header $head = bookcalAdminPrepareHead(); -print dol_get_fiche_head($head, 'settings', $langs->trans($page_name), -1, "bookcal@bookcal"); +print dol_get_fiche_head($head, 'settings', $langs->trans($page_name), -1, "fa-calendar-check"); // Setup page goes here echo ''.$langs->trans("BookCalSetupPage").'

    '; diff --git a/htdocs/bookcal/availabilities_agenda.php b/htdocs/bookcal/availabilities_agenda.php index 0d34fa992c1..d97970c3add 100644 --- a/htdocs/bookcal/availabilities_agenda.php +++ b/htdocs/bookcal/availabilities_agenda.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_availabilities.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "other")); +$langs->loadLangs(array("agenda", "other")); // Get parameters $id = GETPOST('id', 'int'); diff --git a/htdocs/bookcal/availabilities_card.php b/htdocs/bookcal/availabilities_card.php index ac580c650c5..f64b5e6f4b6 100644 --- a/htdocs/bookcal/availabilities_card.php +++ b/htdocs/bookcal/availabilities_card.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/class/availabilities.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_availabilities.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "other")); +$langs->loadLangs(array("agenda", "other")); // Get parameters $id = GETPOST('id', 'int'); diff --git a/htdocs/bookcal/availabilities_contact.php b/htdocs/bookcal/availabilities_contact.php index 41508aaa46a..348602f58a9 100644 --- a/htdocs/bookcal/availabilities_contact.php +++ b/htdocs/bookcal/availabilities_contact.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/class/availabilities.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_availabilities.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "companies", "other", "mails")); +$langs->loadLangs(array("agenda", "companies", "other", "mails")); $id = (GETPOST('id') ?GETPOST('id', 'int') : GETPOST('facid', 'int')); // For backward compatibility $ref = GETPOST('ref', 'alpha'); diff --git a/htdocs/bookcal/availabilities_document.php b/htdocs/bookcal/availabilities_document.php index e7335bff74c..ed6b2976570 100644 --- a/htdocs/bookcal/availabilities_document.php +++ b/htdocs/bookcal/availabilities_document.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/class/availabilities.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_availabilities.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "companies", "other", "mails")); +$langs->loadLangs(array("agenda", "companies", "other", "mails")); $action = GETPOST('action', 'aZ09'); diff --git a/htdocs/bookcal/availabilities_list.php b/htdocs/bookcal/availabilities_list.php index 9af4b65a022..26d66ce0ca4 100644 --- a/htdocs/bookcal/availabilities_list.php +++ b/htdocs/bookcal/availabilities_list.php @@ -36,7 +36,7 @@ require_once __DIR__.'/class/availabilities.class.php'; //dol_include_once('/othermodule/class/otherobject.class.php'); // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "other")); +$langs->loadLangs(array("agenda", "other")); $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -210,7 +210,7 @@ $now = dol_now(); //$help_url = "EN:Module_Availabilities|FR:Module_Availabilities_FR|ES:Módulo_Availabilities"; $help_url = ''; -$title = $langs->trans("Availabilitiess"); +$title = $langs->trans("Availabilities"); $morejs = array(); $morecss = array(); diff --git a/htdocs/bookcal/availabilities_note.php b/htdocs/bookcal/availabilities_note.php index 44ced158e03..6913491d85e 100644 --- a/htdocs/bookcal/availabilities_note.php +++ b/htdocs/bookcal/availabilities_note.php @@ -29,7 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/class/availabilities.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_availabilities.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "companies")); +$langs->loadLangs(array("agenda", "companies")); // Get parameters $id = GETPOST('id', 'int'); diff --git a/htdocs/bookcal/bookcalindex.php b/htdocs/bookcal/bookcalindex.php index 6ec6ae6fb3e..46281eb048a 100644 --- a/htdocs/bookcal/bookcalindex.php +++ b/htdocs/bookcal/bookcalindex.php @@ -30,7 +30,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal")); +$langs->loadLangs(array("agenda")); $action = GETPOST('action', 'aZ09'); diff --git a/htdocs/bookcal/booking_agenda.php b/htdocs/bookcal/booking_agenda.php index a9163d7f70d..fb26fce4fc7 100644 --- a/htdocs/bookcal/booking_agenda.php +++ b/htdocs/bookcal/booking_agenda.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_booking.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "other")); +$langs->loadLangs(array("agenda", "other")); // Get parameters $id = GETPOST('id', 'int'); diff --git a/htdocs/bookcal/booking_card.php b/htdocs/bookcal/booking_card.php index 7f0fc3b9f3a..82bd884cd2d 100644 --- a/htdocs/bookcal/booking_card.php +++ b/htdocs/bookcal/booking_card.php @@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/class/booking.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_booking.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "other")); +$langs->loadLangs(array("agenda", "other")); // Get parameters $id = GETPOST('id', 'int'); diff --git a/htdocs/bookcal/booking_contact.php b/htdocs/bookcal/booking_contact.php index bb73368b770..631f6af8e6c 100644 --- a/htdocs/bookcal/booking_contact.php +++ b/htdocs/bookcal/booking_contact.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/class/booking.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_booking.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "companies", "other", "mails")); +$langs->loadLangs(array("agenda", "companies", "other", "mails")); $id = (GETPOST('id') ?GETPOST('id', 'int') : GETPOST('facid', 'int')); // For backward compatibility $ref = GETPOST('ref', 'alpha'); diff --git a/htdocs/bookcal/booking_document.php b/htdocs/bookcal/booking_document.php index c102597e189..fa925759399 100644 --- a/htdocs/bookcal/booking_document.php +++ b/htdocs/bookcal/booking_document.php @@ -33,7 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/class/booking.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_booking.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "companies", "other", "mails")); +$langs->loadLangs(array("agenda", "companies", "other", "mails")); $action = GETPOST('action', 'aZ09'); diff --git a/htdocs/bookcal/booking_list.php b/htdocs/bookcal/booking_list.php index c7ebdd6f378..2e4fbfccd16 100644 --- a/htdocs/bookcal/booking_list.php +++ b/htdocs/bookcal/booking_list.php @@ -36,7 +36,7 @@ require_once __DIR__.'/class/booking.class.php'; //dol_include_once('/othermodule/class/otherobject.class.php'); // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "other")); +$langs->loadLangs(array("agenda", "other")); $id = GETPOST('id', 'int'); $ref = GETPOST('ref', 'alpha'); diff --git a/htdocs/bookcal/booking_note.php b/htdocs/bookcal/booking_note.php index c8b2de4e6ff..809f382cc16 100644 --- a/htdocs/bookcal/booking_note.php +++ b/htdocs/bookcal/booking_note.php @@ -29,7 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/bookcal/class/booking.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_booking.lib.php'; // Load translation files required by the page -$langs->loadLangs(array("bookcal@bookcal", "companies")); +$langs->loadLangs(array("agenda", "companies")); // Get parameters $id = GETPOST('id', 'int'); diff --git a/htdocs/bookcal/class/availabilities.class.php b/htdocs/bookcal/class/availabilities.class.php index 3ccc4542670..6b4502e3364 100644 --- a/htdocs/bookcal/class/availabilities.class.php +++ b/htdocs/bookcal/class/availabilities.class.php @@ -116,10 +116,10 @@ class Availabilities extends CommonObject 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>'1', 'position'=>2000, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validated', '9'=>'Canceled'), 'validate'=>'1',), - 'start' => array('type'=>'date', 'label'=>'Start Date', 'enabled'=>'1', 'position'=>40, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'isameasure'=>'1',), - 'end' => array('type'=>'date', 'label'=>'End Date', 'enabled'=>'1', 'position'=>45, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'isameasure'=>'1',), + 'start' => array('type'=>'date', 'label'=>'Start Date', 'enabled'=>'1', 'position'=>40, 'notnull'=>1, 'visible'=>1, 'searchall'=>1), + 'end' => array('type'=>'date', 'label'=>'End Date', 'enabled'=>'1', 'position'=>45, 'notnull'=>1, 'visible'=>1, 'searchall'=>1), 'type' => array('type'=>'integer', 'label'=>'Type', 'enabled'=>'1', 'position'=>49, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Customer', '1'=>'Supplier', '2'=>'Else'),), - 'duration' => array('type'=>'integer', 'label'=>'Duration', 'enabled'=>'1', 'position'=>47, 'notnull'=>1, 'visible'=>1, 'default'=>'30', 'isameasure'=>'1',), + 'duration' => array('type'=>'integer', 'label'=>'Duration', 'enabled'=>'1', 'position'=>47, 'notnull'=>1, 'visible'=>1, 'default'=>'30'), 'startHour' => array('type'=>'integer', 'label'=>'Start Hour', 'enabled'=>'1', 'position'=>46, 'notnull'=>1, 'visible'=>-1,), 'endHour' => array('type'=>'integer', 'label'=>'End Hour', 'enabled'=>'1', 'position'=>46.5, 'notnull'=>1, 'visible'=>-1,), ); @@ -842,7 +842,7 @@ class Availabilities extends CommonObject // phpcs:enable if (empty($this->labelStatus) || empty($this->labelStatusShort)) { global $langs; - //$langs->load("bookcal@bookcal"); + //$langs->load("agenda"); $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); @@ -944,7 +944,7 @@ class Availabilities extends CommonObject public function getNextNumRef() { global $langs, $conf; - $langs->load("bookcal@bookcal"); + $langs->load("agenda"); if (empty($conf->global->BOOKCAL_AVAILABILITIES_ADDON)) { $conf->global->BOOKCAL_AVAILABILITIES_ADDON = 'mod_availabilities_standard'; @@ -1009,7 +1009,7 @@ class Availabilities extends CommonObject $result = 0; $includedocgeneration = 0; - $langs->load("bookcal@bookcal"); + $langs->load("agenda"); if (!dol_strlen($modele)) { $modele = 'standard_availabilities'; diff --git a/htdocs/bookcal/class/booking.class.php b/htdocs/bookcal/class/booking.class.php index 1a4f402626b..80807d7125f 100644 --- a/htdocs/bookcal/class/booking.class.php +++ b/htdocs/bookcal/class/booking.class.php @@ -842,7 +842,7 @@ class Booking extends CommonObject // phpcs:enable if (empty($this->labelStatus) || empty($this->labelStatusShort)) { global $langs; - //$langs->load("bookcal@bookcal"); + //$langs->load("agenda"); $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); @@ -944,7 +944,7 @@ class Booking extends CommonObject public function getNextNumRef() { global $langs, $conf; - $langs->load("bookcal@bookcal"); + $langs->load("agenda"); if (empty($conf->global->BOOKCAL_BOOKING_ADDON)) { $conf->global->BOOKCAL_BOOKING_ADDON = 'mod_booking_standard'; @@ -1009,7 +1009,7 @@ class Booking extends CommonObject $result = 0; $includedocgeneration = 0; - $langs->load("bookcal@bookcal"); + $langs->load("agenda"); if (!dol_strlen($modele)) { $modele = 'standard_booking'; diff --git a/htdocs/bookcal/lib/bookcal.lib.php b/htdocs/bookcal/lib/bookcal.lib.php index bc60468fb1d..3f809da08d8 100644 --- a/htdocs/bookcal/lib/bookcal.lib.php +++ b/htdocs/bookcal/lib/bookcal.lib.php @@ -30,7 +30,7 @@ function bookcalAdminPrepareHead() { global $langs, $conf; - $langs->load("bookcal@bookcal"); + $langs->load("agenda"); $h = 0; $head = array(); @@ -47,11 +47,6 @@ function bookcalAdminPrepareHead() $h++; */ - $head[$h][0] = dol_buildpath("/bookcal/admin/about.php", 1); - $head[$h][1] = $langs->trans("About"); - $head[$h][2] = 'about'; - $h++; - // Show more tabs from modules // Entries must be declared in modules descriptor with line //$this->tabs = array( diff --git a/htdocs/bookcal/lib/bookcal_availabilities.lib.php b/htdocs/bookcal/lib/bookcal_availabilities.lib.php index 83d204a2d76..1fb4b2aed75 100644 --- a/htdocs/bookcal/lib/bookcal_availabilities.lib.php +++ b/htdocs/bookcal/lib/bookcal_availabilities.lib.php @@ -31,7 +31,7 @@ function availabilitiesPrepareHead($object) { global $db, $langs, $conf; - $langs->load("bookcal@bookcal"); + $langs->load("agenda"); $showtabofpagecontact = 1; $showtabofpagenote = 1; diff --git a/htdocs/bookcal/lib/bookcal_booking.lib.php b/htdocs/bookcal/lib/bookcal_booking.lib.php index a6cb0e50df6..c0dec7d6d2e 100644 --- a/htdocs/bookcal/lib/bookcal_booking.lib.php +++ b/htdocs/bookcal/lib/bookcal_booking.lib.php @@ -31,7 +31,7 @@ function bookingPrepareHead($object) { global $db, $langs, $conf; - $langs->load("bookcal@bookcal"); + $langs->load("agenda"); $showtabofpagecontact = 1; $showtabofpagenote = 1; diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 8ec011f5e9d..e730243bfbf 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -1945,7 +1945,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa } $listofusertoshow = ''; - $listofusertoshow .= '
    '.$cacheusers[$tmpid]->getNomUrl(-1, '', 0, 0, 0, 0, '', 'paddingright valigntextbottom'); + $listofusertoshow .= '
    '.$cacheusers[$tmpid]->getNomUrl(-1, '', 0, 0, 0, 0, '', 'paddingright valignmiddle'); print $listofusertoshow; } else { // Other calendar // Picto @@ -2020,7 +2020,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa $cacheusers[$tmpid] = $newuser; } - $listofusertoshow .= $cacheusers[$tmpid]->getNomUrl(-3, '', 0, 0, 0, 0, '', 'paddingright valigntextbottom'); + $listofusertoshow .= $cacheusers[$tmpid]->getNomUrl(-3, '', 0, 0, 0, 0, '', 'valignmiddle'); } print $titletoshow; @@ -2070,7 +2070,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa $linerelatedto .= dolGetElementUrl($event->fk_element, $event->elementtype, 1); } if ($linerelatedto) { - print '
    '.$linerelatedto; + print ' '.$linerelatedto; } } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 82d3d263e21..b998fcbd71a 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7858,30 +7858,34 @@ abstract class CommonObject /** * Return validation test result for a field * - * @param array $val Array of properties of field to show + * @param array $fields Array of properties of field to show * @param string $fieldKey Key of attribute * @param string $fieldValue value of attribute * @return bool return false if fail true on success, see $this->error for error message */ - public function validateField($val, $fieldKey, $fieldValue) + public function validateField($fields, $fieldKey, $fieldValue) { global $langs; - if (!class_exists('Validate')) { require_once DOL_DOCUMENT_ROOT . '/core/class/validate.class.php'; } + if (!class_exists('Validate')) { + require_once DOL_DOCUMENT_ROOT . '/core/class/validate.class.php'; + } $this->clearFieldError($fieldKey); - if (!isset($val[$fieldKey])) { + if (!isset($fields[$fieldKey])) { $this->setFieldError($fieldKey, $langs->trans('FieldNotFoundInObject')); return false; } + $val = $fields[$fieldKey]; + $param = array(); $param['options'] = array(); - $type = $val[$fieldKey]['type']; + $type = $val['type']; $required = false; - if (isset($val[$fieldKey]['notnull']) && $val[$fieldKey]['notnull'] === 1) { + if (isset($val['notnull']) && $val['notnull'] === 1) { // 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). $required = true; } @@ -7892,6 +7896,7 @@ abstract class CommonObject // // PREPARE Elements // + $reg = array(); // Convert var to be able to share same code than showOutputField of extrafields if (preg_match('/varchar\((\d+)\)/', $type, $reg)) { @@ -7905,7 +7910,7 @@ abstract class CommonObject $type = 'select'; } - if (preg_match('/^integer:(.*):(.*)/i', $val['type'], $reg)) { + if (!empty($val['type']) && preg_match('/^integer:(.*):(.*)/i', $val['type'], $reg)) { $type = 'link'; } diff --git a/htdocs/core/modules/modBookCal.class.php b/htdocs/core/modules/modBookCal.class.php index c3066dbd2e0..6e3d6768206 100644 --- a/htdocs/core/modules/modBookCal.class.php +++ b/htdocs/core/modules/modBookCal.class.php @@ -40,11 +40,12 @@ class modBookCal extends DolibarrModules public function __construct($db) { global $langs, $conf; + $this->db = $db; // Id for module (must be unique). // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). - $this->numero = 500000; // TODO Go on page https://wiki.dolibarr.org/index.php/List_of_modules_id to reserve an id number for your module + $this->numero = 2430; // Key text used to identify module (for permissions, menus, etc...) $this->rights_class = 'bookcal'; @@ -76,7 +77,7 @@ class modBookCal extends DolibarrModules // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' - $this->picto = 'fa-generic'; + $this->picto = 'fa-calendar-check'; // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) $this->module_parts = array( @@ -463,8 +464,7 @@ class modBookCal extends DolibarrModules { global $conf, $langs; - //$result = $this->_load_tables('/install/mysql/', 'bookcal'); - $result = $this->_load_tables('/bookcal/sql/'); + $result = $this->_load_tables('/install/mysql/', 'bookcal'); if ($result < 0) { return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 934464db3de..8e0acd832d5 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -645,6 +645,8 @@ Module2300Name=Scheduled jobs Module2300Desc=Scheduled jobs management (alias cron or chrono table) Module2400Name=Events/Agenda Module2400Desc=Track events. Log automatic events for tracking purposes or record manual events or meetings. This is the principal module for good Customer or Vendor Relationship Management. +Module2430Name=Booking Calendar System +Module2430Desc=Provide an online calendar to allow anyone to book rendez-vous, according to predefined ranges or availabilities. Module2500Name=DMS / ECM Module2500Desc=Document Management System / Electronic Content Management. Automatic organization of your generated or stored documents. Share them when you need. Module2600Name=API / Web services (SOAP server) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 98b2bec97a0..29f400fc778 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -2763,11 +2763,13 @@ class Societe extends CommonObject $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; } $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; - $linkclose .= ' class="classfortooltip refurl"'; + $linkclose .= ' class="classfortooltip refurl valignmiddle"'; $target_value = array('_self', '_blank', '_parent', '_top'); if (in_array($target, $target_value)) { $linkclose .= ' target="'.dol_escape_htmltag($target).'"'; } + } else { + $linkclose .= ' class="valignmiddle"'; } $linkstart .= $linkclose.'>'; $linkend = ''; From b2d9ade2d34443e48a0aeca8ce212b0d0f1d501a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 01:26:59 +0100 Subject: [PATCH 668/816] Fix bad test --- htdocs/comm/action/peruser.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index 0ee3b6db4a1..fda36284add 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -628,10 +628,11 @@ if ($mode == 'show_day') { if ($type) { $sql .= " AND ca.id = ".((int) $type); } +var_dump($status); if ($status == '0') { $sql .= " AND a.percent = 0"; } -if ($status == '-1' || $status == 'na') { +if ($status === 'na') { // Not applicable $sql .= " AND a.percent = -1"; } @@ -658,7 +659,7 @@ if ($filtert > 0 || $usergroup > 0) { } // Sort on date $sql .= ' ORDER BY fk_user_action, datep'; //fk_user_action - +print $sql; dol_syslog("comm/action/peruser.php", LOG_DEBUG); $resql = $db->query($sql); From df345945ad67794f9310f206f7b714d18ca1248f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 01:28:04 +0100 Subject: [PATCH 669/816] Fix regression --- htdocs/comm/action/peruser.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index fda36284add..bf0747a2582 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -628,7 +628,6 @@ if ($mode == 'show_day') { if ($type) { $sql .= " AND ca.id = ".((int) $type); } -var_dump($status); if ($status == '0') { $sql .= " AND a.percent = 0"; } @@ -659,7 +658,6 @@ if ($filtert > 0 || $usergroup > 0) { } // Sort on date $sql .= ' ORDER BY fk_user_action, datep'; //fk_user_action -print $sql; dol_syslog("comm/action/peruser.php", LOG_DEBUG); $resql = $db->query($sql); From d3c4255e0e12a16228a67ce135ab8ab34f9847c6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 01:28:48 +0100 Subject: [PATCH 670/816] Fix bad test --- htdocs/comm/action/peruser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index 5c5ef948c30..c6c91228af0 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -628,7 +628,7 @@ if ($type) { if ($status == '0') { $sql .= " AND a.percent = 0"; } -if ($status == '-1' || $status == 'na') { +if ($status == 'na') { // Not applicable $sql .= " AND a.percent = -1"; } From a6936a0b6a5f3b3b323befaf212d95baa1227e2d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 02:26:24 +0100 Subject: [PATCH 671/816] Debug v17 --- htdocs/comm/action/list.php | 5 +- htdocs/comm/action/pertype.php | 88 ++++++++++++++++++---------------- htdocs/comm/action/peruser.php | 53 ++++++++++++-------- 3 files changed, 81 insertions(+), 65 deletions(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index ab2037d5f76..8807ccd4764 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -795,9 +795,8 @@ if (!empty($arrayfields['a.tms']['checked'])) { print '
    '; } if (!empty($arrayfields['a.percent']['checked'])) { - print ''; } // Action column diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index c13de5fb183..9d3bd0044e4 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -63,23 +63,19 @@ if (empty($filtert) && empty($conf->global->AGENDA_ALL_CALENDARS)) { // Sorting $sortfield = GETPOST('sortfield', 'aZ09comma'); -if (!$sortfield) { - $sortfield = "a.datec"; -} - $sortorder = GETPOST('sortorder', 'aZ09comma'); -if (!$sortorder) { - $sortorder = "ASC"; -} - -// Page $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $offset = $limit * $page; - +if (!$sortorder) { + $sortorder = "ASC"; +} +if (!$sortfield) { + $sortfield = "a.datec"; +} // Security check @@ -110,14 +106,14 @@ $month = GETPOST("month", "int") ? GETPOST("month", "int") : date("m"); $week = GETPOST("week", "int") ? GETPOST("week", "int") : date("W"); $day = GETPOST("day", "int") ? GETPOST("day", "int") : date("d"); $pid = GETPOSTISSET("search_projectid") ? GETPOST("search_projectid", "int", 3) : GETPOST("projectid", "int", 3); -$status = GETPOSTISSET("search_status") ? GETPOST("search_status", 'alpha') : GETPOST("status", 'alpha'); +$status = GETPOSTISSET("search_status") ? GETPOST("search_status", 'aZ09') : GETPOST("status", 'aZ09'); $type = GETPOSTISSET("search_type") ? GETPOST("search_type", 'alpha') : GETPOST("type", 'alpha'); $maxprint = ((GETPOST("maxprint", 'int') != '') ? GETPOST("maxprint", 'int') : $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW); $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') // Set actioncode (this code must be same for setting actioncode into peruser, listacton and index) -if (GETPOST('search_actioncode', 'array')) { - $actioncode = GETPOST('search_actioncode', 'array', 3); +if (GETPOST('search_actioncode', 'array:aZ09')) { + $actioncode = GETPOST('search_actioncode', 'array:aZ09', 3); if (!count($actioncode)) { $actioncode = '0'; } @@ -321,7 +317,7 @@ if ($pid) { if ($type) { $param .= "&search_type=".urlencode($type); } -if ($mode == 'show_day' || $mode == 'show_week' || $mode == 'show_month' || $mode != 'show_peruser') { +if ($mode != 'show_pertype') { $param .= '&mode='.urlencode($mode); } if ($begin_h != '') { @@ -356,12 +352,13 @@ $next_year = $year + 1; $next_month = $month; $next_day = $day; -// Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) +// Define firstdaytoshow and lastdaytoshow. Warning: lastdaytoshow is last second to show + 1 +// $firstdaytoshow and lastdaytoshow become a gmt dates to use to search/compare because first_xxx are in tz idea and we used tzuserrel $firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'tzuserrel'); $lastdaytoshow = dol_time_plus_duree($firstdaytoshow, 7, 'd'); //print $firstday.'-'.$first_month.'-'.$first_year; -//print dol_print_date($firstdaytoshow,'dayhour'); -//print dol_print_date($lastdaytoshow,'dayhour'); +//print dol_print_date($firstdaytoshow, 'dayhour', 'gmt'); +//print dol_print_date($lastdaytoshow,'dayhour', 'gmt'); $max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year, 'gmt')); @@ -480,7 +477,7 @@ if (empty($reshook)) { $viewmode = $hookmanager->resPrint; } - +$newparam = ''; $newcardbutton = ''; if ($user->rights->agenda->myactions->create || $user->hasRight('agenda', 'allactions', 'create')) { $tmpforcreatebutton = dol_getdate(dol_now(), true); @@ -595,12 +592,12 @@ if ($filtert > 0 || $usergroup > 0) { if ($mode == 'show_day') { $sql .= " AND ("; $sql .= " (a.datep BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'"; - $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year))."')"; + $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')"; $sql .= " OR "; $sql .= " (a.datep2 BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'"; - $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year))."')"; + $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')"; $sql .= " OR "; - $sql .= " (a.datep < '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year))."'"; + $sql .= " (a.datep < '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'"; $sql .= " AND a.datep2 > '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')"; $sql .= ')'; } else { @@ -622,12 +619,14 @@ if ($type) { if ($status == '0') { $sql .= " AND a.percent = 0"; } -if ($status == '-1') { +if ($status === 'na') { + // Not applicable $sql .= " AND a.percent = -1"; -} // Not applicable +} if ($status == '50') { + // Running already started $sql .= " AND (a.percent > 0 AND a.percent < 100)"; -} // Running already started +} if ($status == 'done' || $status == '100') { $sql .= " AND (a.percent = 100)"; } @@ -791,8 +790,9 @@ echo ''; //print "begin_d=".$begin_d." end_d=".$end_d; +echo '
    '; -echo '
    '; $searchpicto = $form->showFilterButtons('left'); print $searchpicto; @@ -776,9 +776,9 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } if (!empty($arrayfields['t.'.$key]['checked'])) { - print ''; + print ''; if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { - print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status onrightofpage' : ''), 1); + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100'.($key == 'status' ? ' search_status width100 onrightofpage' : ''), 1); } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth250', 1); } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { @@ -806,7 +806,7 @@ $parameters = array('arrayfields'=>$arrayfields); $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { +if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { print ''; $searchpicto = $form->showFilterButtons(); print $searchpicto; @@ -820,7 +820,7 @@ $totalarray['nbfield'] = 0; // Fields title label // -------------------------------------------------------------------- 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; @@ -910,7 +910,7 @@ while ($i < $imaxinloop) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; } - if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'ref', 'status'))) { + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; @@ -953,7 +953,7 @@ while ($i < $imaxinloop) { $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column - if (empty($conf->global->MAIN_CHECKBOX_LEFT_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; @@ -984,7 +984,7 @@ if ($num == 0) { $colspan++; } } - print '
    '.$langs->trans("NoRecordFound").'
    '.$langs->trans("NoRecordFound").'
    '; - print ''; + print ''; print ''; - $formactions->form_select_status_action('formaction', $search_status, 1, 'search_status', 1, 2, 'minwidth100imp maxwidth125'); - print ajax_combobox('selectsearch_status'); + print ''; + $formactions->form_select_status_action('formaction', $search_status, 1, 'search_status', 1, 2, 'search_status width100 onrightofpage'); print '
    '; +echo '
    '; echo ''; echo ''; @@ -850,10 +850,11 @@ foreach ($typeofevents as $typeofevent) { // Show days of the current week $curtime = dol_time_plus_duree($firstdaytoshow, $iter_day, 'd'); - $tmparray = dol_getdate($curtime, 'fast'); - $tmpday = $tmparray['mday']; - $tmpmonth = $tmparray['mon']; - $tmpyear = $tmparray['year']; + // $curtime is a gmt time, but we want the day, month, year in user TZ + $tmpday = dol_print_date($curtime, "%d", "tzuserrel"); + $tmpmonth = dol_print_date($curtime, "%m", "tzuserrel"); + $tmpyear = dol_print_date($curtime, "%Y", "tzuserrel"); + //var_dump($curtime.' '.$tmpday.' '.$tmpmonth.' '.$tmpyear); $style = 'cal_current_month'; if ($iter_day == 6) { @@ -878,6 +879,8 @@ foreach ($typeofevents as $typeofevent) { echo "
    \n"; echo "
    "; +echo ''; + if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { $langs->load("commercial"); print '
    '.$langs->trans("Legend").':
    '; @@ -987,14 +990,14 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s // We are in a particular day for $username, now we scan all events foreach ($eventarray as $daykey => $notused) { - $annee = dol_print_date($daykey, '%Y'); - $mois = dol_print_date($daykey, '%m'); - $jour = dol_print_date($daykey, '%d'); + $annee = dol_print_date($daykey, '%Y', 'tzuserrel'); + $mois = dol_print_date($daykey, '%m', 'tzuserrel'); + $jour = dol_print_date($daykey, '%d', 'tzuserrel'); - if ($day == $jour && $month == $mois && $year == $annee) { // Is it the day we are looking for when calling function ? + if ($day == $jour && (int) $month == (int) $mois && $year == $annee) { // Is it the day we are looking for when calling function ? // Scan all event for this date foreach ($eventarray[$daykey] as $index => $event) { - //print $daykey.' '.$year.'-'.$month.'-'.$day.' -> '.$event->id.' '.$index.' '.$annee.'-'.$mois.'-'.$jour."
    \n"; + //print 'daykey='.$daykey.' '.$year.'-'.$month.'-'.$day.' -> '.$event->id.' '.$index.' '.$annee.'-'.$mois.'-'.$jour."
    \n"; //var_dump($event); $keysofuserassigned = array_keys($event->userassigned); @@ -1176,7 +1179,7 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s } } - // Now output $casesX + // Now output $casesX from start hour to end hour for ($h = $begin_h; $h < $end_h; $h++) { $color1 = ''; $color2 = ''; $style1 = ''; $style2 = ''; @@ -1217,11 +1220,12 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s } } - $ids1 = ''; $ids2 = ''; - if (count($cases1[$h]) && array_keys($cases1[$h])) { + $ids1 = ''; + $ids2 = ''; + if (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) && array_keys($cases1[$h])) { $ids1 = join(',', array_keys($cases1[$h])); } - if (count($cases2[$h]) && array_keys($cases2[$h])) { + if (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) && array_keys($cases2[$h])) { $ids2 = join(',', array_keys($cases2[$h])); } @@ -1230,7 +1234,7 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s } else { echo '
    '; } - if (count($cases1[$h]) == 1) { // only 1 event + if (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) == 1) { // only 1 event $output = array_slice($cases1[$h], 0, 1); $title1 = $langs->trans("Ref").' '.$ids1.($title1 ? ' - '.$title1 : ''); if ($output[0]['string']) { @@ -1239,12 +1243,12 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s if ($output[0]['color']) { $color1 = $output[0]['color']; } - } elseif (count($cases1[$h]) > 1) { + } elseif (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) > 1) { $title1 = $langs->trans("Ref").' '.$ids1.($title1 ? ' - '.$title1 : ''); $color1 = '222222'; } - if (count($cases2[$h]) == 1) { // only 1 event + if (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) == 1) { // only 1 event $output = array_slice($cases2[$h], 0, 1); $title2 = $langs->trans("Ref").' '.$ids2.($title2 ? ' - '.$title2 : ''); if ($output[0]['string']) { @@ -1253,7 +1257,7 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s if ($output[0]['color']) { $color2 = $output[0]['color']; } - } elseif (count($cases2[$h]) > 1) { + } elseif (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) > 1) { $title2 = $langs->trans("Ref").' '.$ids2.($title2 ? ' - '.$title2 : ''); $color2 = '222222'; } diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index bf0747a2582..1ae651dae6d 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -349,14 +349,14 @@ $next_year = $next['year']; $next_month = $next['month']; $next_day = $next['day']; -// Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) -$firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'gmt'); - +// Define firstdaytoshow and lastdaytoshow. Warning: lastdaytoshow is last second to show + 1 +// $firstdaytoshow and lastdaytoshow become a gmt dates to use to search/compare because first_xxx are in tz idea and we used tzuserrel +$firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'tzuserrel'); $nb_weeks_to_show = (!empty($conf->global->AGENDA_NB_WEEKS_IN_VIEW_PER_USER)) ? ((int) $conf->global->AGENDA_NB_WEEKS_IN_VIEW_PER_USER * 7) : 7; $lastdaytoshow = dol_time_plus_duree($firstdaytoshow, $nb_weeks_to_show, 'd'); //print $firstday.'-'.$first_month.'-'.$first_year; -//print dol_print_date($firstdaytoshow,'dayhour'); -//print dol_print_date($lastdaytoshow,'dayhour'); +//print dol_print_date($firstdaytoshow, 'dayhour', 'gmt'); +//print dol_print_date($lastdaytoshow,'dayhour', 'gmt'); $max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year, 'gmt')); @@ -658,6 +658,7 @@ if ($filtert > 0 || $usergroup > 0) { } // Sort on date $sql .= ' ORDER BY fk_user_action, datep'; //fk_user_action +//print $sql; dol_syslog("comm/action/peruser.php", LOG_DEBUG); $resql = $db->query($sql); @@ -667,6 +668,7 @@ if ($resql) { $i = 0; while ($i < $num) { $obj = $db->fetch_object($resql); + //print $obj->fk_user_action.' '.$obj->id."
    "; // Discard auto action if option is on if (!empty($conf->global->AGENDA_ALWAYS_HIDE_AUTO) && $obj->code == 'AC_OTH_AUTO') { @@ -677,6 +679,7 @@ if ($resql) { $datep = $db->jdate($obj->datep); $datep2 = $db->jdate($obj->datep2); + // Create a new object action $event = new ActionComm($db); $event->id = $obj->id; @@ -719,13 +722,15 @@ if ($resql) { } } + //print '
    '.$i.' - eventid='.$event->id.' '.dol_print_date($event->date_start_in_calendar, 'dayhour').' '.dol_print_date($firstdaytoshow, 'dayhour').' - '.dol_print_date($event->date_end_in_calendar, 'dayhour').' '.dol_print_date($lastdaytoshow, 'dayhour').'
    '."\n"; + // Check values if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) { // This record is out of visible range unset($event); } else { - //print $i.' - '.dol_print_date($this->date_start_in_calendar, 'dayhour').' - '.dol_print_date($this->date_end_in_calendar, 'dayhour').'
    '."\n"; + //print $i.' - eventid='.$event->id.' '.dol_print_date($event->date_start_in_calendar, 'dayhour').' - '.dol_print_date($event->date_end_in_calendar, 'dayhour').'
    '."\n"; $event->fetch_userassigned(); // This load $event->userassigned if ($event->date_start_in_calendar < $firstdaytoshow) { @@ -746,7 +751,7 @@ if ($resql) { $loop = true; $j = 0; $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt'); do { - //if ($event->id==408) print 'daykey='.$daykey.' '.$event->datep.' '.$event->datef.'
    '; + //print 'Add event into eventarray for daykey='.$daykey.'='.dol_print_date($daykey, 'dayhour', 'gmt').' '.$event->id.' '.$event->datep.' '.$event->datef.'
    '; $eventarray[$daykey][] = $event; $j++; @@ -804,6 +809,7 @@ echo ''; $currentdaytoshow = $firstdaytoshow; echo '
    '; +//print dol_print_date($currentdaytoshow, 'dayhour', 'gmt'); while ($currentdaytoshow < $lastdaytoshow) { echo ''; @@ -855,9 +861,9 @@ while ($currentdaytoshow < $lastdaytoshow) { echo ''.$langs->trans("Day".(($i + (isset($conf->global->MAIN_START_WEEK) ? $conf->global->MAIN_START_WEEK : 1)) % 7)).''; print "
    "; if ($i) { - print dol_print_date(dol_time_plus_duree($currentdaytoshow, $i, 'd'), 'day'); + print dol_print_date(dol_time_plus_duree($currentdaytoshow, $i, 'd'), 'day', 'tzuserrel'); } else { - print dol_print_date($currentdaytoshow, 'day'); + print dol_print_date($currentdaytoshow, 'day', 'tzuserrel'); } echo "\n"; $i++; @@ -978,6 +984,8 @@ while ($currentdaytoshow < $lastdaytoshow) { $showheader = true; $var = false; foreach ($usernames as $username) { + //if ($username->login != 'admin') continue; + $var = !$var; echo ""; echo '
    '; @@ -995,10 +1003,10 @@ while ($currentdaytoshow < $lastdaytoshow) { // Show days of the current week $curtime = dol_time_plus_duree($currentdaytoshow, $iter_day, 'd'); - $tmparray = dol_getdate($curtime, 'fast'); - $tmpday = $tmparray['mday']; - $tmpmonth = $tmparray['mon']; - $tmpyear = $tmparray['year']; + // $curtime is a gmt time, but we want the day, month, year in user TZ + $tmpday = dol_print_date($curtime, "%d", "tzuserrel"); + $tmpmonth = dol_print_date($curtime, "%m", "tzuserrel"); + $tmpyear = dol_print_date($curtime, "%Y", "tzuserrel"); //var_dump($curtime.' '.$tmpday.' '.$tmpmonth.' '.$tmpyear); $style = 'cal_current_month'; @@ -1136,17 +1144,22 @@ function show_day_events2($username, $day, $month, $year, $monthshown, $style, & //if ($username->id && $day==1) { //var_dump($eventarray); //} + //var_dump("------ username=".$username->login." for day=".$day); // We are in a particular day for $username, now we scan all events foreach ($eventarray as $daykey => $notused) { - $annee = dol_print_date($daykey, '%Y'); - $mois = dol_print_date($daykey, '%m'); - $jour = dol_print_date($daykey, '%d'); + $annee = dol_print_date($daykey, '%Y', 'tzuserrel'); + $mois = dol_print_date($daykey, '%m', 'tzuserrel'); + $jour = dol_print_date($daykey, '%d', 'tzuserrel'); + //var_dump("daykey=$daykey day=$day jour=$jour, month=$month mois=$mois, year=$year annee=$annee"); + + + if ($day == $jour && (int) $month == (int) $mois && $year == $annee) { // Is it the day we are looking for when calling function ? + //var_dump("day=$day jour=$jour month=$month mois=$mois year=$year annee=$annee"); - if ($day == $jour && $month == $mois && $year == $annee) { // Is it the day we are looking for when calling function ? // Scan all event for this date foreach ($eventarray[$daykey] as $index => $event) { - //print $daykey.' '.dol_print_date($daykey, 'dayhour', 'gmt').' '.$year.'-'.$month.'-'.$day.' -> '.$event->id.' '.$index.' '.$annee.'-'.$mois.'-'.$jour."
    \n"; + //print 'daykey='.$daykey.'='.dol_print_date($daykey, 'dayhour', 'gmt').' '.$year.'-'.$month.'-'.$day.' -> This event: '.$event->id.' '.$index.' is open for this daykey '.$annee.'-'.$mois.'-'.$jour."
    \n"; //var_dump($event); $keysofuserassigned = array_keys($event->userassigned); @@ -1355,7 +1368,7 @@ function show_day_events2($username, $day, $month, $year, $monthshown, $style, & } } - // Now output $casesX + // Now output $casesX from start hour to end hour for ($h = $begin_h; $h < $end_h; $h++) { $color1 = ''; $color2 = ''; $style1 = ''; $style2 = ''; @@ -1437,7 +1450,7 @@ function show_day_events2($username, $day, $month, $year, $monthshown, $style, & $title2 = $langs->trans("Ref").' '.$ids2.($title2 ? ' - '.$title2 : ''); $color2 = '222222'; } - print ''; + print '
    '; print ''; } if (!empty($arrayfields['a.percent']['checked'])) { - print ''; } // Action column diff --git a/htdocs/comm/action/pertype.php b/htdocs/comm/action/pertype.php index 61092df5665..7fe8f8108ed 100644 --- a/htdocs/comm/action/pertype.php +++ b/htdocs/comm/action/pertype.php @@ -63,23 +63,19 @@ if (empty($filtert) && empty($conf->global->AGENDA_ALL_CALENDARS)) { // Sorting $sortfield = GETPOST('sortfield', 'aZ09comma'); -if (!$sortfield) { - $sortfield = "a.datec"; -} - $sortorder = GETPOST('sortorder', 'aZ09comma'); -if (!$sortorder) { - $sortorder = "ASC"; -} - -// Page $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $offset = $limit * $page; - +if (!$sortorder) { + $sortorder = "ASC"; +} +if (!$sortfield) { + $sortfield = "a.datec"; +} // Security check @@ -110,14 +106,14 @@ $month = GETPOST("month", "int") ? GETPOST("month", "int") : date("m"); $week = GETPOST("week", "int") ? GETPOST("week", "int") : date("W"); $day = GETPOST("day", "int") ? GETPOST("day", "int") : date("d"); $pid = GETPOSTISSET("search_projectid") ? GETPOST("search_projectid", "int", 3) : GETPOST("projectid", "int", 3); -$status = GETPOSTISSET("search_status") ? GETPOST("search_status", 'alpha') : GETPOST("status", 'alpha'); +$status = GETPOSTISSET("search_status") ? GETPOST("search_status", 'aZ09') : GETPOST("status", 'aZ09'); $type = GETPOSTISSET("search_type") ? GETPOST("search_type", 'alpha') : GETPOST("type", 'alpha'); $maxprint = ((GETPOST("maxprint", 'int') != '') ? GETPOST("maxprint", 'int') : $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW); $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') // Set actioncode (this code must be same for setting actioncode into peruser, listacton and index) -if (GETPOST('search_actioncode', 'array')) { - $actioncode = GETPOST('search_actioncode', 'array', 3); +if (GETPOST('search_actioncode', 'array:aZ09')) { + $actioncode = GETPOST('search_actioncode', 'array:aZ09', 3); if (!count($actioncode)) { $actioncode = '0'; } @@ -321,7 +317,7 @@ if ($pid) { if ($type) { $param .= "&search_type=".urlencode($type); } -if ($mode == 'show_day' || $mode == 'show_week' || $mode == 'show_month' || $mode != 'show_peruser') { +if ($mode != 'show_pertype') { $param .= '&mode='.urlencode($mode); } if ($begin_h != '') { @@ -356,12 +352,13 @@ $next_year = $year + 1; $next_month = $month; $next_day = $day; -// Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) +// Define firstdaytoshow and lastdaytoshow. Warning: lastdaytoshow is last second to show + 1 +// $firstdaytoshow and lastdaytoshow become a gmt dates to use to search/compare because first_xxx are in tz idea and we used tzuserrel $firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'tzuserrel'); $lastdaytoshow = dol_time_plus_duree($firstdaytoshow, 7, 'd'); //print $firstday.'-'.$first_month.'-'.$first_year; -//print dol_print_date($firstdaytoshow,'dayhour'); -//print dol_print_date($lastdaytoshow,'dayhour'); +//print dol_print_date($firstdaytoshow, 'dayhour', 'gmt'); +//print dol_print_date($lastdaytoshow,'dayhour', 'gmt'); $max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year, 'gmt')); @@ -477,7 +474,7 @@ if (empty($reshook)) { $viewmode = $hookmanager->resPrint; } - +$newparam = ''; $newcardbutton = ''; if ($user->rights->agenda->myactions->create || $user->rights->agenda->allactions->create) { $tmpforcreatebutton = dol_getdate(dol_now(), true); @@ -592,12 +589,12 @@ if ($filtert > 0 || $usergroup > 0) { if ($mode == 'show_day') { $sql .= " AND ("; $sql .= " (a.datep BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'"; - $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year))."')"; + $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')"; $sql .= " OR "; $sql .= " (a.datep2 BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'"; - $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year))."')"; + $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')"; $sql .= " OR "; - $sql .= " (a.datep < '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year))."'"; + $sql .= " (a.datep < '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'"; $sql .= " AND a.datep2 > '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')"; $sql .= ')'; } else { @@ -619,12 +616,14 @@ if ($type) { if ($status == '0') { $sql .= " AND a.percent = 0"; } -if ($status == '-1') { +if ($status === 'na') { + // Not applicable $sql .= " AND a.percent = -1"; -} // Not applicable +} if ($status == '50') { + // Running already started $sql .= " AND (a.percent > 0 AND a.percent < 100)"; -} // Running already started +} if ($status == 'done' || $status == '100') { $sql .= " AND (a.percent = 100)"; } @@ -788,8 +787,9 @@ echo ''; //print "begin_d=".$begin_d." end_d=".$end_d; +echo '
    '; -echo '
    Date: Thu, 19 Jan 2023 02:26:24 +0100 Subject: [PATCH 672/816] Debug v17 --- htdocs/comm/action/list.php | 5 +- htdocs/comm/action/pertype.php | 88 ++++++++++++++++++---------------- htdocs/comm/action/peruser.php | 53 ++++++++++++-------- 3 files changed, 81 insertions(+), 65 deletions(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 5eb538d4e62..4ff5c864908 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -795,9 +795,8 @@ if (!empty($arrayfields['a.tms']['checked'])) { print ''; - $formactions->form_select_status_action('formaction', $search_status, 1, 'search_status', 1, 2, 'minwidth100imp maxwidth125'); - print ajax_combobox('selectsearch_status'); + print ''; + $formactions->form_select_status_action('formaction', $search_status, 1, 'search_status', 1, 2, 'search_status width100 onrightofpage'); print '
    '; +echo '
    '; echo ''; echo ''; @@ -847,10 +847,11 @@ foreach ($typeofevents as $typeofevent) { // Show days of the current week $curtime = dol_time_plus_duree($firstdaytoshow, $iter_day, 'd'); - $tmparray = dol_getdate($curtime, 'fast'); - $tmpday = $tmparray['mday']; - $tmpmonth = $tmparray['mon']; - $tmpyear = $tmparray['year']; + // $curtime is a gmt time, but we want the day, month, year in user TZ + $tmpday = dol_print_date($curtime, "%d", "tzuserrel"); + $tmpmonth = dol_print_date($curtime, "%m", "tzuserrel"); + $tmpyear = dol_print_date($curtime, "%Y", "tzuserrel"); + //var_dump($curtime.' '.$tmpday.' '.$tmpmonth.' '.$tmpyear); $style = 'cal_current_month'; if ($iter_day == 6) { @@ -875,6 +876,8 @@ foreach ($typeofevents as $typeofevent) { echo "
    \n"; echo "
    "; +echo ''; + if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { $langs->load("commercial"); print '
    '.$langs->trans("Legend").':
    '; @@ -984,14 +987,14 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s // We are in a particular day for $username, now we scan all events foreach ($eventarray as $daykey => $notused) { - $annee = dol_print_date($daykey, '%Y'); - $mois = dol_print_date($daykey, '%m'); - $jour = dol_print_date($daykey, '%d'); + $annee = dol_print_date($daykey, '%Y', 'tzuserrel'); + $mois = dol_print_date($daykey, '%m', 'tzuserrel'); + $jour = dol_print_date($daykey, '%d', 'tzuserrel'); - if ($day == $jour && $month == $mois && $year == $annee) { // Is it the day we are looking for when calling function ? + if ($day == $jour && (int) $month == (int) $mois && $year == $annee) { // Is it the day we are looking for when calling function ? // Scan all event for this date foreach ($eventarray[$daykey] as $index => $event) { - //print $daykey.' '.$year.'-'.$month.'-'.$day.' -> '.$event->id.' '.$index.' '.$annee.'-'.$mois.'-'.$jour."
    \n"; + //print 'daykey='.$daykey.' '.$year.'-'.$month.'-'.$day.' -> '.$event->id.' '.$index.' '.$annee.'-'.$mois.'-'.$jour."
    \n"; //var_dump($event); $keysofuserassigned = array_keys($event->userassigned); @@ -1173,7 +1176,7 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s } } - // Now output $casesX + // Now output $casesX from start hour to end hour for ($h = $begin_h; $h < $end_h; $h++) { $color1 = ''; $color2 = ''; $style1 = ''; $style2 = ''; @@ -1214,11 +1217,12 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s } } - $ids1 = ''; $ids2 = ''; - if (count($cases1[$h]) && array_keys($cases1[$h])) { + $ids1 = ''; + $ids2 = ''; + if (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) && array_keys($cases1[$h])) { $ids1 = join(',', array_keys($cases1[$h])); } - if (count($cases2[$h]) && array_keys($cases2[$h])) { + if (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) && array_keys($cases2[$h])) { $ids2 = join(',', array_keys($cases2[$h])); } @@ -1227,7 +1231,7 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s } else { echo '
    '; } - if (count($cases1[$h]) == 1) { // only 1 event + if (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) == 1) { // only 1 event $output = array_slice($cases1[$h], 0, 1); $title1 = $langs->trans("Ref").' '.$ids1.($title1 ? ' - '.$title1 : ''); if ($output[0]['string']) { @@ -1236,12 +1240,12 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s if ($output[0]['color']) { $color1 = $output[0]['color']; } - } elseif (count($cases1[$h]) > 1) { + } elseif (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) > 1) { $title1 = $langs->trans("Ref").' '.$ids1.($title1 ? ' - '.$title1 : ''); $color1 = '222222'; } - if (count($cases2[$h]) == 1) { // only 1 event + if (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) == 1) { // only 1 event $output = array_slice($cases2[$h], 0, 1); $title2 = $langs->trans("Ref").' '.$ids2.($title2 ? ' - '.$title2 : ''); if ($output[0]['string']) { @@ -1250,7 +1254,7 @@ function show_day_events_pertype($username, $day, $month, $year, $monthshown, $s if ($output[0]['color']) { $color2 = $output[0]['color']; } - } elseif (count($cases2[$h]) > 1) { + } elseif (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) > 1) { $title2 = $langs->trans("Ref").' '.$ids2.($title2 ? ' - '.$title2 : ''); $color2 = '222222'; } diff --git a/htdocs/comm/action/peruser.php b/htdocs/comm/action/peruser.php index c6c91228af0..993bc3a908a 100644 --- a/htdocs/comm/action/peruser.php +++ b/htdocs/comm/action/peruser.php @@ -349,14 +349,14 @@ $next_year = $next['year']; $next_month = $next['month']; $next_day = $next['day']; -// Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) -$firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'gmt'); - +// Define firstdaytoshow and lastdaytoshow. Warning: lastdaytoshow is last second to show + 1 +// $firstdaytoshow and lastdaytoshow become a gmt dates to use to search/compare because first_xxx are in tz idea and we used tzuserrel +$firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'tzuserrel'); $nb_weeks_to_show = (!empty($conf->global->AGENDA_NB_WEEKS_IN_VIEW_PER_USER)) ? ((int) $conf->global->AGENDA_NB_WEEKS_IN_VIEW_PER_USER * 7) : 7; $lastdaytoshow = dol_time_plus_duree($firstdaytoshow, $nb_weeks_to_show, 'd'); //print $firstday.'-'.$first_month.'-'.$first_year; -//print dol_print_date($firstdaytoshow,'dayhour'); -//print dol_print_date($lastdaytoshow,'dayhour'); +//print dol_print_date($firstdaytoshow, 'dayhour', 'gmt'); +//print dol_print_date($lastdaytoshow,'dayhour', 'gmt'); $max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year, 'gmt')); @@ -655,6 +655,7 @@ if ($filtert > 0 || $usergroup > 0) { } // Sort on date $sql .= ' ORDER BY fk_user_action, datep'; //fk_user_action +//print $sql; dol_syslog("comm/action/peruser.php", LOG_DEBUG); @@ -665,6 +666,7 @@ if ($resql) { $i = 0; while ($i < $num) { $obj = $db->fetch_object($resql); + //print $obj->fk_user_action.' '.$obj->id."
    "; // Discard auto action if option is on if (!empty($conf->global->AGENDA_ALWAYS_HIDE_AUTO) && $obj->code == 'AC_OTH_AUTO') { @@ -675,6 +677,7 @@ if ($resql) { $datep = $db->jdate($obj->datep); $datep2 = $db->jdate($obj->datep2); + // Create a new object action $event = new ActionComm($db); $event->id = $obj->id; @@ -717,13 +720,15 @@ if ($resql) { } } + //print '
    '.$i.' - eventid='.$event->id.' '.dol_print_date($event->date_start_in_calendar, 'dayhour').' '.dol_print_date($firstdaytoshow, 'dayhour').' - '.dol_print_date($event->date_end_in_calendar, 'dayhour').' '.dol_print_date($lastdaytoshow, 'dayhour').'
    '."\n"; + // Check values if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) { // This record is out of visible range unset($event); } else { - //print $i.' - '.dol_print_date($this->date_start_in_calendar, 'dayhour').' - '.dol_print_date($this->date_end_in_calendar, 'dayhour').'
    '."\n"; + //print $i.' - eventid='.$event->id.' '.dol_print_date($event->date_start_in_calendar, 'dayhour').' - '.dol_print_date($event->date_end_in_calendar, 'dayhour').'
    '."\n"; $event->fetch_userassigned(); // This load $event->userassigned if ($event->date_start_in_calendar < $firstdaytoshow) { @@ -744,7 +749,7 @@ if ($resql) { $loop = true; $j = 0; $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt'); do { - //if ($event->id==408) print 'daykey='.$daykey.' '.$event->datep.' '.$event->datef.'
    '; + //print 'Add event into eventarray for daykey='.$daykey.'='.dol_print_date($daykey, 'dayhour', 'gmt').' '.$event->id.' '.$event->datep.' '.$event->datef.'
    '; $eventarray[$daykey][] = $event; $j++; @@ -802,6 +807,7 @@ echo ''; $currentdaytoshow = $firstdaytoshow; echo '
    '; +//print dol_print_date($currentdaytoshow, 'dayhour', 'gmt'); while ($currentdaytoshow < $lastdaytoshow) { echo ''; @@ -853,9 +859,9 @@ while ($currentdaytoshow < $lastdaytoshow) { echo ''.$langs->trans("Day".(($i + (isset($conf->global->MAIN_START_WEEK) ? $conf->global->MAIN_START_WEEK : 1)) % 7)).''; print "
    "; if ($i) { - print dol_print_date(dol_time_plus_duree($currentdaytoshow, $i, 'd'), 'day'); + print dol_print_date(dol_time_plus_duree($currentdaytoshow, $i, 'd'), 'day', 'tzuserrel'); } else { - print dol_print_date($currentdaytoshow, 'day'); + print dol_print_date($currentdaytoshow, 'day', 'tzuserrel'); } echo "\n"; $i++; @@ -976,6 +982,8 @@ while ($currentdaytoshow < $lastdaytoshow) { $showheader = true; $var = false; foreach ($usernames as $username) { + //if ($username->login != 'admin') continue; + $var = !$var; echo ""; echo ''; // Ref Product - print ''; - // Description + // Description of line print ''; } $db->free($resql); + + if ($num == 0) { + print ''; + } } else { print $db->lasterror(); // Show last sql error } diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index 39508332d40..1cf9149024a 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -418,8 +418,8 @@ if ($result) { print_liste_field_titre("Description", $_SERVER["PHP_SELF"], "erd.comments", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Amount", $_SERVER["PHP_SELF"], "erd.total_ht", "", $param, '', $sortfield, $sortorder, 'right maxwidth50 '); print_liste_field_titre("VATRate", $_SERVER["PHP_SELF"], "erd.tva_tx", "", $param, '', $sortfield, $sortorder, 'right '); - print_liste_field_titre("AccountAccountingSuggest", '', '', '', '', '', '', '', 'nowraponall '); - print_liste_field_titre("IntoAccount", '', '', '', '', '', '', '', ''); + print_liste_field_titre("DataUsedToSuggestAccount", '', '', '', '', '', '', '', 'nowraponall '); + print_liste_field_titre("AccountAccountingSuggest", '', '', '', '', '', '', '', ''); $checkpicto = ''; if ($massactionbutton) { $checkpicto = $form->showCheckAddButtons('checkforselect', 1); diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index dfd8af7f68f..aae34a51e03 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -111,7 +111,7 @@ if (!isModEnabled('accounting')) { if ($user->socid > 0) { accessforbidden(); } -if (empty($user->rights->accounting->mouvements->lire)) { +if (!$user->hasRight('accounting', 'mouvements', 'lire')) { accessforbidden(); } @@ -531,8 +531,8 @@ if ($result) { print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "s.nom", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Country", $_SERVER["PHP_SELF"], "co.label", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("VATIntraShort", $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder); - print_liste_field_titre("AccountAccountingSuggest", '', '', '', '', '', '', '', 'nowraponall '); - print_liste_field_titre("IntoAccount", '', '', '', '', '', '', '', 'center '); + print_liste_field_titre("DataUsedToSuggestAccount", '', '', '', '', '', '', '', 'nowraponall '); + print_liste_field_titre("AccountAccountingSuggest", '', '', '', '', '', '', '', 'center '); $checkpicto = ''; if ($massactionbutton) { $checkpicto = $form->showCheckAddButtons('checkforselect', 1); @@ -711,14 +711,19 @@ if ($result) { // Found accounts print '"; print ''; // Date End print ""; print ''; // Number of terms diff --git a/htdocs/loan/list.php b/htdocs/loan/list.php index 1225f5304be..b664d784e7e 100644 --- a/htdocs/loan/list.php +++ b/htdocs/loan/list.php @@ -42,6 +42,7 @@ $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'); +$massaction = GETPOST('massaction', 'alpha'); if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) { $page = 0; } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action @@ -148,6 +149,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { } $db->free($resql); } +$arrayfields = array(); // Complete request and execute it with limit $sql .= $db->order($sortfield, $sortorder); diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 8a5aecf1513..ac465b16bd7 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1485,7 +1485,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } } - if ($type == 1 && $conf->workstation->enabled) { + if ($type == 1 && isModEnabled("workstation")) { // Default workstation print '
    '; @@ -993,10 +1001,10 @@ while ($currentdaytoshow < $lastdaytoshow) { // Show days of the current week $curtime = dol_time_plus_duree($currentdaytoshow, $iter_day, 'd'); - $tmparray = dol_getdate($curtime, 'fast'); - $tmpday = $tmparray['mday']; - $tmpmonth = $tmparray['mon']; - $tmpyear = $tmparray['year']; + // $curtime is a gmt time, but we want the day, month, year in user TZ + $tmpday = dol_print_date($curtime, "%d", "tzuserrel"); + $tmpmonth = dol_print_date($curtime, "%m", "tzuserrel"); + $tmpyear = dol_print_date($curtime, "%Y", "tzuserrel"); //var_dump($curtime.' '.$tmpday.' '.$tmpmonth.' '.$tmpyear); $style = 'cal_current_month'; @@ -1134,17 +1142,22 @@ function show_day_events2($username, $day, $month, $year, $monthshown, $style, & //if ($username->id && $day==1) { //var_dump($eventarray); //} + //var_dump("------ username=".$username->login." for day=".$day); // We are in a particular day for $username, now we scan all events foreach ($eventarray as $daykey => $notused) { - $annee = dol_print_date($daykey, '%Y'); - $mois = dol_print_date($daykey, '%m'); - $jour = dol_print_date($daykey, '%d'); + $annee = dol_print_date($daykey, '%Y', 'tzuserrel'); + $mois = dol_print_date($daykey, '%m', 'tzuserrel'); + $jour = dol_print_date($daykey, '%d', 'tzuserrel'); + //var_dump("daykey=$daykey day=$day jour=$jour, month=$month mois=$mois, year=$year annee=$annee"); + + + if ($day == $jour && (int) $month == (int) $mois && $year == $annee) { // Is it the day we are looking for when calling function ? + //var_dump("day=$day jour=$jour month=$month mois=$mois year=$year annee=$annee"); - if ($day == $jour && $month == $mois && $year == $annee) { // Is it the day we are looking for when calling function ? // Scan all event for this date foreach ($eventarray[$daykey] as $index => $event) { - //print $daykey.' '.dol_print_date($daykey, 'dayhour', 'gmt').' '.$year.'-'.$month.'-'.$day.' -> '.$event->id.' '.$index.' '.$annee.'-'.$mois.'-'.$jour."
    \n"; + //print 'daykey='.$daykey.'='.dol_print_date($daykey, 'dayhour', 'gmt').' '.$year.'-'.$month.'-'.$day.' -> This event: '.$event->id.' '.$index.' is open for this daykey '.$annee.'-'.$mois.'-'.$jour."
    \n"; //var_dump($event); $keysofuserassigned = array_keys($event->userassigned); @@ -1353,7 +1366,7 @@ function show_day_events2($username, $day, $month, $year, $monthshown, $style, & } } - // Now output $casesX + // Now output $casesX from start hour to end hour for ($h = $begin_h; $h < $end_h; $h++) { $color1 = ''; $color2 = ''; $style1 = ''; $style2 = ''; @@ -1435,7 +1448,7 @@ function show_day_events2($username, $day, $month, $year, $monthshown, $style, & $title2 = $langs->trans("Ref").' '.$ids2.($title2 ? ' - '.$title2 : ''); $color2 = '222222'; } - print ''; + print '
    '; print ''; } // Action column From 79c21e083a42ecaa6ecd67ab91390abad9bd16df Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 14:29:28 +0100 Subject: [PATCH 681/816] Fix bad position title lines --- htdocs/contrat/services_list.php | 111 ++++++++++++++++--------------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 9b3081a412a..21f49ebc789 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -517,60 +517,6 @@ $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfi print '
    '; print '
    Date: Thu, 19 Jan 2023 11:24:53 +0100 Subject: [PATCH 673/816] Harmonize CSS for tables in fichehalfleft/fichehalfright --- htdocs/theme/eldy/global.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 43dfbf67869..1592fed7493 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -3549,7 +3549,7 @@ td.border, div.tagtable div div.border { } -.fichehalfright table.noborder { +.fichehalfright table.noborder , .fichehalfleft table.noborder{ margin: 0px 0px 0px 0px; } table.liste, table.noborder, table.formdoc, div.noborder { From 17b6cb2724ae6afa81b61ec67d974891ab806e1b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 13:23:08 +0100 Subject: [PATCH 674/816] Fix warning --- htdocs/core/modules/mailings/contacts1.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/mailings/contacts1.modules.php b/htdocs/core/modules/mailings/contacts1.modules.php index 09595b61376..eee3ee68e6c 100644 --- a/htdocs/core/modules/mailings/contacts1.modules.php +++ b/htdocs/core/modules/mailings/contacts1.modules.php @@ -309,7 +309,7 @@ class mailing_contacts1 extends MailingTargets // Choose language if multilangue active - if (@$conf->global->MAIN_MULTILANGS==1) { + if (getDolGlobalInt('MAIN_MULTILANGS') == 1) { require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; $formadmin = new FormAdmin($this->db); $s .= ''.$langs->trans("DefaultLang").': '; From 4157263cb898f1847cfcfc22dee6007c01b13a4d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 13:40:37 +0100 Subject: [PATCH 675/816] FIX Add bookmark with search fields that are arrays --- htdocs/bookmarks/bookmarks.lib.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/htdocs/bookmarks/bookmarks.lib.php b/htdocs/bookmarks/bookmarks.lib.php index c13b810a4bc..88cae3e4293 100644 --- a/htdocs/bookmarks/bookmarks.lib.php +++ b/htdocs/bookmarks/bookmarks.lib.php @@ -52,6 +52,7 @@ function printDropdownBookmarksList() } } } + $tmpurl = ''; // No urlencode, all param $url will be urlencoded later if ($sortfield) { @@ -65,7 +66,13 @@ function printDropdownBookmarksList() if ((preg_match('/^search_/', $key) || in_array($key, $authorized_var)) && $val != '' && !array_key_exists($key, $url_param)) { - $url_param[$key] = http_build_query(array(dol_escape_htmltag($key) => dol_escape_htmltag($val))); + if (is_array($val)) { + foreach ($val as $tmpsubval) { + $url_param[] = http_build_query(array(dol_escape_htmltag($key).'[]' => dol_escape_htmltag($tmpsubval))); + } + } elseif ($val != '') { + $url_param[$key] = http_build_query(array(dol_escape_htmltag($key) => dol_escape_htmltag($val))); + } } } } From d426598ab59da022843d23166fe77dab1944990c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 13:46:54 +0100 Subject: [PATCH 676/816] Fix search criteria on service lines --- htdocs/contrat/services_list.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index cfc888e229a..08989fdcad0 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -256,7 +256,7 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid"; if ($search_product_category > 0) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product=cd.fk_product'; } -$sql .= " WHERE c.entity = ".$conf->entity; +$sql .= " WHERE c.entity IN (".getEntity($object->element).")"; $sql .= " AND c.rowid = cd.fk_contrat"; if ($search_product_category > 0) { $sql .= " AND cp.fk_categorie = ".((int) $search_product_category); @@ -281,13 +281,13 @@ if ($filter == "notexpired") { $sql .= " AND cd.date_fin_validite >= '".$db->idate($now)."'"; } if ($search_name) { - $sql .= " AND s.nom LIKE '%".$db->escape($search_name)."%'"; + $sql .= natural_search("c.ref", $search_name); } if ($search_contract) { - $sql .= " AND c.ref LIKE '%".$db->escape($search_contract)."%' "; + $sql .= natural_search("c.ref", $search_contract); } if ($search_service) { - $sql .= " AND (p.ref LIKE '%".$db->escape($search_service)."%' OR p.description LIKE '%".$db->escape($search_service)."%' OR cd.description LIKE '%".$db->escape($search_service)."%')"; + $sql .= natural_search(array("p.ref", "p.description", "cd.description"), $search_service); } if ($socid > 0) { $sql .= " AND s.rowid = ".((int) $socid); From 1afd2069461f6d20a0a86c816840e10884f675ca Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 13:50:11 +0100 Subject: [PATCH 677/816] Fix debug v17 --- htdocs/contrat/services_list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 08989fdcad0..99d03f2d793 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -217,7 +217,7 @@ $form = new Form($db); $sql = "SELECT c.rowid as cid, c.ref, c.statut as cstatut, c.ref_customer, c.ref_supplier,"; $sql .= " s.rowid as socid, s.nom as name, s.email, s.client, s.fournisseur,"; -$sql .= " cd.rowid, cd.description, cd.statut,"; +$sql .= " cd.rowid, cd.description, cd.statut, cd.product_type as type,"; $sql .= " p.rowid as pid, p.ref as pref, p.label as label, p.fk_product_type as ptype, p.tobuy, p.tosell, p.barcode, p.entity as pentity,"; if (empty($user->rights->societe->client->voir) && !$socid) { $sql .= " sc.fk_soc, sc.fk_user,"; From d171750e28567e90b115086cee327874fbf808a8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 13:53:37 +0100 Subject: [PATCH 678/816] Fix warning --- htdocs/contrat/services_list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 99d03f2d793..9b3081a412a 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -692,7 +692,7 @@ $contractstatic = new Contrat($db); $productstatic = new Product($db); $i = 0; -$totalarray = array(); +$totalarray = array('nbfield'=>0); while ($i < min($num, $limit)) { $obj = $db->fetch_object($resql); From 7cf144890feb32fb7e951595cb6acb8c36c1b039 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 14:17:11 +0100 Subject: [PATCH 679/816] Fix default value --- htdocs/contrat/services_list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 99d03f2d793..6efd3e84e4e 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -136,7 +136,7 @@ $arrayfields = array( 's.nom'=>array('label'=>"ThirdParty", 'checked'=>1, 'position'=>90), 'cd.tva_tx'=>array('label'=>"VATRate", 'checked'=>-1, 'position'=>100), 'cd.subprice'=>array('label'=>"PriceUHT", 'checked'=>-1, 'position'=>105), - 'cd.qty'=>array('label'=>"Qty", 'checked'=>-1, 'position'=>108), + 'cd.qty'=>array('label'=>"Qty", 'checked'=>1, 'position'=>108), 'cd.total_ht'=>array('label'=>"TotalHT", 'checked'=>-1, 'position'=>109), 'cd.total_tva'=>array('label'=>"TotalVAT", 'checked'=>-1, 'position'=>110), 'cd.date_ouverture_prevue'=>array('label'=>"DateStartPlannedShort", 'checked'=>(($mode == "" || $mode == -1) || $mode == "0"), 'position'=>150), From d01135a931b0e00c81dfb67ee321a0e1c4e23865 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 14:28:10 +0100 Subject: [PATCH 680/816] css --- htdocs/contrat/class/contrat.class.php | 2 +- htdocs/contrat/services_list.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 539d7b63f31..4d08fdb96cd 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2979,7 +2979,7 @@ class ContratLigne extends CommonObjectLine 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10), 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>30, 'index'=>1), 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35), - 'qty' =>array('type'=>'integer', 'label'=>'Quantity', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35, 'isameasure'=>1), + 'qty' =>array('type'=>'integer', 'label'=>'Quantity', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'position'=>35, 'isameasure'=>1), 'total_ht' =>array('type'=>'integer', 'label'=>'AmountHT', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>36, 'isameasure'=>1), 'total_tva' =>array('type'=>'integer', 'label'=>'AmountVAT', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>37, 'isameasure'=>1), 'total_ttc' =>array('type'=>'integer', 'label'=>'AmountTTC', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>38, 'isameasure'=>1), diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 6efd3e84e4e..19c4659c589 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -137,7 +137,7 @@ $arrayfields = array( 'cd.tva_tx'=>array('label'=>"VATRate", 'checked'=>-1, 'position'=>100), 'cd.subprice'=>array('label'=>"PriceUHT", 'checked'=>-1, 'position'=>105), 'cd.qty'=>array('label'=>"Qty", 'checked'=>1, 'position'=>108), - 'cd.total_ht'=>array('label'=>"TotalHT", 'checked'=>-1, 'position'=>109), + 'cd.total_ht'=>array('label'=>"TotalHT", 'checked'=>-1, 'position'=>109, 'isameasure'=>1), 'cd.total_tva'=>array('label'=>"TotalVAT", 'checked'=>-1, 'position'=>110), 'cd.date_ouverture_prevue'=>array('label'=>"DateStartPlannedShort", 'checked'=>(($mode == "" || $mode == -1) || $mode == "0"), 'position'=>150), 'cd.date_ouverture'=>array('label'=>"DateStartRealShort", 'checked'=>(($mode == "" || $mode == -1) || $mode > 0), 'position'=>160), @@ -670,7 +670,7 @@ if (!empty($arrayfields['cd.tms']['checked'])) { } if (!empty($arrayfields['status']['checked'])) { // Status - print ''; + print ''; $arrayofstatus = array( '0'=>$langs->trans("ServiceStatusInitial"), '4'=>$langs->trans("ServiceStatusRunning"), @@ -678,7 +678,7 @@ if (!empty($arrayfields['status']['checked'])) { '4&filter=expired'=>$langs->trans("ServiceStatusLate"), '5'=>$langs->trans("ServiceStatusClosed") ); - print $form->selectarray('search_status', $arrayofstatus, (strstr($search_status, ',') ?-1 : $search_status), 1, 0, 0, '', 0, 0, 0, '', 'minwidth100imp maxwidth150'); + print $form->selectarray('search_status', $arrayofstatus, (strstr($search_status, ',') ?-1 : $search_status), 1, 0, 0, '', 0, 0, 0, '', 'search_status width100 onrightofpage'); print '
    '."\n"; -print ''; -if (!empty($arrayfields['c.ref']['checked'])) { - print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], "c.ref", "", $param, "", $sortfield, $sortorder); -} -if (!empty($arrayfields['p.description']['checked'])) { - print_liste_field_titre($arrayfields['p.description']['label'], $_SERVER["PHP_SELF"], "p.description", "", $param, "", $sortfield, $sortorder); -} -if (!empty($arrayfields['cd.tva_tx']['checked'])) { - print_liste_field_titre($arrayfields['cd.tva_tx']['label'], $_SERVER["PHP_SELF"], "cd.tva_tx", "", $param, '', $sortfield, $sortorder, 'center nowrap '); -} -if (!empty($arrayfields['cd.subprice']['checked'])) { - print_liste_field_titre($arrayfields['cd.subprice']['label'], $_SERVER["PHP_SELF"], "cd.subprice", "", $param, '', $sortfield, $sortorder, 'center nowrap '); -} -if (!empty($arrayfields['cd.qty']['checked'])) { - print_liste_field_titre($arrayfields['cd.qty']['label'], $_SERVER["PHP_SELF"], "cd.qty", "", $param, '', $sortfield, $sortorder, 'center nowrap '); -} -if (!empty($arrayfields['cd.total_ht']['checked'])) { - print_liste_field_titre($arrayfields['cd.total_ht']['label'], $_SERVER["PHP_SELF"], "cd.total_ht", "", $param, '', $sortfield, $sortorder, 'center nowrap '); -} -if (!empty($arrayfields['cd.total_tva']['checked'])) { - print_liste_field_titre($arrayfields['cd.total_tva']['label'], $_SERVER["PHP_SELF"], "cd.total_tva", "", $param, '', $sortfield, $sortorder, 'center nowrap '); -} -if (!empty($arrayfields['s.nom']['checked'])) { - print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder); -} -if (!empty($arrayfields['cd.date_ouverture_prevue']['checked'])) { - print_liste_field_titre($arrayfields['cd.date_ouverture_prevue']['label'], $_SERVER["PHP_SELF"], "cd.date_ouverture_prevue", "", $param, '', $sortfield, $sortorder, 'center '); -} -if (!empty($arrayfields['cd.date_ouverture']['checked'])) { - print_liste_field_titre($arrayfields['cd.date_ouverture']['label'], $_SERVER["PHP_SELF"], "cd.date_ouverture", "", $param, '', $sortfield, $sortorder, 'center '); -} -if (!empty($arrayfields['cd.date_fin_validite']['checked'])) { - print_liste_field_titre($arrayfields['cd.date_fin_validite']['label'], $_SERVER["PHP_SELF"], "cd.date_fin_validite", "", $param, '', $sortfield, $sortorder, 'center '); -} -if (!empty($arrayfields['cd.date_cloture']['checked'])) { - print_liste_field_titre($arrayfields['cd.date_cloture']['label'], $_SERVER["PHP_SELF"], "cd.date_cloture", "", $param, '', $sortfield, $sortorder, 'center '); -} -// 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 -print $hookmanager->resPrint; -if (!empty($arrayfields['cd.datec']['checked'])) { - print_liste_field_titre($arrayfields['cd.datec']['label'], $_SERVER["PHP_SELF"], "cd.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap '); -} -if (!empty($arrayfields['cd.tms']['checked'])) { - print_liste_field_titre($arrayfields['cd.tms']['label'], $_SERVER["PHP_SELF"], "cd.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap '); -} -if (!empty($arrayfields['status']['checked'])) { - print_liste_field_titre($arrayfields['status']['label'], $_SERVER["PHP_SELF"], "cd.statut,c.statut", "", $param, '', $sortfield, $sortorder, 'right '); -} -print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); -print "\n"; print ''; if (!empty($arrayfields['c.ref']['checked'])) { @@ -614,7 +560,6 @@ if (!empty($arrayfields['s.nom']['checked'])) { print ''; } - if (!empty($arrayfields['cd.date_ouverture_prevue']['checked'])) { print ''; print "\n"; +print ''; +if (!empty($arrayfields['c.ref']['checked'])) { + print_liste_field_titre($arrayfields['c.ref']['label'], $_SERVER["PHP_SELF"], "c.ref", "", $param, "", $sortfield, $sortorder); +} +if (!empty($arrayfields['p.description']['checked'])) { + print_liste_field_titre($arrayfields['p.description']['label'], $_SERVER["PHP_SELF"], "p.description", "", $param, "", $sortfield, $sortorder); +} +if (!empty($arrayfields['cd.tva_tx']['checked'])) { + print_liste_field_titre($arrayfields['cd.tva_tx']['label'], $_SERVER["PHP_SELF"], "cd.tva_tx", "", $param, '', $sortfield, $sortorder, 'center nowrap '); +} +if (!empty($arrayfields['cd.subprice']['checked'])) { + print_liste_field_titre($arrayfields['cd.subprice']['label'], $_SERVER["PHP_SELF"], "cd.subprice", "", $param, '', $sortfield, $sortorder, 'center nowrap '); +} +if (!empty($arrayfields['cd.qty']['checked'])) { + print_liste_field_titre($arrayfields['cd.qty']['label'], $_SERVER["PHP_SELF"], "cd.qty", "", $param, '', $sortfield, $sortorder, 'center nowrap '); +} +if (!empty($arrayfields['cd.total_ht']['checked'])) { + print_liste_field_titre($arrayfields['cd.total_ht']['label'], $_SERVER["PHP_SELF"], "cd.total_ht", "", $param, '', $sortfield, $sortorder, 'center nowrap '); +} +if (!empty($arrayfields['cd.total_tva']['checked'])) { + print_liste_field_titre($arrayfields['cd.total_tva']['label'], $_SERVER["PHP_SELF"], "cd.total_tva", "", $param, '', $sortfield, $sortorder, 'center nowrap '); +} +if (!empty($arrayfields['s.nom']['checked'])) { + print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder); +} +if (!empty($arrayfields['cd.date_ouverture_prevue']['checked'])) { + print_liste_field_titre($arrayfields['cd.date_ouverture_prevue']['label'], $_SERVER["PHP_SELF"], "cd.date_ouverture_prevue", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['cd.date_ouverture']['checked'])) { + print_liste_field_titre($arrayfields['cd.date_ouverture']['label'], $_SERVER["PHP_SELF"], "cd.date_ouverture", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['cd.date_fin_validite']['checked'])) { + print_liste_field_titre($arrayfields['cd.date_fin_validite']['label'], $_SERVER["PHP_SELF"], "cd.date_fin_validite", "", $param, '', $sortfield, $sortorder, 'center '); +} +if (!empty($arrayfields['cd.date_cloture']['checked'])) { + print_liste_field_titre($arrayfields['cd.date_cloture']['label'], $_SERVER["PHP_SELF"], "cd.date_cloture", "", $param, '', $sortfield, $sortorder, 'center '); +} +// 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 +print $hookmanager->resPrint; +if (!empty($arrayfields['cd.datec']['checked'])) { + print_liste_field_titre($arrayfields['cd.datec']['label'], $_SERVER["PHP_SELF"], "cd.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap '); +} +if (!empty($arrayfields['cd.tms']['checked'])) { + print_liste_field_titre($arrayfields['cd.tms']['label'], $_SERVER["PHP_SELF"], "cd.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap '); +} +if (!empty($arrayfields['status']['checked'])) { + print_liste_field_titre($arrayfields['status']['label'], $_SERVER["PHP_SELF"], "cd.statut,c.statut", "", $param, '', $sortfield, $sortorder, 'right '); +} +print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); +print "\n"; + + $contractstatic = new Contrat($db); $productstatic = new Product($db); From ac6705a7f6832c1b547fe83d19b645a50c1f5e07 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 14:54:11 +0100 Subject: [PATCH 682/816] NEW Filter on amount and qty on list of service's contracts --- htdocs/contrat/services_list.php | 60 +++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 84ee5b3f88c..e1ab25a2030 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -58,6 +58,11 @@ if (!$sortorder) { $mode = GETPOST("mode"); $filter = GETPOST("filter"); $search_name = GETPOST("search_name", 'alpha'); +$search_subprice = GETPOST("search_subprice", 'alpha'); +$search_qty = GETPOST("search_name", 'alpha'); +$search_total_ht = GETPOST("search_total_ht", 'alpha'); +$search_total_tva = GETPOST("search_total_tva", 'alpha'); +$search_total_ttc = GETPOST("search_total_ttc", 'alpha'); $search_contract = GETPOST("search_contract", 'alpha'); $search_service = GETPOST("search_service", 'alpha'); $search_status = GETPOST("search_status", 'alpha'); @@ -180,6 +185,11 @@ if (empty($reshook)) { if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers $search_product_category = 0; $search_name = ""; + $search_subprice = ""; + $search_qty = ""; + $search_total_ht = ""; + $search_total_tva = ""; + $search_total_ttc = ""; $search_contract = ""; $search_service = ""; $search_status = -1; @@ -280,8 +290,23 @@ if ($filter == "expired") { if ($filter == "notexpired") { $sql .= " AND cd.date_fin_validite >= '".$db->idate($now)."'"; } +if ($search_subprice) { + $sql .= natural_search("cd.subprice", $search_subprice, 1); +} +if ($search_qty) { + $sql .= natural_search("cd.total_qty", $search_qty, 1); +} +if ($search_total_ht) { + $sql .= natural_search("cd.total_ht", $search_total_ht, 1); +} +if ($search_total_tva) { + $sql .= natural_search("cd.total_tva", $search_total_tva, 1); +} +if ($search_total_ttc) { + $sql .= natural_search("cd.total_ttc", $search_total_ttc, 1); +} if ($search_name) { - $sql .= natural_search("c.ref", $search_name); + $sql .= natural_search("s.nom", $search_name); } if ($search_contract) { $sql .= natural_search("c.ref", $search_contract); @@ -398,6 +423,21 @@ if ($search_contract) { if ($search_name) { $param .= '&search_name='.urlencode($search_name); } +if ($search_subprice) { + $param .= '&search_subprice='.urlencode($search_subprice); +} +if ($search_qty) { + $param .= '&search_qty='.urlencode($search_qty); +} +if ($search_total_ht) { + $param .= '&search_total_ht='.urlencode($search_total_ht); +} +if ($search_total_tva) { + $param .= '&search_total_tva='.urlencode($search_total_tva); +} +if ($search_total_ttc) { + $param .= '&search_total_ttc='.urlencode($search_total_ttc); +} if ($search_service) { $param .= '&search_service='.urlencode($search_service); } @@ -538,19 +578,23 @@ if (!empty($arrayfields['cd.tva_tx']['checked'])) { print ''; } if (!empty($arrayfields['cd.subprice']['checked'])) { - print ''; } if (!empty($arrayfields['cd.qty']['checked'])) { - print ''; } if (!empty($arrayfields['cd.total_ht']['checked'])) { - print ''; } if (!empty($arrayfields['cd.total_tva']['checked'])) { - print ''; } // Third party @@ -647,13 +691,13 @@ if (!empty($arrayfields['cd.subprice']['checked'])) { print_liste_field_titre($arrayfields['cd.subprice']['label'], $_SERVER["PHP_SELF"], "cd.subprice", "", $param, '', $sortfield, $sortorder, 'center nowrap '); } if (!empty($arrayfields['cd.qty']['checked'])) { - print_liste_field_titre($arrayfields['cd.qty']['label'], $_SERVER["PHP_SELF"], "cd.qty", "", $param, '', $sortfield, $sortorder, 'center nowrap '); + print_liste_field_titre($arrayfields['cd.qty']['label'], $_SERVER["PHP_SELF"], "cd.qty", "", $param, '', $sortfield, $sortorder, 'right nowrap '); } if (!empty($arrayfields['cd.total_ht']['checked'])) { - print_liste_field_titre($arrayfields['cd.total_ht']['label'], $_SERVER["PHP_SELF"], "cd.total_ht", "", $param, '', $sortfield, $sortorder, 'center nowrap '); + print_liste_field_titre($arrayfields['cd.total_ht']['label'], $_SERVER["PHP_SELF"], "cd.total_ht", "", $param, '', $sortfield, $sortorder, 'right nowrap '); } if (!empty($arrayfields['cd.total_tva']['checked'])) { - print_liste_field_titre($arrayfields['cd.total_tva']['label'], $_SERVER["PHP_SELF"], "cd.total_tva", "", $param, '', $sortfield, $sortorder, 'center nowrap '); + print_liste_field_titre($arrayfields['cd.total_tva']['label'], $_SERVER["PHP_SELF"], "cd.total_tva", "", $param, '', $sortfield, $sortorder, 'right nowrap '); } if (!empty($arrayfields['s.nom']['checked'])) { print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder); From 97dfaf267e99160bd787d3ab7663ab60fd6aa0b9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 14:59:02 +0100 Subject: [PATCH 683/816] Fix missing total on qties --- htdocs/contrat/services_list.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index e1ab25a2030..fb50283991b 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -737,7 +737,7 @@ $contractstatic = new Contrat($db); $productstatic = new Product($db); $i = 0; -$totalarray = array('nbfield'=>0); +$totalarray = array('nbfield'=>0, 'cd.qty'=>0, 'cd.total_ht'=>0, 'cd.total_tva'=>0); while ($i < min($num, $limit)) { $obj = $db->fetch_object($resql); @@ -819,6 +819,10 @@ while ($i < min($num, $limit)) { if (!$i) { $totalarray['nbfield']++; } + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 'cd.qty'; + } + $totalarray['val']['cd.qty'] += $obj->qty; } if (!empty($arrayfields['cd.total_ht']['checked'])) { print ''; } // Date invoice @@ -728,7 +738,7 @@ if ($resql) { } } if (!empty($arrayfields['s.nom']['checked'])) { - print ''; + print ''; if (!$i) { $totalarray['nbfield']++; } From 84436e1217327fac1e27c395613d41c8abf75ce7 Mon Sep 17 00:00:00 2001 From: hystepik Date: Thu, 19 Jan 2023 15:31:47 +0100 Subject: [PATCH 685/816] Fix : php 8.1 warnings and dolibarr log --- htdocs/barcode/printsheet.php | 2 +- htdocs/comm/action/index.php | 2 +- htdocs/comm/mailing/cibles.php | 2 +- htdocs/comm/mailing/index.php | 4 ++-- htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php | 4 ++-- htdocs/hrm/class/position.class.php | 4 ++-- htdocs/modulebuilder/index.php | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/barcode/printsheet.php b/htdocs/barcode/printsheet.php index 373effecbe8..56361b948f0 100644 --- a/htdocs/barcode/printsheet.php +++ b/htdocs/barcode/printsheet.php @@ -226,7 +226,7 @@ if ($action == 'builddoc') { 'code'=>$code, 'encoding'=>$encoding, 'is2d'=>$is2d, - 'photo'=>$barcodeimage // Photo must be a file that exists with format supported by TCPDF + 'photo'=>!empty($barcodeimage) ? $barcodeimage : '' // Photo must be a file that exists with format supported by TCPDF ); } } else { diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index e730243bfbf..9d84e205f2b 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -2048,7 +2048,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa } } if (!empty($contact_id) && $contact_id > 0) { - if (!is_object($cachecontacts[$contact_id])) { + if (empty($cachecontacts[$contact_id]) || !is_object($cachecontacts[$contact_id])) { $contact = new Contact($db); $contact->fetch($contact_id); $cachecontacts[$contact_id] = $contact; diff --git a/htdocs/comm/mailing/cibles.php b/htdocs/comm/mailing/cibles.php index dde6e3204d6..c39e4fbf834 100644 --- a/htdocs/comm/mailing/cibles.php +++ b/htdocs/comm/mailing/cibles.php @@ -675,7 +675,7 @@ if ($object->fetch($id) >= 0) { // Date last update print ''; // Status of recipient sending email (Warning != status of emailing) diff --git a/htdocs/comm/mailing/index.php b/htdocs/comm/mailing/index.php index d3ebc379b55..cf3d18adbac 100644 --- a/htdocs/comm/mailing/index.php +++ b/htdocs/comm/mailing/index.php @@ -101,7 +101,7 @@ if (is_resource($handle)) { $qualified = 1; foreach ($mailmodule->require_module as $key) { - if (!$conf->$key->enabled || (!$user->admin && $mailmodule->require_admin)) { + if (empty($conf->$key->enabled) || (!$user->admin && $mailmodule->require_admin)) { $qualified = 0; //print "Les pr�requis d'activation du module mailing ne sont pas respect�s. Il ne sera pas actif"; break; @@ -176,7 +176,7 @@ if ($result) { print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; diff --git a/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php b/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php index b75d0752334..5a6dbbedd37 100644 --- a/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php +++ b/htdocs/core/boxes/box_graph_nb_ticket_last_x_days.php @@ -120,7 +120,7 @@ class box_graph_nb_ticket_last_x_days extends ModeleBoxes while ($i < $num) { $objp = $this->db->fetch_object($resql); while ($minimumdatecformated < $objp->datec) { - $dataseries[] = array('label' => dol_print_date($minimumdatecformated, 'day'), 'data' => 0); + $dataseries[] = array('label' => dol_print_date($minimumdatec, 'day'), 'data' => 0); $minimumdatec = dol_time_plus_duree($minimumdatec, $intervaltoadd, 'd'); $minimumdatecformated = dol_print_date($minimumdatec, 'dayrfc'); } @@ -130,7 +130,7 @@ class box_graph_nb_ticket_last_x_days extends ModeleBoxes $i++; } while (count($dataseries) < $days) { - $dataseries[] = array('label' => dol_print_date($minimumdatecformated, 'day'), 'data' => 0); + $dataseries[] = array('label' => dol_print_date($minimumdatec, 'day'), 'data' => 0); $minimumdatec = dol_time_plus_duree($minimumdatec, $intervaltoadd, 'd'); $minimumdatecformated = dol_print_date($minimumdatec, 'dayrfc'); $i++; diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index b685147a9b9..caf2ff00b03 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -395,10 +395,10 @@ class Position extends CommonObject foreach ($filter as $key => $value) { if ($key == 't.rowid') { $sqlwhere[] = $key . '=' . $value; - } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key . ' = \'' . $this->db->idate($value) . '\''; } elseif ($key == 'customsql') { $sqlwhere[] = $value; + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key . ' = \'' . $this->db->idate($value) . '\''; } elseif (strpos($value, '%') === false) { $sqlwhere[] = $key . ' IN (' . $this->db->sanitize($this->db->escape($value)) . ')'; } else { diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index b8810a2696d..0d2137928ac 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -3739,7 +3739,7 @@ if ($module == 'initmodule') { print ''; print ''; print ''; print ''; print ''; print ''; @@ -256,20 +256,20 @@ if ($nb) { if ($type == 'bank-transfer') { $title = $langs->trans('BankToPayCreditTransfer').': '; } - print $title; + print ''.$title.''; print img_picto('', 'bank_account'); $default_account = ($type == 'bank-transfer' ? 'PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT' : 'PRELEVEMENT_ID_BANKACCOUNT'); - print $form->select_comptes($conf->global->$default_account, 'id_bankaccount', 0, "courant=1", 0, '', 0, '', 1); - print ' - '; + print $form->select_comptes(getDolGlobalInt($default_account), 'id_bankaccount', 0, "courant=1", 0, '', 0, 'widthcentpercentminusx maxwidth300', 1); + print '     '; if (empty($executiondate)) { $delayindays = 0; if ($type != 'bank-transfer') { - $delayindays = $conf->global->PRELEVEMENT_ADDDAYS; + $delayindays = getDolGlobalInt('PRELEVEMENT_ADDDAYS'); } else { - $delayindays = $conf->global->PAYMENTBYBANKTRANSFER_ADDDAYS; + $delayindays = getDolGlobalInt('PAYMENTBYBANKTRANSFER_ADDDAYS'); } $executiondate = dol_time_plus_duree(dol_now(), $delayindays, 'd'); @@ -292,14 +292,14 @@ if ($nb) { print ''; print ''; } - print ''; + print ''; } else { $title = $langs->trans("CreateAll"); if ($type == 'bank-transfer') { $title = $langs->trans("CreateFileForPaymentByBankTransfer"); } print ''."\n"; - print ''."\n"; + print ''."\n"; } } else { if ($mysoc->isInEEC()) { @@ -307,18 +307,18 @@ if ($nb) { if ($type == 'bank-transfer') { $title = $langs->trans("CreateSepaFileForPaymentByBankTransfer"); } - print ''.$title."\n"; + print ''.$title."\n"; if ($type != 'bank-transfer') { $title = $langs->trans("CreateForSepaRCUR"); - print ''.$title."\n"; + print ''.$title."\n"; } } else { $title = $langs->trans("CreateAll"); if ($type == 'bank-transfer') { $title = $langs->trans("CreateFileForPaymentByBankTransfer"); } - print ''.$title."\n"; + print ''.$title."\n"; } } } else { @@ -328,7 +328,9 @@ if ($nb) { $titlefortab = $langs->transnoentitiesnoconv("PaymentByBankTransfers"); $title = $langs->trans("CreateFileForPaymentByBankTransfer"); } - print ''.$title."\n"; + print ''; + print $title; + print "\n"; } print "\n"; @@ -343,6 +345,9 @@ print '
    '; */ $sql = "SELECT f.ref, f.rowid, f.total_ttc, s.nom as name, s.rowid as socid,"; +if ($type == 'bank-transfer') { + $sql .= " f.ref_supplier,"; +} $sql .= " pfd.rowid as request_row_id, pfd.date_demande, pfd.amount"; if ($type == 'bank-transfer') { $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f,"; @@ -423,6 +428,9 @@ if ($resql) { print '
    '; $arrayofoperators = array('<'=>'<', '>'=>'>'); @@ -688,6 +633,62 @@ print $searchpicto; print '
    '; + print ''; + print ''; print ''; + print ''; + print ''; print ''; + print ''; + print ''; print ''; + print ''; + print ''; print ''; From a092654ea8cf6b0a340a30667ae2edf6a869f231 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 15:17:40 +0100 Subject: [PATCH 684/816] NEW Add filter on nb of generation done in list of recurring invoices --- htdocs/compta/facture/invoicetemplate_list.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture/invoicetemplate_list.php b/htdocs/compta/facture/invoicetemplate_list.php index ae9e4c2959b..0471b97c038 100644 --- a/htdocs/compta/facture/invoicetemplate_list.php +++ b/htdocs/compta/facture/invoicetemplate_list.php @@ -94,6 +94,7 @@ $search_date_when_end = dol_mktime(23, 59, 59, $search_date_when_endmonth, $sear $search_recurring = GETPOST('search_recurring', 'int'); $search_frequency = GETPOST('search_frequency', 'alpha'); $search_unit_frequency = GETPOST('search_unit_frequency', 'alpha'); +$search_nb_gen_done = GETPOST('search_nb_gen_done', 'aplha'); $search_status = GETPOST('search_status', 'int'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; @@ -236,6 +237,7 @@ if (empty($reshook)) { $search_recurring = ''; $search_frequency = ''; $search_unit_frequency = ''; + $search_nb_gen_done = ''; $search_status = ''; $search_array_options = array(); } @@ -334,7 +336,11 @@ if ($search_frequency != '') { $sql .= natural_search('f.frequency', $search_frequency, 1); } if ($search_unit_frequency != '') { - $sql .= ' AND f.frequency > 0'.natural_search('f.unit_frequency', $search_unit_frequency); + $sql .= ' AND f.frequency > 0'; + $sql .= natural_search('f.unit_frequency', $search_unit_frequency); +} +if ($search_nb_gen_done != '') { + $sql .= natural_search("f.nb_gen_done", $search_nb_gen_done, 1); } if ($search_status != '' && $search_status >= -1) { if ($search_status == 0) { @@ -458,6 +464,9 @@ if ($resql) { if ($search_unit_frequency != '') { $param .= '&search_unit_frequency='.urlencode($search_unit_frequency); } + if ($search_nb_gen_done != '') { + $param .= '&search_nb_gen_done='.urlencode($search_nb_gen_done); + } if ($search_status != '') { $param .= '&search_status='.urlencode($search_status); } @@ -561,6 +570,7 @@ if ($resql) { if (!empty($arrayfields['f.nb_gen_done']['checked'])) { // Nb generation print ''; + print ''; print ''.$companystatic->getNomUrl(1, 'customer').''.$companystatic->getNomUrl(1, 'customer').''; - print dol_print_date($obj->tms, 'dayhour'); + print dol_print_date(dol_stringtotime($obj->tms), 'dayhour'); print '
    '.$mailstatic->getNomUrl(1).''.dol_trunc($obj->title, 38).''.(!empty($obj->title) ? dol_trunc($obj->title, 38) : '').''.dol_print_date($db->jdate($obj->date_creat), 'day').''.($obj->nbemail ? $obj->nbemail : "0").''.$mailstatic->LibStatut($obj->statut, 5).''; - print dol_escape_htmltag($menu['leftmenu']); + print !empty($menu['leftmenu']) ? dol_escape_htmltag($menu['leftmenu']) : ''; print ''; From b4b6cba9fb92b0bd55eec00848e20ec5a7d5a7e6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 15:56:30 +0100 Subject: [PATCH 686/816] NEW Show supplier invoice ref of direct debit transfer tab invoices --- htdocs/compta/prelevement/factures.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/prelevement/factures.php b/htdocs/compta/prelevement/factures.php index 0ed75b5c3b8..378480ef0d2 100644 --- a/htdocs/compta/prelevement/factures.php +++ b/htdocs/compta/prelevement/factures.php @@ -21,7 +21,7 @@ /** * \file htdocs/compta/prelevement/factures.php * \ingroup prelevement - * \brief Page liste des factures prelevees + * \brief Page list of invoice paied by direct debit or credit transfer */ // Load Dolibarr environment @@ -174,6 +174,9 @@ if ($id > 0 || $ref) { // List of invoices $sql = "SELECT pf.rowid, p.type,"; $sql .= " f.rowid as facid, f.ref as ref, f.total_ttc,"; +if ($object->type == 'bank-transfer') { + $sql .= " f.ref_supplier,"; +} $sql .= " s.rowid as socid, s.nom as name, pl.statut, pl.amount as amount_requested"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; $sql .= ", ".MAIN_DB_PREFIX."prelevement_lignes as pl"; @@ -251,6 +254,9 @@ if ($resql) { print ''; print ''; print_liste_field_titre("Bill", $_SERVER["PHP_SELF"], "p.ref", '', $param, '', $sortfield, $sortorder); + if ($object->type == 'bank-transfer') { + print_liste_field_titre("RefSupplierShort", $_SERVER["PHP_SELF"], "f.ref_supplier", '', $param, '', $sortfield, $sortorder); + } print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "s.nom", '', $param, '', $sortfield, $sortorder); print_liste_field_titre("AmountInvoice", $_SERVER["PHP_SELF"], "f.total_ttc", "", $param, 'class="right"', $sortfield, $sortorder); print_liste_field_titre("AmountRequested", $_SERVER["PHP_SELF"], "pl.amount", "", $param, 'class="right"', $sortfield, $sortorder); @@ -282,6 +288,12 @@ if ($resql) { print $invoicetmp->getNomUrl(1); print "\n"; + if ($object->type == 'bank-transfer') { + print '\n"; + } + print '\n"; From e6ca13ca65b5339102809ce50af657765828936c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 19 Jan 2023 15:57:44 +0100 Subject: [PATCH 687/816] Missing column --- htdocs/compta/prelevement/factures.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/compta/prelevement/factures.php b/htdocs/compta/prelevement/factures.php index 378480ef0d2..cc416d7d530 100644 --- a/htdocs/compta/prelevement/factures.php +++ b/htdocs/compta/prelevement/factures.php @@ -334,6 +334,9 @@ if ($resql) { if ($num > 0) { print ''; print ''; + if ($object->type == 'bank-transfer') { + print ''; + } print ''; print ''; - foreach ($socialnetworks as $key => $value) { - if ($value['active']) { - print ''; - print ''; - print ''; - print ''; - } elseif (!empty($object->socialnetworks[$key])) { - print ''; - } - } - - print ''; -} - llxFooter(); diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index e55f123a540..c9d62c410b3 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -32,6 +32,7 @@ * \brief File of contacts class */ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/commonsocialnetworks.class.php'; /** @@ -39,6 +40,8 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; */ class Contact extends CommonObject { + use CommonSocialNetworks; + /** * @var string ID to identify managed object */ diff --git a/htdocs/core/class/commonsocialnetworks.class.php b/htdocs/core/class/commonsocialnetworks.class.php new file mode 100644 index 00000000000..eeb6583ca65 --- /dev/null +++ b/htdocs/core/class/commonsocialnetworks.class.php @@ -0,0 +1,102 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/class/commonincoterm.class.php + * \ingroup core + * \brief File of the superclass of object classes that support incoterm (customer and supplier) + */ + + +/** + * Superclass for social networks + */ +trait CommonSocialNetworks +{ + /** + * Show social network part if the module is enabled with hiding functionality + * + * @param array $socialnetworks Array of social networks + * @param int $colspan Colspan + * @return void + */ + public function showSocialNetwork($socialnetworks, $colspan = 4) + { + global $object, $form, $langs; + + $nbofnetworks = count($socialnetworks); + $nbactive = 0; + foreach ($socialnetworks as $key => $value) { + if (!empty($object->socialnetworks[$key])) { + $nbactive++; + } + } + + if ($nbofnetworks > 1) { + print ''; + print ''; + print '
    '.$nbactive.''; + print ''; + print '
    '; + } + foreach ($socialnetworks as $key => $value) { + if ($value['active'] || $nbofnetworks == 1) { + print ''; + print ''; + print ''; + print ''; + } elseif (!empty($object->socialnetworks[$key])) { + print ''; + } + } + print '
    '; + + if ($nbofnetworks > 1) { + print ''; + } + } +} diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 38b6892dbae..911ba31bc25 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -500,4 +500,6 @@ CurrentOutstandingBillLate=Current outstanding bill late BecarefullChangeThirdpartyBeforeAddProductToInvoice=Be carefull, depending on your product price settings, you should change thirdparty before adding product to POS. EmailAlreadyExistsPleaseRewriteYourCompanyName=email already exists please rewrite your company name TwoRecordsOfCompanyName=more than one record exists for this company, please contact us to complete your partnership request -CompanySection=Company section \ No newline at end of file +CompanySection=Company section +ShowSocialNetworks=Show social networks +HideSocialNetworks=Hide social networks diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 6ef8d929361..02d0b042aab 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1663,7 +1663,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Social networks if (isModEnabled('socialnetworks')) { - showSocialNetwork(); + $object->showSocialNetwork($socialnetworks, ($conf->browser->layout == 'phone' ? 2 : 4)); } // Prof ids @@ -2381,7 +2381,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Social network if (isModEnabled('socialnetworks')) { - showSocialNetwork(); + $object->showSocialNetwork($socialnetworks, ($conf->browser->layout == 'phone' ? 2 : 4)); } // Prof ids @@ -3299,54 +3299,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } } -/** - * Show social network part if the module is enabled with hiding functionality - * - * @return void - */ -function showSocialNetwork() -{ - global $socialnetworks, $object, $form, $object, $langs; - echo ''; - - print ''; - foreach ($socialnetworks as $key => $value) { - if ($value['active']) { - print ''; - print ''; - print ''; - print ''; - } elseif (!empty($object->socialnetworks[$key])) { - print ''; - } - } - - print ''; -} // End of page llxFooter(); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 29f400fc778..2e633126f64 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -40,6 +40,7 @@ */ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/commonsocialnetworks.class.php'; require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php'; @@ -49,6 +50,7 @@ require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php'; class Societe extends CommonObject { use CommonIncoterm; + use CommonSocialNetworks; /** * @var string ID to identify managed object From 7df07b57ce9d9925abe2f092c2db2263444f9bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Fri, 20 Jan 2023 13:58:04 +0100 Subject: [PATCH 702/816] fix missing global in template modulebuilder --- htdocs/modulebuilder/template/class/myobject.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index c60dbaa7e5b..4cc03121988 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -874,6 +874,7 @@ class MyObject extends CommonObject */ public function getKanbanView($option = '', $arraydata = null) { + global $conf, $langs; $return = '
    '; $return .= '
    '; $return .= ''; From 0721c8b5d8e558dd7519a56e47cf6fbc3571df69 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 20 Jan 2023 15:14:44 +0100 Subject: [PATCH 703/816] Clean code --- htdocs/core/class/commoninvoice.class.php | 27 +++++++++++++++----- htdocs/stripe/class/stripe.class.php | 31 ++++++++++++++++++----- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 93d125291ef..17c9c7deae3 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -865,7 +865,7 @@ abstract class CommonInvoice extends CommonObject /** - * Create a withdrawal request at Stripe for a direct debit order or a credit transfer order. + * Create a withdrawal request, from a prelevement_demande, to Stripe for a direct debit order or a credit transfer order. * Use the remain to pay excluding all existing open direct debit requests. * * @param User $fuser User asking the direct debit transfer @@ -901,6 +901,7 @@ abstract class CommonInvoice extends CommonObject $sql = "SELECT rowid, date_demande, amount, fk_facture, fk_facture_fourn"; $sql .= " FROM ".$this->db->prefix()."prelevement_demande"; $sql .= " AND fk_facture = ".((int) $this->fk_facture); // Add a protection to not pay another invoice than current one + $sql .= " AND traite = 0"; // Add a protection to not process twice $sql .= " WHERE rowid = ".((int) $did); dol_syslog(get_class($this)."::makeStripeSepaRequest 1", LOG_DEBUG); @@ -1077,10 +1078,11 @@ abstract class CommonInvoice extends CommonObject $stripecard = null; if ($companypaymentmode->type == 'ban') { $sepaMode = true; + // Check into societe_rib if a payment mode for Stripe and ban payment exists $stripecard = $stripe->sepaStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0); } - if ($stripecard) { // Can be src_... (for sepa) - Other card_... (old mode) or pm_... (new mode) should not happen here. + if ($stripecard) { // Can be src_... (for sepa). Note that card_... (old card mode) or pm_... (new card mode) should not happen here. $FULLTAG = 'INV=' . $this->id . '-CUS=' . $thirdparty->id; $description = 'Stripe payment from makeStripeSepaRequest: ' . $FULLTAG . ' ref=' . $this->ref; @@ -1128,6 +1130,7 @@ abstract class CommonInvoice extends CommonObject //var_dump("stripefailurecode=".$stripefailurecode." stripefailuremessage=".$stripefailuremessage." stripefailuredeclinecode=".$stripefailuredeclinecode); //exit; + // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) if (empty($charge) || $charge->status == 'failed') { dol_syslog('Failed to charge payment mode ' . $stripecard->id . ' stripefailurecode=' . $stripefailurecode . ' stripefailuremessage=' . $stripefailuremessage . ' stripefailuredeclinecode=' . $stripefailuredeclinecode, LOG_WARNING); @@ -1179,7 +1182,11 @@ abstract class CommonInvoice extends CommonObject $this->stripechargedone++; // Default description used for label of event. Will be overwrite by another value later. - $description = 'Stripe payment OK (' . $charge->id . ') from makeStripeSepaRequest: ' . $FULLTAG; + $description = 'Stripe payment request OK (' . $charge->id . ') from makeStripeSepaRequest: ' . $FULLTAG; + + + // TODO Save request to status pending. Done should be set with a webhook. + $db = $this->db; @@ -1549,13 +1556,19 @@ abstract class CommonInvoice extends CommonObject $this->errors[] = "Remain to pay is null for the invoice " . $this->id . " " . $this->ref . ". Why is the invoice not classified 'Paid' ?"; } - // TODO Create a prelevement_bon ? - // For the moment no + // TODO Create a prelevement_bon and set its status to sent instead of this + $idtransferfile = 0; - // We must update the direct debit payment request as "done" - $sql = "UPDATE".MAIN_DB_PREFIX."prelevement_demande SET traite = 1, date_traite = '".$this->db->idate(dol_now())."'"; + // Update the direct debit payment request of the processed invoice to save the id of the prelevement_bon + $sql = "UPDATE".MAIN_DB_PREFIX."prelevement_demande SET"; + $sql .= " traite = 1,"; // TODO Remove this + $sql .= " date_traite = '".$this->db->idate(dol_now())."'"; // TODO Remove this + if ($idtransferfile > 0) { + $sql .= " fk_prelevement_bons = ".((int) $idtransferfile); + } $sql .= "WHERE rowid = ".((int) $did); + dol_syslog(get_class($this)."::makeStripeSepaRequest", LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 972d2e25c23..942d5d8d275 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -602,7 +602,7 @@ class Stripe extends CommonObject * but not when using the STRIPE_USE_NEW_CHECKOUT. * * @param string $description Description - * @param Societe $object Object to pay with Stripe + * @param Societe $object Object of company to link the Stripe payment mode with * @param string $customer Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe() * @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect * @param int $status Status (0=test, 1=live) @@ -813,8 +813,21 @@ class Stripe extends CommonObject $ipaddress = getUserRemoteIP(); $dataforcard = array( - "source" => array('object'=>'card', 'exp_month'=>$exp_date_month, 'exp_year'=>$exp_date_year, 'number'=>$number, 'cvc'=>$cvc, 'name'=>$cardholdername), - "metadata" => array('dol_id'=>$object->id, 'dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress) + "source" => array( + 'object'=>'card', + 'exp_month'=>$exp_date_month, + 'exp_year'=>$exp_date_year, + 'number'=>$number, + 'cvc'=>$cvc, + 'name'=>$cardholdername + ), + "metadata" => array( + 'dol_type'=>$object->element, + 'dol_id'=>$object->id, + 'dol_version'=>DOL_VERSION, + 'dol_entity'=>$conf->entity, + 'ipaddress'=>$ipaddress + ) ); //$a = \Stripe\Stripe::getApiKey(); @@ -898,8 +911,8 @@ class Stripe extends CommonObject * @param CompanyPaymentMode $object Object companypaymentmode to check, or create on stripe (create on stripe also update the societe_rib table for current entity) * @param string $stripeacc ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect * @param int $status Status (0=test, 1=live) - * @param int $createifnotlinkedtostripe 1=Create the stripe sepa and the link if the sepa is not yet linked to a stripe sepa. Deprecated with new Stripe API and SCA. - * @return \Stripe\PaymentMethod|null Stripe SEPA or null if not found + * @param int $createifnotlinkedtostripe 1=Create the stripe sepa and the link if the sepa is not yet linked to a stripe sepa. Used by the "Create bank to Stripe" feature. + * @return \Stripe\PaymentMethod|null Stripe SEPA or null if not found */ public function sepaStripe($cu, CompanyPaymentMode $object, $stripeacc = '', $status = 0, $createifnotlinkedtostripe = 0) { @@ -996,8 +1009,10 @@ class Stripe extends CommonObject $stripeacc = $stripearrayofkeysbyenv[$servicestatus]['secret_key']; dol_syslog("Try to create sepa_debit with data = ".json_encode($dataforcard)); - // TODO Replace with PaymentIntent. Can use $stripe->getPaymentIntent ? + $s = new \Stripe\StripeClient($stripeacc); + + // TODO Deprecated with the new Stripe API and SCA. Replace ->create() and ->createSource() Replace with getSetupIntent() ? $sepa = $s->sources->create($dataforcard); if (!$sepa) { $this->error = 'Creation of sepa_debit on Stripe has failed'; @@ -1007,9 +1022,10 @@ class Stripe extends CommonObject if (!$cs) { $this->error = 'Link SEPA <-> Customer failed'; } else { - dol_syslog("Update the payment request"); + dol_syslog("Update the payment mode of the customer"); // print json_encode($sepa); + // Save the Stripe payment mode ID into the Dolibarr database $sql = "UPDATE ".MAIN_DB_PREFIX."societe_rib"; $sql .= " SET stripe_card_ref = '".$this->db->escape($sepa->id)."', card_type = 'sepa_debit',"; $sql .= " stripe_account= '" . $this->db->escape($cu->id . "@" . $stripeacc) . "'"; @@ -1034,6 +1050,7 @@ class Stripe extends CommonObject return $sepa; } + /** * Create charge. * This is called by page htdocs/stripe/payment.php and may be deprecated. From e2dd443c584aa1dc21c7ff2b3396008fec6cd6e2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 20 Jan 2023 16:04:23 +0100 Subject: [PATCH 704/816] Doc --- htdocs/stripe/class/stripe.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 942d5d8d275..6a6ad66a96a 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -804,6 +804,7 @@ class Stripe extends CommonObject dol_syslog($this->error, LOG_WARNING); } } elseif ($createifnotlinkedtostripe) { + // Deprecated with new Stripe API and SCA. We should not use anymore this part of code now. $exp_date_month = $obj->exp_date_month; $exp_date_year = $obj->exp_date_year; $number = $obj->number; @@ -1012,7 +1013,8 @@ class Stripe extends CommonObject $s = new \Stripe\StripeClient($stripeacc); - // TODO Deprecated with the new Stripe API and SCA. Replace ->create() and ->createSource() Replace with getSetupIntent() ? + // TODO Deprecated with the new Stripe API and SCA. + // TODO Replace ->create() and ->createSource() and replace with ->getSetupIntent() to get a Payment mode with $payment_method = \Stripe\PaymentMethod::retrieve($setupintent->payment_method); ? $sepa = $s->sources->create($dataforcard); if (!$sepa) { $this->error = 'Creation of sepa_debit on Stripe has failed'; From 343922210c66ccbb87ac1e5e0eee1f7dc94ff365 Mon Sep 17 00:00:00 2001 From: Randall Mora <50120822+randallmoraes@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:12:58 -0600 Subject: [PATCH 705/816] repair security issue When reassing value to the $socid in line 68 clean the filter set by $user->socid --- htdocs/comm/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php index 67af97cfe12..b748cac3df4 100644 --- a/htdocs/comm/index.php +++ b/htdocs/comm/index.php @@ -65,7 +65,7 @@ $max = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT; $now = dol_now(); // Security check -$socid = GETPOST("socid", 'int'); +//$socid = GETPOST("socid", 'int'); if ($user->socid > 0) { $action = ''; $id = $user->socid; From 210410775982614150ee25f26c0d4e1e22c8d353 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 20 Jan 2023 17:38:47 +0100 Subject: [PATCH 706/816] Fix warnings --- htdocs/societe/class/societe.class.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 12a82c44180..01a72c6c7f3 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -784,6 +784,10 @@ class Societe extends CommonObject */ public $multicurrency_code; + /** + * @var string Set if company email found into unsubscribe of emailing list table + */ + public $no_email; // Fields loaded by fetchPartnerships() From 56f0efa2fc3142ee59eba51ceb8dfef0fddf25fc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 20 Jan 2023 19:09:56 +0100 Subject: [PATCH 707/816] Fix greek language --- htdocs/langs/el_GR/main.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/el_GR/main.lang b/htdocs/langs/el_GR/main.lang index 605ee14d77a..68583623c45 100644 --- a/htdocs/langs/el_GR/main.lang +++ b/htdocs/langs/el_GR/main.lang @@ -7,10 +7,10 @@ DIRECTION=ltr # To read Chinese pdf with Linux: sudo apt-get install poppler-data # cid0jp is for Japanish # cid0kr is for Korean -# DejaVuSans is for some Eastern languages, some Asian languages and some Arabic languages +# DejaVuSans is for some Eastern languages, greek, some Asian languages and some Arabic languages # freemono is for ru_RU or uk_UA, uz_UZ # freeserif is for Tamil -FONTFORPDF=helvetica +FONTFORPDF=DejaVuSans FONTSIZEFORPDF=10 SeparatorDecimal=, SeparatorThousand=. From f7302232df71d2d276984d4bf4d455ef77af39a2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 20 Jan 2023 19:34:26 +0100 Subject: [PATCH 708/816] Fix rounding --- htdocs/core/lib/functions.lib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index c20f58a943d..0d4e30f4a2a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5743,9 +5743,9 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $ // If force rounding if ((string) $forcerounding != '-1') { - if ($forcerounding == 'MU') { + if ($forcerounding === 'MU') { $nbdecimal = $conf->global->MAIN_MAX_DECIMALS_UNIT; - } elseif ($forcerounding == 'MT') { + } elseif ($forcerounding === 'MT') { $nbdecimal = $conf->global->MAIN_MAX_DECIMALS_TOT; } elseif ($forcerounding >= 0) { $nbdecimal = $forcerounding; From 439f8d4bb429538ac16ff07c275ae67ef410490d Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sat, 21 Jan 2023 08:45:10 +0100 Subject: [PATCH 709/816] New: REST Api - GET /setup/dictionary/incoterms --- htdocs/api/class/api_setup.class.php | 62 ++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index e06cdeb0312..34fed417e70 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -1682,6 +1682,68 @@ class Setup extends DolibarrApi return $list; } + /** + * Get the list of incoterms. + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Number of items per page + * @param int $page Page number (starting from zero) + * @param int $active Payment term is active or not {@min 0} {@max 1} + * @param string $lang Code of the language the label of the type must be translated to + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" + * @return array List of ticket types + * + * @url GET dictionary/incoterms + * + * @throws RestException + */ + public function getListOfIncoterms($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $lang = '', $sqlfilters = '') + { + $list = array(); + + $sql = "SELECT rowid, code, active"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_incoterms as t"; + $sql .= " WHERE 1=1"; + + // Add sql filters + if ($sqlfilters) { + $errormessage = ''; + if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { + throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + + $sql .= $this->db->order($sortfield, $sortorder); + + if ($limit) { + if ($page < 0) { + $page = 0; + } + $offset = $limit * $page; + + $sql .= $this->db->plimit($limit, $offset); + } + + $result = $this->db->query($sql); + + if ($result) { + $num = $this->db->num_rows($result); + $min = min($num, ($limit <= 0 ? $num : $limit)); + for ($i = 0; $i < $min; $i++) { + $type =$this->db->fetch_object($result); + $list[] = $type; + } + } else { + throw new RestException(503, 'Error when retrieving list of incoterm types : '.$this->db->lasterror()); + } + + return $list; + } + /** * Get properties of company * From 3c26825b5d86e3507f31b23c68aeee3ac20d9f6a Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sat, 21 Jan 2023 08:49:24 +0100 Subject: [PATCH 710/816] change description --- htdocs/api/class/api_setup.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index 34fed417e70..c79a3e63653 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -1692,7 +1692,7 @@ class Setup extends DolibarrApi * @param int $active Payment term is active or not {@min 0} {@max 1} * @param string $lang Code of the language the label of the type must be translated to * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.code:like:'A%') and (t.active:>=:0)" - * @return array List of ticket types + * @return array List of incoterm types * * @url GET dictionary/incoterms * From 6ab5c79c6b0ff4ab70033743bb5889f16a1a47b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sat, 21 Jan 2023 11:46:11 +0100 Subject: [PATCH 711/816] box_birthday_member doesn't give same date than box_birthday --- htdocs/core/boxes/box_birthdays_members.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/boxes/box_birthdays_members.php b/htdocs/core/boxes/box_birthdays_members.php index fc8dc4c6745..64a1f16e624 100644 --- a/htdocs/core/boxes/box_birthdays_members.php +++ b/htdocs/core/boxes/box_birthdays_members.php @@ -2,7 +2,7 @@ /* Copyright (C) 2003-2007 Rodolphe Quiedeville * Copyright (C) 2004-2010 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin - * Copyright (C) 2015-2019 Frederic France + * Copyright (C) 2015-2023 Frederic France * * 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 @@ -115,7 +115,7 @@ class box_birthdays_members extends ModeleBoxes $this->info_box_contents[$line][] = array( 'td' => 'class="center nowraponall"', - 'text' => dol_print_date($dateb, "day", 'gmt').' - '.$age.' '.$langs->trans('DurationYears') + 'text' => dol_print_date($dateb, "day", 'tzserver').' - '.$age.' '.$langs->trans('DurationYears') ); /*$this->info_box_contents[$line][] = array( From fa185e9cf0118ff88b91f6e968d63cd5f9414755 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 21 Jan 2023 12:24:54 +0100 Subject: [PATCH 712/816] NEW Add helplist property to describe fields of obects --- htdocs/modulebuilder/template/class/myobject.class.php | 2 +- htdocs/modulebuilder/template/myobject_list.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index c60dbaa7e5b..9544e9c25ef 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -96,7 +96,7 @@ class MyObject extends CommonObject * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' - * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. + * 'help' and 'helplist' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index b28a7a5f955..58231ee7de5 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -634,7 +634,7 @@ foreach ($object->fields as $key => $val) { } $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label if (!empty($arrayfields['t.'.$key]['checked'])) { - print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''), 0, (empty($val['helplist']) ? '' : $val['helplist']))."\n"; $totalarray['nbfield']++; } } From 7d6c802085854529144946d274cbc60a5328de87 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 21 Jan 2023 12:25:23 +0100 Subject: [PATCH 713/816] Fix image size --- doc/images/dolibarr_screenshot1_1280x800.jpg | Bin 140952 -> 175013 bytes doc/images/dolibarr_screenshot2_1280x800.jpg | Bin 159669 -> 185341 bytes doc/images/dolibarr_screenshot5_1280x800.jpg | Bin 135317 -> 157713 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/images/dolibarr_screenshot1_1280x800.jpg b/doc/images/dolibarr_screenshot1_1280x800.jpg index ac238d39c1f8d5e022217ad3a690ccee819cd100..6d2c431239430a9949d125120f24abf215d66e0a 100644 GIT binary patch literal 175013 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

      TMpr=C4~b=d24m0EtS+K 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 diff --git a/doc/images/dolibarr_screenshot2_1280x800.jpg b/doc/images/dolibarr_screenshot2_1280x800.jpg index 2956a55d36aa8b86d46eae11e987f1c88c4c77e3..7f5319942c280da6f083e2eef93106d07c796212 100644 GIT binary patch literal 185341 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 z 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

      k=&p%0vx@~)?vnG|FD}&AsfzZ1~a}B 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

      2yQWp{p{P6PFV6n*i9 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%0D!N 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�<&qccLSIk{jL8 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%0Aq&_@9cyKK$hZ#2zu8Ci4Dv7+c0l)xt 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 O{@DZ9C;ia>e-i*~FhZ{Y diff --git a/doc/images/dolibarr_screenshot5_1280x800.jpg b/doc/images/dolibarr_screenshot5_1280x800.jpg index 6eea0a2f02936c757f5403c168a1c67678f2d3d3..f9ddd1d1f77bb72e03ffd0fb8dc84bb6e9b926da 100644 GIT binary patch literal 157713 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

      (2r!V>?s;JfU4J99?#AZm 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Ę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 BA`}1s From fb492515dfa60ba8569d93de4829fc963833302c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sat, 21 Jan 2023 13:08:47 +0100 Subject: [PATCH 714/816] fix missing include --- htdocs/mailmanspip/class/mailmanspip.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/mailmanspip/class/mailmanspip.class.php b/htdocs/mailmanspip/class/mailmanspip.class.php index 6bc34977e4e..e03ea174ef7 100644 --- a/htdocs/mailmanspip/class/mailmanspip.class.php +++ b/htdocs/mailmanspip/class/mailmanspip.class.php @@ -6,7 +6,7 @@ * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2009 Regis Houssin * Copyright (C) 2012 Marcos García - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018-2023 Frédéric France * * 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 @@ -128,6 +128,7 @@ class MailmanSpip { global $conf; + require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; //Patterns that are going to be replaced with their original value $patterns = array( '%LISTE%', @@ -139,7 +140,7 @@ class MailmanSpip $list, $object->email, $object->pass, - $conf->global->ADHERENT_MAILMAN_ADMIN_PASSWORD + getDolGlobalString('ADHERENT_MAILMAN_ADMIN_PASSWORD') ); $curl_url = str_replace($patterns, $replace, $url); From e48b16a9c5b9c8a6aea162f74584e237fad68b73 Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sat, 21 Jan 2023 23:20:43 +0100 Subject: [PATCH 715/816] integrate Contact Management for Supplier Orders --- .../fourn/class/api_supplier_orders.class.php | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/htdocs/fourn/class/api_supplier_orders.class.php b/htdocs/fourn/class/api_supplier_orders.class.php index d55a398dbd6..1b7098d9cc5 100644 --- a/htdocs/fourn/class/api_supplier_orders.class.php +++ b/htdocs/fourn/class/api_supplier_orders.class.php @@ -288,6 +288,155 @@ class SupplierOrders extends DolibarrApi return false; } + /** + * Get contacts of given supplier order + * + * Return an array with contact informations + * + * @param int $id ID of supplier order + * @param string $source Source of the contact (internal, external, all). + * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...) + * @return Object Object with cleaned properties + * + * @url GET {id}/contacts + * + * @throws RestException + */ + public function getContacts($id, $source, $type = '') + { + if (!DolibarrApiAccess::$user->rights->fournisseur->commande->lire) { + throw new RestException(401); + } + + $result = $this->order->fetch($id); + if (!$result) { + throw new RestException(404, 'Supplier order not found'); + } + + if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $contacts = array(); + + if ($source == 'all' || $source == 'external') { + $tmpContacts = $this->order->liste_contact(-1, 'external', 0, $type); + $contacts = array_merge($contacts, $tmpContacts); + } + + if ($source == 'all' || $source == 'internal') { + $tmpContacts = $this->order->liste_contact(-1, 'internal', 0, $type); + $contacts = array_merge($contacts, $tmpContacts); + } + + return $this->_cleanObjectDatas($contacts); + } + + /** + * Add a contact type of given supplier order + * + * @param int $id Id of supplier order to update + * @param int $contactid Id of contact/user to add + * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...) + * @param string $source Source of the contact (external, internal) + * @return array + * + * @url POST {id}/contact/{contactid}/{type}/{source} + * + * @throws RestException 401 + * @throws RestException 404 + */ + public function postContact($id, $contactid, $type, $source) + { + if (!DolibarrApiAccess::$user->rights->fournisseur->commande->creer) { + throw new RestException(401); + } + + $result = $this->order->fetch($id); + if (!$result) { + throw new RestException(404, 'Supplier order not found'); + } + + if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $result = $this->order->add_contact($contactid, $type, $source); + + if ($result < 0) { + throw new RestException(500, 'Error when added the contact'); + } + + if ($result == 0) { + throw new RestException(304, 'contact already added'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Contact linked to the order' + ) + ); + } + + /** + * Unlink a contact type of given supplier order + * + * @param int $id Id of supplier order to update + * @param int $contactid Id of contact/user to add + * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER, SALESREPFOLL, ...). + * @param string $source Source of the contact (internal, external). + * + * @url DELETE {id}/contact/{contactid}/{type}/{source} + * + * @return array + * + * @throws RestException 401 + * @throws RestException 404 + * @throws RestException 500 System error + */ + public function deleteContact($id, $contactid, $type, $source) + { + if (!DolibarrApiAccess::$user->rights->fournisseur->commande->creer) { + throw new RestException(401); + } + + $result = $this->order->fetch($id); + if (!$result) { + throw new RestException(404, 'Supplier order not found'); + } + + if (!DolibarrApi::_checkAccessToResource('fournisseur', $this->order->id, 'commande_fournisseur', 'commande')) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $contacts = $this->order->liste_contact(-1, $source, 0, $type); + + $contactToUnlink = 0; + foreach ($contacts as $contact) { + if ($contact['id'] == $contactid && $contact['code'] == $type) { + $contactToUnlink = $contact['rowid']; + break; + } + } + + if ($contactToUnlink == 0) { + throw new RestException(404, 'Linked contact not found'); + } + + $result = $this->order->delete_contact($contact['rowid']); + + if (!$result) { + throw new RestException(500, 'Error when deleted the contact'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Contact unlinked from supplier order' + ) + ); + } + /** * Delete supplier order * From 5c5d8d11f338906ee3feed954bfef0ab1a71dae1 Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sat, 21 Jan 2023 23:43:47 +0100 Subject: [PATCH 716/816] add parentId (example id for SupplierOrder) --- htdocs/core/class/commonobject.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index b998fcbd71a..88fefed035f 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1397,6 +1397,7 @@ abstract class CommonObject $transkey = "TypeContact_".$obj->element."_".$obj->source."_".$obj->code; $libelle_type = ($langs->trans($transkey) != $transkey ? $langs->trans($transkey) : $obj->libelle); $tab[$i] = array( + 'parentId' => $this->id, 'source' => $obj->source, 'socid' => $obj->socid, 'id' => $obj->id, From 9806941217c7f96c2612276858b5c1f4464252c5 Mon Sep 17 00:00:00 2001 From: Faustin Date: Sun, 22 Jan 2023 12:37:40 +0100 Subject: [PATCH 717/816] Update what is needed --- htdocs/admin/oauth.php | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/oauth.php b/htdocs/admin/oauth.php index 1ed4683496e..6fadc36a285 100644 --- a/htdocs/admin/oauth.php +++ b/htdocs/admin/oauth.php @@ -109,13 +109,36 @@ if ($action == 'update') { $error++; } } - print $newconstvalue.'_ID'."######".GETPOST($constvalue.'_ID')."\n"; + // If name changed, we have to delete old const and proceed few other changes if ($constvalue !== $newconstvalue) { dolibarr_del_const($db, $constvalue.'_ID', $conf->entity); dolibarr_del_const($db, $constvalue.'_SECRET', $conf->entity); dolibarr_del_const($db, $constvalue.'_URLAUTHORIZE', $conf->entity); dolibarr_del_const($db, $constvalue.'_SCOPE', $conf->entity); + + // Update name of token + $oldname = preg_replace('/^OAUTH_/', '', $constvalue); + $oldprovider = ucfirst(strtolower(preg_replace('/-.*$/', '', $oldname))); + $oldlabel = preg_replace('/^.*-/', '', $oldname); + $newlabel = preg_replace('/^.*-/', '', $newconstvalue); + + $sql = "UPDATE ".MAIN_DB_PREFIX."oauth_token"; + $sql.= " SET service = '".$oldprovider."-".$newlabel."'"; + $sql.= " WHERE service = '".$oldprovider."-".$oldlabel."'"; + + + $resql = $db->query($sql); + if (!$resql) { + $error++; + } + + // Update const where the token was used, might not be exhaustive + if (getDolGlobalString('MAIN_MAIL_SMTPS_OAUTH_SERVICE') == $oldname) { + if (!dolibarr_set_const($db, 'MAIN_MAIL_SMTPS_OAUTH_SERVICE', strtoupper($oldprovider).'-'.$newlabel, 'chaine', 0, '', $conf->entity)) { + $error++; + } + } } } } From 70509d105c2bc99b2d199bbd2a083e8511c25ecd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Jan 2023 13:27:22 +0100 Subject: [PATCH 718/816] Fix responsive --- htdocs/compta/prelevement/create.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index 37a2d74c5e3..317136e1333 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -74,6 +74,8 @@ if ($type == 'bank-transfer') { $error = 0; $option = ""; +$mesg = ''; + /* * Actions @@ -225,13 +227,13 @@ if ($type == 'bank-transfer') { $title = $langs->trans("NbOfInvoiceToPayByBankTransfer"); } -print '

    '; -print ''; +print ''; print ''; -print ''; print ''; @@ -417,6 +419,7 @@ if ($resql) { $tradinvoice = "SupplierInvoice"; } + print '
    '; print '
    '; + print dol_escape_htmltag($invoicetmp->ref_supplier); + print "'; print $thirdpartytmp->getNomUrl(1); print "
    '.$langs->trans("Total").'  '; //if ($totalinvoices != $object->amount) print img_warning("AmountOfFileDiffersFromSumOfInvoices"); // It is normal to have total that differs. For an amount of invoice of 100, request to pay may be 50 only. From 9a40c966bd7d4cb67b8f16fbbb97b01d345034b0 Mon Sep 17 00:00:00 2001 From: piernov Date: Thu, 19 Jan 2023 16:25:59 +0100 Subject: [PATCH 688/816] Fix: don setPaid sets paid field When donation is classified as paid, paid field also needs to be set to 1 so that accounting reports show the correct information. --- htdocs/don/class/don.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/don/class/don.class.php b/htdocs/don/class/don.class.php index 181b3fc0ca3..3b09e8cc178 100644 --- a/htdocs/don/class/don.class.php +++ b/htdocs/don/class/don.class.php @@ -758,7 +758,7 @@ class Don extends CommonObject */ public function setPaid($id, $modepayment = 0) { - $sql = "UPDATE ".MAIN_DB_PREFIX."don SET fk_statut = 2"; + $sql = "UPDATE ".MAIN_DB_PREFIX."don SET fk_statut = 2, paid = 1"; if ($modepayment) { $sql .= ", fk_payment = ".((int) $modepayment); } @@ -768,6 +768,7 @@ class Don extends CommonObject if ($resql) { if ($this->db->affected_rows($resql)) { $this->statut = 2; + $this->paid = 1; return 1; } else { return 0; From 62d0b7b97299964cf85c5cd44c78eded7f92787a Mon Sep 17 00:00:00 2001 From: "T. Mulzer" Date: Thu, 19 Jan 2023 17:10:50 +0100 Subject: [PATCH 689/816] Update get_attribute_values.php --- htdocs/variants/ajax/get_attribute_values.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/variants/ajax/get_attribute_values.php b/htdocs/variants/ajax/get_attribute_values.php index 1867eb368de..3950a262500 100644 --- a/htdocs/variants/ajax/get_attribute_values.php +++ b/htdocs/variants/ajax/get_attribute_values.php @@ -83,4 +83,4 @@ if ($res == -1) { exit(); } -print json_encode($res); +print json_encode($res, JSON_PARTIAL_OUTPUT_ON_ERROR); From d8dcb0d1012278aea36f05f29cd4dde52a1714db Mon Sep 17 00:00:00 2001 From: "T. Mulzer" Date: Thu, 19 Jan 2023 17:13:25 +0100 Subject: [PATCH 690/816] Solves issue #17181 --- htdocs/variants/combinations.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/variants/combinations.php b/htdocs/variants/combinations.php index 5128f31d0c5..e5043dcd7fa 100644 --- a/htdocs/variants/combinations.php +++ b/htdocs/variants/combinations.php @@ -511,7 +511,7 @@ if (!empty($id) || !empty($ref)) { '; - - print '
     
    '; - if (!empty($value['icon'])) { - print ''; - } - print ''; - print '

    '; + if (!empty($value['icon'])) { + print ''; + } + print ''; + print '
     
    '; - if (!empty($value['icon'])) { - print ''; - } - print ''; - print '
    '.$title.''; -print $nb; +print '
    '.$title.''; +print dol_escape_htmltag($nb); print '
    '.$langs->trans("AmountTotal").''; +print ''; print price($pricetowithdraw); print '
    '; print ''; print ''; @@ -510,6 +513,8 @@ if ($resql) { print ''; } print "
    '.$langs->trans($tradinvoice).'
    '.$langs->trans("None").'
    "; + print ""; + print ""; print "
    \n"; } else { From 4208cb3bc67341ef7341f9a55aa70b327dd4c645 Mon Sep 17 00:00:00 2001 From: Faustin Date: Sun, 22 Jan 2023 13:54:39 +0100 Subject: [PATCH 719/816] escape missing in sql request --- htdocs/admin/oauth.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/oauth.php b/htdocs/admin/oauth.php index 6fadc36a285..8c082d674db 100644 --- a/htdocs/admin/oauth.php +++ b/htdocs/admin/oauth.php @@ -123,9 +123,10 @@ if ($action == 'update') { $oldlabel = preg_replace('/^.*-/', '', $oldname); $newlabel = preg_replace('/^.*-/', '', $newconstvalue); + $sql = "UPDATE ".MAIN_DB_PREFIX."oauth_token"; - $sql.= " SET service = '".$oldprovider."-".$newlabel."'"; - $sql.= " WHERE service = '".$oldprovider."-".$oldlabel."'"; + $sql.= " SET service = '".$db->escape($oldprovider."-".$newlabel)."'"; + $sql.= " WHERE service = '".$db->escape($oldprovider."-".$oldlabel)."'"; $resql = $db->query($sql); From 1beb0ad3981ebf837a0f9600887c9617318bf5d2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Jan 2023 14:09:19 +0100 Subject: [PATCH 720/816] Fix responsive --- htdocs/compta/prelevement/create.php | 48 ++++++++++++++++++---------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index 317136e1333..b6e651029de 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -234,7 +234,7 @@ print '
    '.$langs->trans("AmountTotal").''; -print price($pricetowithdraw); +print price($pricetowithdraw, 0, $langs, 1,-1, -1, $conf->currency); print '
    '; print ''; print ''; + if ($type == 'bank-transfer') { + print ''; + } print ''; print ''; print ''; @@ -442,17 +450,25 @@ if ($resql) { $bac->fetch(0, $obj->socid); + $invoicestatic->id = $obj->rowid; + $invoicestatic->ref = $obj->ref; + $invoicestatic->ref_supplier = $obj->ref_supplier; + print ''; // Ref invoice - print ''; + if ($type == 'bank-transfer') { + print ''; + } + // Thirdparty - print ''; From 9f8e368890d2e8d0bbd73423580417da63cee5ca Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Jan 2023 14:15:55 +0100 Subject: [PATCH 721/816] CSS --- htdocs/theme/eldy/global.inc.php | 2 +- htdocs/theme/md/style.css.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index bef2e6e7800..a8a79e8bb34 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1638,7 +1638,7 @@ table[summary="list_of_modules"] .fa-cog { .maxwidth40 { max-width: 40px; } .maxwidth50 { max-width: 50px; } .maxwidth75 { max-width: 75px; } -.maxwidthdate { max-width: 80px; } +.maxwidthdate { max-width: 85px; } .maxwidth100 { max-width: 100px; } .maxwidth125 { max-width: 125px; } .maxwidth150 { max-width: 150px; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index afc43936695..0fde8b72044 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1856,7 +1856,7 @@ tr.nobottom td { .maxwidth40 { max-width: 40px; } .maxwidth50 { max-width: 50px; } .maxwidth75 { max-width: 75px; } -.maxwidthdate { max-width: 80px; } +.maxwidthdate { max-width: 85px; } .maxwidth100 { max-width: 100px; } .maxwidth125 { max-width: 125px; } .maxwidth150 { max-width: 150px; } @@ -7652,7 +7652,7 @@ div.clipboardCPValue.hidewithsize { .lilevel1 span.paddingright { padding-right: 3px; } - + img.userphotopublicvcard { left: unset; top: unset; From 260ef315d053a9ff1d0235c696fb801e73763899 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Jan 2023 14:21:47 +0100 Subject: [PATCH 722/816] Fix missing include --- htdocs/compta/prelevement/create.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index b6e651029de..56a047a387c 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -34,6 +34,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/prelevement.lib.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; From 642ba67a55730128a6c9af4f687111266277a498 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Jan 2023 14:21:47 +0100 Subject: [PATCH 723/816] Fix missing include --- htdocs/compta/prelevement/create.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index 37a2d74c5e3..7c91bfcca8e 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -34,6 +34,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/prelevement.lib.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; From 29531b8cb425b639ee4499cdfb943722caa04845 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Jan 2023 18:57:22 +0100 Subject: [PATCH 724/816] Fix phpcs --- htdocs/compta/prelevement/create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index 56a047a387c..598b86fcda3 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -235,7 +235,7 @@ print ''; print ''; print ''; print ''; From 1513c46c77fe21b1fd38d82f57e8db200a8273fc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Jan 2023 19:25:37 +0100 Subject: [PATCH 725/816] Doxygen --- htdocs/core/lib/functions.lib.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index a25d083c251..1076d32602f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3885,14 +3885,14 @@ function dol_strlen($string, $stringencoding = 'UTF-8') /** * Make a substring. Works even if mbstring module is not enabled for better compatibility. * - * @param string $string String to scan - * @param string $start Start position - * @param int $length Length (in nb of characters or nb of bytes depending on trunconbytes param) - * @param string $stringencoding Page code used for input string encoding - * @param int $trunconbytes 1=Length is max of bytes instead of max of characters - * @return string substring + * @param string $string String to scan + * @param string $start Start position + * @param int|null $length Length (in nb of characters or nb of bytes depending on trunconbytes param) + * @param string $stringencoding Page code used for input string encoding + * @param int $trunconbytes 1=Length is max of bytes instead of max of characters + * @return string substring */ -function dol_substr($string, $start, $length, $stringencoding = '', $trunconbytes = 0) +function dol_substr($string, $start, $length = null, $stringencoding = '', $trunconbytes = 0) { global $langs; From 545fa935e399faa293e7865294f76e7bf859fc81 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Sun, 22 Jan 2023 20:41:25 +0100 Subject: [PATCH 726/816] Update ChangeLog --- ChangeLog | 136 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 70 insertions(+), 66 deletions(-) diff --git a/ChangeLog b/ChangeLog index 76ec4faf452..00fbde60b91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,10 +24,10 @@ For users: --------------- NEW: Minimal PHP version is now PHP 7.0 instead of PHP 5.6 -NEW: #21780 Add pid field to Cronjob class and store PID on job execution NEW: #19680 Add option PRODUCT_ALLOW_EXTERNAL_DOWNLOAD to automatically have uploaded files shared publicly by a link NEW: #20650 can move the checkbox column on left (experimental option MAIN_CHECKBOX_LEFT_COLUMN) NEW: #21000 Added columns 'alias_name' on project, supplier invoice, supplier order, supplier proposals and task list +NEW: #21780 Add pid field to Cronjob class and store PID on job execution NEW: #21395 Added option for dark theme mode in display - color and theme NEW: #21397 added option to auto define barcode numbers for third-parties in barcode module setup NEW: #21399 @@ -46,15 +46,11 @@ NEW: #22676 massaction for updating product prices NEW: #22735 Massaction to affect users on projects NEW: #25594 can chose if VAT ID is unique or not for third parties NEW: #4482 adding js to hide/show advanced option on the export data page + NEW: Add a constant to disallow modification of the product reference. -NEW: Add a method doAutoRenewContracts that can be used as a cron task. -NEW: Add " as enclosure by default for CSV export. Keep removing CR/LF. NEW: add attached file in presend email form of thirdparty card NEW: Add a way to enter LICENSE file content in property of website -NEW: add constant PROPAL_BYPASS_VALIDATED_STATUS NEW: Add employment anniversary in birthday box -NEW: Add fail2ban rules examples to limit access to /public pages -NEW: Add filter "Product subject to lot/Serial" in stock per lot/serial NEW: Add hidden option MAIN_EMAIL_SUPPORT_ACK to restore Email ack checkbox (feature abandonned by mailers) NEW: Add link to create an element from the category page NEW: Add max size send for "backup and link to mail" option @@ -63,43 +59,58 @@ NEW: Add more advices into the Setup security page NEW: Add new global variable for keeping the previous signature information on proposale (case of reopen a proposale) NEW: Add objectLink on expedition NEW: Add oldcopy to Ticket so triggers intercepting TICKET_MODIFY have access to old values of the updated properties -NEW: Add option FICHINTER_ALLOW_EXTERNAL_DOWNLOAD NEW: Add option --force on CLI cron_run_jobs.php NEW: Add option "Show price on the generated documents for receptions" -NEW: Add performance index (name for company and contact) and llx_bank_url(url_id) -NEW: Add picto property on sub-module for password generation +NEW: invoice export : add accounting affectation +NEW: label on products categories filter +NEW: manage no email with thirdparties (better for GDPR) +NEW: Manage VAT on all lines on purchases cycle +NEW: On a bank reconciled line, we can modify the bank receipt +NEW: parent company column and filter in invoice and order list +NEW: possibility to select scopes with checkbox for Oauth tokens +NEW: private and public note on user, thirdparty and contact list +NEW: Public counters feature +NEW: Saved token of OAUTH module are now encrypted into llx_oauth_token +NEW: Save one click to select on delivery ack, on emails. +NEW: scheduled job to send unpaid invoice reminder can now use the cc and bcc from email template +NEW: experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP) +NEW: can substitue project title in mail template +NEW: The purge of files can purge only if older than a number of seconds +NEW: Update ActionComm type_code on email message ticket +NEW: Finance - VAT - Admin - Add information on deadline day for submission of VAT declaration +NEW: Add the target to select attendees of event for emailings NEW: add redirect on action confirm addconsumedline and addproduceline -NEW: Add a new advanced permission "read price" -NEW: Add substitution key __SENDEREMAIL_SIGNATURE__ NEW: Add the referrer-policy to "same-origin" by default on all public pages. -NEW: Add the SMTP header References on ticket email created by email NEW: Add trigger to record the event of sending an email from a project #20912 -NEW: Allow download link option in module configuration (propal,invoice,supplier proposal, order) -NEW: Can enter the unit price including the vat +NEW: Allow download link option in module configuration (propal, order, invoice, supplier proposal) +NEW: Can enter the unit price including the VAT NEW: Can invoice task time per different services -NEW: Can join several files by default on email form NEW: Can set a commercial discount by entering amount including VAT -NEW: Can set a monthly frequency (or multiple) in cron tasks. NEW: Can set start and end dates and comment on button "Activate all services" NEW: can sort and preselected best supplier price -NEW: Can use products categories to make inventory -NEW: Change filter type on tickets list into a multiselect combo NEW: show date delivery planned on orders linked to company and product -NEW: Encrypt all sensitive constants in llx_const NEW: filter on reception dates (from / to) in cheque paiement card + NEW: Accountancy - Add a graphic option to enable lettering function - FPC21 NEW: Accountancy - Add a way to clean some words when you generate thirdparty accounting account NEW: Accountancy - Added an option during export to export or not the lettering FPC21 NEW: Accountancy - Manage supplier deposit with specific account NEW: Accountancy - Model Digitaria - Add a way to clean some words when you generate thirdparty accounting account FPC22 +NEW: Agenda - start a simple support of recurrent events on agenda NEW: Bank - add salaries & VAT in tab planned entries -NEW: Contracts - Default template of contract is not mandatory +NEW: Contracts - add a method doAutoRenewContracts that can be used as a cron task +NEW: Contracts - default template of contract is not mandatory NEW: Contracts - Manage Position (Rank) on Contract Lines NEW: EMail - can copy/paste images into emails sent NEW: EMail - can edit label of an emailing even once sent +NEW: EMail - can join several files by default on email form NEW: EMail - can send an email on scheduled job error +NEW: EMail - on a form to send an email, we show all emails of all contacts of object +NEW: EMail - add the SMTP header References on ticket email created by email +NEW: EMail - add substitution key __SENDEREMAIL_SIGNATURE__ NEW: EMail-Collector - add IMAP port setting NEW: EMail-Collector - add a button "Test collect" +NEW: Export - Add " as enclosure by default for CSV export. Keep removing CR/LF. NEW: Event-Organization - add date event (!= date project) and location on event organization NEW: Extrafields - add badge in admin extrafields setup NEW: Extrafields - can edit property css, cssview, csslist on extrafields @@ -111,8 +122,10 @@ NEW: Invoice - Add french mention on pdf when vat debit option is on NEW: Members - default_lang for members NEW: Members - Table of membership types NEW: Members - add free membership amounts at the membership type level +NEW: Orders - resize parent company column in order list +NEW: Products supplier price - autofill default supplier VAT NEW: Projects - add author on list -NEW: Projects - add the thirdparty column to the time list (projet/tasks/time.php) +NEW: Projects - add thirdparty column to the time list (projet/tasks/time.php) NEW: Proposals - show delivery mode on PDF for proposals NEW: Proposals - skip accept/refuse process for proposals (option PROPAL_SKIP_ACCEPT_REFUSE) NEW: Reception - add a from/to on search on date field @@ -120,64 +133,55 @@ NEW: Stock - page for mass stock transfer can be used with no source stock NEW: Stock - product categories filter on inventory list NEW: Stock - show product label on inventory NEW: Stock - manage virtual stock at a future date +NEW: Stock Inventory - add filter "Product subject to lot/Serial" in stock per lot/serial +NEW: Stock Inventory - can use products categories to make inventory +NEW: Supplier Order List - add column private and public note NEW: TakePOS - add margin infos to TakePOS invoice lines -NEW: TakePOS - display currency in TakePOS menu -NEW: TakePOS - Header Scroll in TakePOS NEW: TakePOS - add price to product box in TakePOS NEW: TakePOS - add setup parameters, can setup terminal name -NEW: TakePOS - support of Stripe Terminal with TakePOS -NEW: TakePOS - Receipt preview in TakePOS setup NEW: TakePOS - different product list on smartphone +NEW: TakePOS - display currency in TakePOS menu +NEW: TakePOS - Header Scroll in TakePOS +NEW: TakePOS - Receipt preview in TakePOS setup +NEW: TakePOS - support of Stripe Terminal with TakePOS NEW: Thirdparty - set thirdparty type with company modify trigger +NEW: Tickets - change filter type on tickets list into a multiselect combo NEW: Website - can delete a whole website if disabled NEW: Website - can remove a website template NEW: Website - can set header "Strict-Transport-Security" in web sites. NEW: Website - can switch status of website and page from the website toolbar NEW: Website - Templates of websites are now directories and not zip into core repo NEW: Website - add 4 other templates in website module -NEW: General - Bulk action to remove a category in list/search website pages -NEW: General - If we select another view list mode, we keep it -NEW: General - Introduce dolEncrypt and dolDecrypt to be able to encrypt data in db -NEW: invoice export : add accounting affectation -NEW: label on products categories filter -NEW: The link "add to bookmark" is always on top in the bookmark popup -NEW: manage no email with thirdparties (better for GDPR) -NEW: Manage VAT on all lines on purchases cycle -NEW: On a bank reconciled line, we can modify the bank receipt -NEW: On a form to send an email, we show all emails of all contacts of object -NEW: parent company column and filter in invoice and order list -NEW: Add show "Sales rep" option for PDF -NEW: Picto for shared link is clickable -NEW: possibility to select scopes with checkbox for Oauth tokens -NEW: private and public note on user, thirdparty and contact list -NEW: Product supplier price: autofill default supplier VAT -NEW: Public counters feature -NEW: Start a simple support of recurrent events on agenda -NEW: Resize parent company column in order list -NEW: Saved token of OAUTH module are now encrypted into llx_oauth_token -NEW: Save one click to select on delivery ack, on emails. -NEW: scheduled job to send unpaid invoice reminder can now use the cc and bcc from email template -NEW: Show also scheduled task never finished in scheduled task widget -NEW: show badge with number of extrafields in setup -NEW: show category tree in sellist and chkbxlst for common object -NEW: Show picto and color into combo for selection of tags -NEW: show sell-by and eat-by dates only if not empty -NEW: show SellBy/EatBy dates for each batch product in shipment card -NEW: experimental SMTP using PhpImap allowing OAuth2 authentication (need to add option MAIN_IMAP_USE_PHPIMAP) -NEW: can substitue project title in mail template -NEW: Supplier order list - Add column private and public note -NEW: The purge of files can purge only if older than a number of seconds -NEW: Update ActionComm type_code on email message ticket -NEW: VAT - Admin - Add information on deadline day for submission of VAT declaration -NEW: expand/collapse permissions on user permission page -NEW: Add the target to select attendees of event for emailings + +General: +NEW: Actions: Bulk action to remove a category in list/search website pages +NEW: Cronjobs: can set a monthly frequency (or multiple) in cron tasks +NEW: Database: Encrypt all sensitive constants in llx_const +NEW: Database: Add performance index (name for company and contact) and llx_bank_url(url_id) +NEW: Database: Introduce dolEncrypt and dolDecrypt to be able to encrypt data in db +NEW: GUI: If we select another view list mode, we keep it +NEW: GUI: the link "add to bookmark" is always on top in the bookmark popup +NEW: GUI: Picto for shared link is clickable +NEW: GUI: add picto property on sub-module for password generation +NEW: GUI: show also scheduled task never finished in scheduled task widget +NEW: GUI: show badge with number of extrafields in setup +NEW: GUI: show category tree in sellist and chkbxlst for common object +NEW: GUI: show picto and color into combo for selection of tags +NEW: GUI: show sell-by and eat-by dates only if not empty +NEW: GUI: show SellBy/EatBy dates for each batch product in shipment card +NEW: GUI/Permissions: expand/collapse permissions on user permission page +NEW: Permissions: add a new advanced permission "read price" +NEW: Print: add show "Sales rep" option for PDF +NEW: Security: add fail2ban rules examples to limit access to /public pages Option / Const for System: -NEW: MAIN_SEARCH_CATEGORY_PRODUCT_ON_LISTS const to show category customer filter -NEW: PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT showing warehouse on PDF -NEW: PRODUIT_DESC_IN_FORM accept (desktop only or +smartphone) +NEW: FICHINTER_ALLOW_EXTERNAL_DOWNLOAD +NEW: MAIN_SEARCH_CATEGORY_PRODUCT_ON_LISTS - const to show category customer filter +NEW: PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT - showing warehouse on PDF +NEW: PRODUIT_DESC_IN_FORM accept - desktop only or +smartphone +NEW: PROPAL_BYPASS_VALIDATED_STATUS NEW: PROPAL_NEW_AS_SIGNED -NEW: TIMESPENT_ALWAYS_UPDATE_THM, when it's on we always check current thm of user to update it in task time line +NEW: TIMESPENT_ALWAYS_UPDATE_THM - when it's on we always check current thm of user to update it in task time line Localisation: NEW: adding JAPAN Chart-of-Account and regions/departments @@ -207,7 +211,7 @@ NEW: support multilang in Civilities API Hooks: NEW: Actioncomm - add new hooks for actioncomm -NEW: Actioncomm - hook formConfirm on action comm card +NEW: Actioncomm - hook formConfirm on actioncomm card NEW: Agenda - hook on agenda pages NEW: Help - hook "changeHelpURL" to modify target of the help button NEW: Product - add hook to show virtual stock details on product stock card From fb2d9b315a7496b03e2e2960e67bf9c53137708e Mon Sep 17 00:00:00 2001 From: Christian Humpel Date: Sun, 22 Jan 2023 22:31:46 +0100 Subject: [PATCH 727/816] Fix bracket. --- htdocs/bom/bom_card.php | 301 ++++++++++++++++++++-------------------- 1 file changed, 150 insertions(+), 151 deletions(-) diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 333b6232f9f..fbced8e6773 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -358,11 +358,11 @@ if (empty($reshook)) { // Confirmation to delete if ($action == 'delete') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteBillOfMaterials'), $langs->trans('ConfirmDeleteBillOfMaterials'), 'confirm_delete', '', 0, 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteBillOfMaterials'), $langs->trans('ConfirmDeleteBillOfMaterials'), 'confirm_delete', '', 0, 1); } // Confirmation to delete line if ($action == 'deleteline') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); } // Confirmation of validation @@ -393,13 +393,13 @@ if (empty($reshook)) { $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy } $formquestion = array( - // 'text' => $langs->trans("ConfirmClone"), - // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), - // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + // 'text' => $langs->trans("ConfirmClone"), + // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), ); } - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('Validate'), $text, 'confirm_validate', $formquestion, 0, 1, 220); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('Validate'), $text, 'confirm_validate', $formquestion, 0, 1, 220); } // Confirmation of closing @@ -421,13 +421,13 @@ if (empty($reshook)) { $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy } $formquestion = array( - // 'text' => $langs->trans("ConfirmClone"), - // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), - // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + // 'text' => $langs->trans("ConfirmClone"), + // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), ); } - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('Close'), $text, 'confirm_close', $formquestion, 0, 1, 220); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('Close'), $text, 'confirm_close', $formquestion, 0, 1, 220); } // Confirmation of reopen @@ -444,26 +444,26 @@ if (empty($reshook)) { $formquestion = array(); if (isModEnabled('bom')) { $langs->load("mrp"); - require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; + require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php'; $forcecombo = 0; if ($conf->browser->name == 'ie') { $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy } $formquestion = array( - // 'text' => $langs->trans("ConfirmClone"), - // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), - // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + // 'text' => $langs->trans("ConfirmClone"), + // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), ); } - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ReOpen'), $text, 'confirm_reopen', $formquestion, 0, 1, 220); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ReOpen'), $text, 'confirm_reopen', $formquestion, 0, 1, 220); } // Clone confirmation if ($action == 'clone') { // Create an array for form $formquestion = array(); - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneBillOfMaterials', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneBillOfMaterials', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); } // Confirmation of action xxxx @@ -471,7 +471,7 @@ if (empty($reshook)) { $text = $langs->trans('ConfirmSetToDraft', $object->ref); $formquestion = array(); - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('SetToDraft'), $text, 'confirm_setdraft', $formquestion, 0, 1, 220); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('SetToDraft'), $text, 'confirm_setdraft', $formquestion, 0, 1, 220); } // Call Hook formConfirm @@ -489,7 +489,7 @@ if (empty($reshook)) { // Object card // ------------------------------------------------------------ - $linkback = ''.$langs->trans("BackToList").''; + $linkback = '' . $langs->trans("BackToList") . ''; $morehtmlref = '
    '; /* @@ -538,17 +538,17 @@ if (empty($reshook)) { print '
    '; print '
    '; print '
    '; - print '
    '.$langs->trans($tradinvoice).''.$langs->trans("RefSupplier").''.$langs->trans("ThirdParty").''.$langs->trans("RIB").''.$langs->trans("RUM").'
    '; - $invoicestatic->id = $obj->rowid; - $invoicestatic->ref = $obj->ref; + print ''; print $invoicestatic->getNomUrl(1, 'withdraw'); print ''; + print dol_escape_htmltag($invoicestatic->ref_supplier); + print ''; + print ''; $thirdpartystatic->fetch($obj->socid); print $thirdpartystatic->getNomUrl(1, 'ban'); print '
    '.$langs->trans("AmountTotal").''; -print price($pricetowithdraw, 0, $langs, 1,-1, -1, $conf->currency); +print price($pricetowithdraw, 0, $langs, 1, -1, -1, $conf->currency); print '
    '."\n"; + print '
    ' . "\n"; // Common attributes $keyforbreak = 'duration'; - include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php'; $object->calculateCosts(); - print ''; - print ''; + print ''; + print ''; // Other attributes - include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; print '
    '.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).''.price($object->total_cost).'
    '.$langs->trans("UnitCost").''.price($object->unit_cost).'
    ' . $form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")) . '' . price($object->total_cost) . '
    ' . $langs->trans("UnitCost") . '' . price($object->unit_cost) . '
    '; print ''; @@ -559,7 +559,6 @@ if (empty($reshook)) { print dol_get_fiche_end(); - /* * Lines */ @@ -580,7 +579,7 @@ if (empty($reshook)) { '; if (!empty($conf->use_javascript_ajax) && $object->status == 0) { - include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php'; + include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php'; } print '
    '; @@ -602,7 +601,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); if (empty($reshook)) - $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); + $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); } } @@ -652,7 +651,7 @@ if (empty($reshook)) { $reshook = $hookmanager->executeHooks('formAddObjectServiceLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); if (empty($reshook)) - $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); + $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); } } } @@ -665,146 +664,146 @@ if (empty($reshook)) { print "\n"; mrpCollapseBomManagement(); - } - $res = $object->fetchLines(); + $res = $object->fetchLines(); - // Buttons for actions + // Buttons for actions - if ($action != 'presend' && $action != 'editline') { - print '
    '."\n"; - $parameters = array(); - $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook - if ($reshook < 0) { - setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); - } - - if (empty($reshook)) { - // Send - //if (empty($user->socid)) { - // print '' . $langs->trans('SendMail') . ''."\n"; - //} - - // Back to draft - if ($object->status == $object::STATUS_VALIDATED) { - if ($permissiontoadd) { - print ''.$langs->trans("SetToDraft").''."\n"; - } + if ($action != 'presend' && $action != 'editline') { + print '
    ' . "\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } - // Modify - if ($object->status == $object::STATUS_DRAFT) { - if ($permissiontoadd) { - print ''.$langs->trans("Modify").''."\n"; - } else { - print ''.$langs->trans('Modify').''."\n"; - } - } + if (empty($reshook)) { + // Send + //if (empty($user->socid)) { + // print '' . $langs->trans('SendMail') . ''."\n"; + //} - // Validate - if ($object->status == $object::STATUS_DRAFT) { - if ($permissiontoadd) { - if (is_array($object->lines) && count($object->lines) > 0) { - print ''.$langs->trans("Validate").''."\n"; - } else { - $langs->load("errors"); - print ''.$langs->trans("Validate").''."\n"; + // Back to draft + if ($object->status == $object::STATUS_VALIDATED) { + if ($permissiontoadd) { + print '' . $langs->trans("SetToDraft") . '' . "\n"; } } - } - // Re-open - if ($permissiontoadd && $object->status == $object::STATUS_CANCELED) { - print ''.$langs->trans("ReOpen").''."\n"; - } - - // Create MO - if (isModEnabled('mrp')) { - if ($object->status == $object::STATUS_VALIDATED && !empty($user->rights->mrp->write)) { - print ''.$langs->trans("CreateMO").''."\n"; + // Modify + if ($object->status == $object::STATUS_DRAFT) { + if ($permissiontoadd) { + print '' . $langs->trans("Modify") . '' . "\n"; + } else { + print '' . $langs->trans('Modify') . '' . "\n"; + } } - } - // Clone - if ($permissiontoadd) { - print dolGetButtonAction($langs->trans("ToClone"), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.(!empty($object->socid) ? '&socid='.$object->socid : "").'&action=clone&object=bom', 'clone', $permissiontoadd); - } + // Validate + if ($object->status == $object::STATUS_DRAFT) { + if ($permissiontoadd) { + if (is_array($object->lines) && count($object->lines) > 0) { + print '' . $langs->trans("Validate") . '' . "\n"; + } else { + $langs->load("errors"); + print '' . $langs->trans("Validate") . '' . "\n"; + } + } + } - // Close / Cancel - if ($permissiontoadd && $object->status == $object::STATUS_VALIDATED) { - print ''.$langs->trans("Disable").''."\n"; - } + // Re-open + if ($permissiontoadd && $object->status == $object::STATUS_CANCELED) { + print '' . $langs->trans("ReOpen") . '' . "\n"; + } - /* - if ($user->rights->bom->write) - { - if ($object->status == 1) - { - print ''.$langs->trans("Disable").''."\n"; - } - else - { - print ''.$langs->trans("Enable").''."\n"; - } - } - */ + // Create MO + if (isModEnabled('mrp')) { + if ($object->status == $object::STATUS_VALIDATED && !empty($user->rights->mrp->write)) { + print '' . $langs->trans("CreateMO") . '' . "\n"; + } + } - // Delete - print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $permissiontodelete); + // Clone + if ($permissiontoadd) { + print dolGetButtonAction($langs->trans("ToClone"), '', 'default', $_SERVER['PHP_SELF'] . '?id=' . $object->id . (!empty($object->socid) ? '&socid=' . $object->socid : "") . '&action=clone&object=bom', 'clone', $permissiontoadd); + } + + // Close / Cancel + if ($permissiontoadd && $object->status == $object::STATUS_VALIDATED) { + print '' . $langs->trans("Disable") . '' . "\n"; + } + + /* + if ($user->rights->bom->write) + { + if ($object->status == 1) + { + print ''.$langs->trans("Disable").''."\n"; + } + else + { + print ''.$langs->trans("Enable").''."\n"; + } + } + */ + + // Delete + print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=delete&token=' . newToken(), 'delete', $permissiontodelete); + } + print '
    ' . "\n"; } - print '
    '."\n"; + + + // Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + if ($action != 'presend') { + print '
    '; + print ''; // ancre + + // Documents + $objref = dol_sanitizeFileName($object->ref); + $relativepath = $objref . '/' . $objref . '.pdf'; + $filedir = $conf->bom->dir_output . '/' . $objref; + $urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id; + $genallowed = $user->rights->bom->read; // If you can read, you can build the PDF to read content + $delallowed = $user->rights->bom->write; // If you can create/edit, you can remove a file on card + print $formfile->showdocuments('bom', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang); + + // Show links to link elements + $linktoelem = $form->showLinkToObjectBlock($object, null, array('bom')); + $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); + + + print '
    '; + + $MAXEVENT = 10; + + $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT . '/bom/bom_agenda.php?id=' . $object->id); + + // List of actions on element + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, $object->element, 0, 1, '', $MAXEVENT, '', $morehtmlcenter); + + print '
    '; + } + + //Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + // Presend form + $modelmail = 'bom'; + $defaulttopic = 'InformationMessage'; + $diroutput = $conf->bom->dir_output; + $trackid = 'bom' . $object->id; + + include DOL_DOCUMENT_ROOT . '/core/tpl/card_presend.tpl.php'; } - - - // Select mail models is same action as presend - if (GETPOST('modelselected')) { - $action = 'presend'; - } - - if ($action != 'presend') { - print '
    '; - print ''; // ancre - - // Documents - $objref = dol_sanitizeFileName($object->ref); - $relativepath = $objref.'/'.$objref.'.pdf'; - $filedir = $conf->bom->dir_output.'/'.$objref; - $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; - $genallowed = $user->rights->bom->read; // If you can read, you can build the PDF to read content - $delallowed = $user->rights->bom->write; // If you can create/edit, you can remove a file on card - print $formfile->showdocuments('bom', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang); - - // Show links to link elements - $linktoelem = $form->showLinkToObjectBlock($object, null, array('bom')); - $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); - - - print '
    '; - - $MAXEVENT = 10; - - $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/bom/bom_agenda.php?id='.$object->id); - - // List of actions on element - include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; - $formactions = new FormActions($db); - $somethingshown = $formactions->showactions($object, $object->element, 0, 1, '', $MAXEVENT, '', $morehtmlcenter); - - print '
    '; - } - - //Select mail models is same action as presend - if (GETPOST('modelselected')) { - $action = 'presend'; - } - - // Presend form - $modelmail = 'bom'; - $defaulttopic = 'InformationMessage'; - $diroutput = $conf->bom->dir_output; - $trackid = 'bom'.$object->id; - - include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; } // End of page From c067e52ec8c5896ff756d4b12d6c4ea220749f2c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Jan 2023 11:28:37 +0100 Subject: [PATCH 728/816] Doc --- htdocs/core/website.inc.php | 2 +- htdocs/main.inc.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php index 2bdc9080b78..82fcabd557b 100644 --- a/htdocs/core/website.inc.php +++ b/htdocs/core/website.inc.php @@ -112,7 +112,7 @@ if (!defined('USEDOLIBARRSERVER') && !defined('USEDOLIBARREDITOR')) { // The constant WEBSITE_MAIN_SECURITY_FORCECSP should never be defined by page, but the variable used just after may be // A default security policy that keep usage of js external component like ckeditor, stripe, google, working - // $contentsecuritypolicy = "font-src *; img-src *; style-src * 'unsafe-inline' 'unsafe-eval'; default-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; frame-src 'self' *.stripe.com; connect-src 'self';"; + // $contentsecuritypolicy = "font-src *; img-src *; style-src * 'unsafe-inline' 'unsafe-eval'; default-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; frame-ancestors 'self'; frame-src 'self' *.stripe.com; connect-src 'self';"; $contentsecuritypolicy = getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSP'); if (!is_object($hookmanager)) { diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 2904f576bf7..115be3cf0cf 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1473,7 +1473,7 @@ function top_httphead($contenttype = 'text/html', $forcenocache = 0) // If CSP not forced from the page // A default security policy that keep usage of js external component like ckeditor, stripe, google, working - // $contentsecuritypolicy = "font-src *; img-src *; style-src * 'unsafe-inline' 'unsafe-eval'; default-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; frame-src 'self' *.stripe.com; connect-src 'self';"; + // $contentsecuritypolicy = "frame-ancestors 'self'; font-src *; img-src *; style-src * 'unsafe-inline' 'unsafe-eval'; default-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; frame-src 'self' *.stripe.com; connect-src 'self';"; $contentsecuritypolicy = getDolGlobalString('MAIN_SECURITY_FORCECSP'); if (!is_object($hookmanager)) { @@ -1492,7 +1492,7 @@ function top_httphead($contenttype = 'text/html', $forcenocache = 0) if (!empty($contentsecuritypolicy)) { // For example, to restrict 'script', 'object', 'frames' or 'img' to some domains: - // script-src https://api.google.com https://anotherhost.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: https://static.example.com + // frame-ancestors 'self'; script-src https://api.google.com https://anotherhost.com; object-src https://youtube.com; frame-src https://youtube.com; img-src https://static.example.com // For example, to restrict everything to one domain, except 'object', ...: // default-src https://cdn.example.net; object-src 'none' // For example, to restrict everything to itself except img that can be on other servers: From 58043c5d5e225fd61df58b6e5b65cb63ad7e7bf1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Jan 2023 12:28:17 +0100 Subject: [PATCH 729/816] Add imgs --- doc/images/dolibarr_screenshot12_1280x800.jpg | Bin 0 -> 136840 bytes doc/images/dolibarr_screenshot4_1280x800.jpg | Bin 0 -> 117180 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/images/dolibarr_screenshot12_1280x800.jpg create mode 100644 doc/images/dolibarr_screenshot4_1280x800.jpg diff --git a/doc/images/dolibarr_screenshot12_1280x800.jpg b/doc/images/dolibarr_screenshot12_1280x800.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bdc3a13722803f97f641202bca8266bbd16578e0 GIT binary patch literal 136840 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

    *?*HeLgt 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�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 Date: Mon, 23 Jan 2023 19:36:55 +0100 Subject: [PATCH 730/816] Update llx_10_c_regions.sql add new Slovakia --- htdocs/install/mysql/data/llx_10_c_regions.sql | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/install/mysql/data/llx_10_c_regions.sql b/htdocs/install/mysql/data/llx_10_c_regions.sql index 52a1a3bbbb6..f86fbe069b8 100644 --- a/htdocs/install/mysql/data/llx_10_c_regions.sql +++ b/htdocs/install/mysql/data/llx_10_c_regions.sql @@ -78,6 +78,7 @@ -- Portugal -- Romania -> for Departmements -- San Salvador +-- Slovakia -- Slovenia -- Spain -- Switzerland/Suisse -> for Departmements/Cantons @@ -450,6 +451,13 @@ INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) values ( 8 INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) values ( 86, 8603, NULL, NULL, 'Occidental'); +-- Slovakia Regions (rowid country=201) +INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) VALUES ( 201, '20101', 'SK01', NULL, 'Bratislava Region'); +INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) VALUES ( 201, '20102', 'SK02', NULL, 'Western Slovakia'); +INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) VALUES ( 201, '20103', 'SK03', NULL, 'Central Slovakia'); +INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) VALUES ( 201, '20104', 'SK04', NULL, 'Eastern Slovakia'); + + -- Slovenia Regions (rowid country=202) INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) VALUES ( 202, '20203', 'SI03', NULL, 'East Slovenia'); INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom) VALUES ( 202, '20204', 'SI04', NULL, 'West Slovenia'); From c5fcd99f6e92f6228cddc3c998c28b758230dbd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NASSIET?= Date: Mon, 23 Jan 2023 19:51:00 +0100 Subject: [PATCH 731/816] Adding a hook addToLandingPageList in userihm context --- htdocs/user/param_ihm.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/htdocs/user/param_ihm.php b/htdocs/user/param_ihm.php index 3d2e3240ce3..136da34e1bd 100644 --- a/htdocs/user/param_ihm.php +++ b/htdocs/user/param_ihm.php @@ -215,6 +215,16 @@ if (isModEnabled('ticket')) { $tmparray['ticket/list.php?mainmenu=ticket&leftmenu='] = 'Tickets'; } +// Hook for insertion new items in the List of possible landing pages +$reshook = $hookmanager->executeHooks('addToLandingPageList', $tmparray, $object); +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} elseif ($reshook > 0) { + $tmparray=$hookmanager->resArray; +} elseif ($reshook == 0) { + $tmparray=array_merge($tmparray, $hookmanager->resArray); +} + $head = user_prepare_head($object); $title = $langs->trans("User"); From 229b06a33309c794d862a96cb2ed6f66d303b32b Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 23 Jan 2023 19:56:52 +0100 Subject: [PATCH 732/816] fix sql request by adding left join for user table --- htdocs/hrm/position_list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/hrm/position_list.php b/htdocs/hrm/position_list.php index 308e48e153b..de86b3d41c5 100644 --- a/htdocs/hrm/position_list.php +++ b/htdocs/hrm/position_list.php @@ -234,7 +234,7 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook $sql .= preg_replace('/^,/', '', $hookmanager->resPrint); $sql = preg_replace('/,\s*$/', '', $sql); -$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t, ".MAIN_DB_PREFIX.$userstatic->table_element." as u,".MAIN_DB_PREFIX."hrm_job as j"; +$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t LEFT JOIN ".MAIN_DB_PREFIX.$userstatic->table_element." as u on t.fk_user = u.rowid, ".MAIN_DB_PREFIX."hrm_job as j"; if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; } From 5ad4f278ca4a77d83bf58652d9f568a751a1f5dc Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Mon, 23 Jan 2023 20:26:04 +0100 Subject: [PATCH 733/816] Update list.php update parameters (like /modulebuilder/template/myobject_list.php) --- htdocs/adherents/list.php | 63 +++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index d06d91cbea6..2e04aba9167 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -30,9 +30,9 @@ // Load Dolibarr environment require '../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; @@ -41,47 +41,51 @@ $langs->loadLangs(array("members", "companies")); // Get parameters -$action = GETPOST('action', 'aZ09'); +$action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); $show_files = GETPOST('show_files', 'int'); -$confirm = GETPOST('confirm', 'alpha'); -$toselect = GETPOST('toselect', 'array'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'alpha'); +$toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'memberslist'; // To manage different context of search -$mode = GETPOST('mode', 'alpha'); - +$backtopage = GETPOST('backtopage', 'alpha'); +$optioncss = GETPOST('optioncss', 'aZ'); +$mode = GETPOST('mode', 'alpha'); // Search fields -$search = GETPOST("search", 'alpha'); -$search_ref = GETPOST("search_ref", 'alpha'); -$search_lastname = GETPOST("search_lastname", 'alpha'); -$search_firstname = GETPOST("search_firstname", 'alpha'); -$search_gender = GETPOST("search_gender", 'alpha'); -$search_civility = GETPOST("search_civility", 'alpha'); -$search_company = GETPOST('search_company', 'alphanohtml'); -$search_login = GETPOST("search_login", 'alpha'); -$search_address = GETPOST("search_address", 'alpha'); -$search_zip = GETPOST("search_zip", 'alpha'); -$search_town = GETPOST("search_town", 'alpha'); -$search_state = GETPOST("search_state", 'alpha'); -$search_country = GETPOST("search_country", 'alpha'); -$search_phone = GETPOST("search_phone", 'alpha'); +$search = GETPOST("search", 'alpha'); +$search_ref = GETPOST("search_ref", 'alpha'); +$search_lastname = GETPOST("search_lastname", 'alpha'); +$search_firstname = GETPOST("search_firstname", 'alpha'); +$search_gender = GETPOST("search_gender", 'alpha'); +$search_civility = GETPOST("search_civility", 'alpha'); +$search_company = GETPOST('search_company', 'alphanohtml'); +$search_login = GETPOST("search_login", 'alpha'); +$search_address = GETPOST("search_address", 'alpha'); +$search_zip = GETPOST("search_zip", 'alpha'); +$search_town = GETPOST("search_town", 'alpha'); +$search_state = GETPOST("search_state", 'alpha'); // county / departement / federal state +$search_country = GETPOST("search_country", 'alpha'); +$search_phone = GETPOST("search_phone", 'alpha'); $search_phone_perso = GETPOST("search_phone_perso", 'alpha'); $search_phone_mobile = GETPOST("search_phone_mobile", 'alpha'); -$search_type = GETPOST("search_type", 'alpha'); -$search_email = GETPOST("search_email", 'alpha'); -$search_categ = GETPOST("search_categ", 'int'); -$search_filter = GETPOST("search_filter", 'alpha'); -$search_status = GETPOST("search_status", 'intcomma'); -$search_morphy = GETPOST("search_morphy", 'alpha'); +$search_type = GETPOST("search_type", 'alpha'); +$search_email = GETPOST("search_email", 'alpha'); +$search_categ = GETPOST("search_categ", 'int'); +$search_morphy = GETPOST("search_morphy", 'alpha'); $search_import_key = trim(GETPOST("search_import_key", 'alpha')); -$catid = GETPOST("catid", 'int'); -$optioncss = GETPOST('optioncss', 'alpha'); -$socid = GETPOST('socid', 'int'); + +$catid = GETPOST("catid", 'int'); +$socid = GETPOST('socid', 'int'); + +$search_filter = GETPOST("search_filter", 'alpha'); +$search_status = GETPOST("search_status", 'intcomma'); // statut $filter = GETPOST("filter", 'alpha'); if ($filter) { $search_filter = $filter; // For backward compatibility } + $statut = GETPOST("statut", 'alpha'); if ($statut != '') { $search_status = $statut; // For backward compatibility @@ -93,6 +97,7 @@ if ($search_status < -2) { $search_status = ''; } +// Pagination parameters $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); From 2dcd811e37b1392b91090274e4e03974053878a5 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Mon, 23 Jan 2023 20:35:17 +0100 Subject: [PATCH 734/816] Update list.php update parameters --- htdocs/bookmarks/list.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/htdocs/bookmarks/list.php b/htdocs/bookmarks/list.php index 2adef615a70..3eae08bb60a 100644 --- a/htdocs/bookmarks/list.php +++ b/htdocs/bookmarks/list.php @@ -29,15 +29,18 @@ require_once DOL_DOCUMENT_ROOT.'/bookmarks/class/bookmark.class.php'; $langs->loadLangs(array('bookmarks', 'admin')); // Get Parameters -$action = GETPOST('action', 'aZ09'); +$id = GETPOST("id", 'int'); + +$action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); $show_files = GETPOST('show_files', 'int'); -$confirm = GETPOST('confirm', 'alpha'); -$toselect = GETPOST('toselect', 'array'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'alpha'); +$toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bookmarklist'; // To manage different context of search -$id = GETPOST("id", 'int'); -$optioncss = GETPOST('optioncss', 'alpha'); -$mode = GETPOST('mode', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); +$optioncss = GETPOST('optioncss', 'alpha'); +$mode = GETPOST('mode', 'aZ09'); // Load variable for pagination $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; From 6cf41da7745a397956d9ab97cef9bb29a6d0c5e8 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Mon, 23 Jan 2023 20:41:39 +0100 Subject: [PATCH 735/816] Update list.php --- htdocs/comm/action/list.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index 8807ccd4764..a0176ca18b0 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -33,18 +33,22 @@ require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/agenda.lib.php'; -include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; +include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; + // Load translation files required by the page $langs->loadLangs(array("users", "companies", "agenda", "commercial", "other", "orders", "bills")); -$action = GETPOST('action', 'aZ09'); +// Get Parameters +$action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'alpha'); +$toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'actioncommlist'; // To manage different context of search -$optioncss = GETPOST('optioncss', 'alpha'); -$toselect = GETPOST('toselect', 'array'); -$confirm = GETPOST('confirm', 'alpha'); +$optioncss = GETPOST('optioncss', 'alpha'); + $disabledefaultvalues = GETPOST('disabledefaultvalues', 'int'); @@ -70,6 +74,7 @@ if (GETPOST('search_actioncode', 'array')) { $actioncode = GETPOST("search_actioncode", "alpha", 3) ?GETPOST("search_actioncode", "alpha", 3) : (GETPOST("search_actioncode") == '0' ? '0' : ((empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE) || $disabledefaultvalues) ? '' : $conf->global->AGENDA_DEFAULT_FILTER_TYPE)); } +// Search Fields $search_id = GETPOST('search_id', 'alpha'); $search_title = GETPOST('search_title', 'alpha'); $search_note = GETPOST('search_note', 'alpha'); @@ -106,6 +111,7 @@ if (empty($filtert) && empty($conf->global->AGENDA_ALL_CALENDARS)) { $filtert = $user->id; } +// Pagination parameters $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); From cd13fcb0af0b687b61d60b416cac1d904ceff030 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Mon, 23 Jan 2023 21:04:31 +0100 Subject: [PATCH 736/816] Update list.php --- htdocs/comm/mailing/list.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/htdocs/comm/mailing/list.php b/htdocs/comm/mailing/list.php index 6916a2dfe5d..501de4c11cf 100644 --- a/htdocs/comm/mailing/list.php +++ b/htdocs/comm/mailing/list.php @@ -27,20 +27,24 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/comm/mailing/class/mailing.class.php'; // Load translation files required by the page -$langs->load("mails"); +$langs->load('mails'); -$sortfield = GETPOST('sortfield', 'aZ09comma'); -$sortorder = GETPOST('sortorder', 'aZ09comma'); -$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; -$optioncss = GETPOST('optioncss', 'alpha'); +// Get Parameters $massaction = GETPOST('massaction', 'alpha'); -$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +$optioncss = GETPOST('optioncss', 'alpha'); + +// 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 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) { $page = 0; } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; + if (!$sortorder) { $sortorder = "DESC"; } @@ -48,10 +52,12 @@ if (!$sortfield) { $sortfield = "m.date_creat"; } +// Search Fields $search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $search_ref = GETPOST("search_ref", "alpha") ? GETPOST("search_ref", "alpha") : GETPOST("sref", "alpha"); $filteremail = GETPOST('filteremail', 'alpha'); +// Initialize objects $object = new Mailing($db); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context @@ -128,7 +134,9 @@ if (empty($reshook)) { * View */ -llxHeader('', $langs->trans("Mailing"), 'EN:Module_EMailing|FR:Module_Mailing|ES:Módulo_Mailing'); +// Page Header +$help_url = 'EN:Module_EMailing|FR:Module_Mailing|ES:Módulo_Mailing'; +llxHeader('', $langs->trans("Mailing"), $help_url); $form = new Form($db); From 0c30837f154c3089a7562708587d58b6d30edc6c Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Mon, 23 Jan 2023 21:09:34 +0100 Subject: [PATCH 737/816] Update list.php --- htdocs/comm/propal/list.php | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index cc5872abb25..93d2298795c 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -62,21 +62,23 @@ if (isModEnabled("expedition")) { $langs->loadLangs(array('sendings')); } +// Get Parameters $socid = GETPOST('socid', 'int'); -$action = GETPOST('action', 'aZ09'); +$action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); $show_files = GETPOST('show_files', 'int'); -$confirm = GETPOST('confirm', 'alpha'); -$toselect = GETPOST('toselect', 'array'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'alpha'); +$toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'proposallist'; -$mode = GETPOST('mode', 'alpha'); +$mode = GETPOST('mode', 'alpha'); -$search_user = GETPOST('search_user', 'int'); -$search_sale = GETPOST('search_sale', 'int'); -$search_ref = GETPOST('sf_ref') ?GETPOST('sf_ref', 'alpha') : GETPOST('search_ref', 'alpha'); +// Search Fields +$search_user = GETPOST('search_user', 'int'); +$search_sale = GETPOST('search_sale', 'int'); +$search_ref = GETPOST('sf_ref') ?GETPOST('sf_ref', 'alpha') : GETPOST('search_ref', 'alpha'); $search_refcustomer = GETPOST('search_refcustomer', 'alpha'); - $search_refproject = GETPOST('search_refproject', 'alpha'); $search_project = GETPOST('search_project', 'alpha'); @@ -140,15 +142,15 @@ $search_date_signature_endyear = GETPOST('search_date_signature_endyear', 'int') $search_date_signature_start = dol_mktime(0, 0, 0, $search_date_signature_startmonth, $search_date_signature_startday, $search_date_signature_startyear); $search_date_signature_end = dol_mktime(23, 59, 59, $search_date_signature_endmonth, $search_date_signature_endday, $search_date_signature_endyear); - $search_status = GETPOST('search_status', 'alpha'); + $optioncss = GETPOST('optioncss', 'alpha'); $object_statut = GETPOST('search_statut', 'alpha'); $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $mesg = (GETPOST("msg") ? GETPOST("msg") : GETPOST("mesg")); - +// Pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); @@ -263,6 +265,7 @@ foreach ($object->fields as $key => $val) { $fieldstosearchall['t.'.$key] = $val['label']; } }*/ + // Definition of array of fields for columns /*$arrayfields = array(); foreach ($object->fields as $key => $val) { @@ -278,9 +281,11 @@ foreach ($object->fields as $key => $val) { ); } }*/ + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; +// Permissions $permissiontoread = $user->rights->propal->lire; $permissiontoadd = $user->rights->propal->creer; $permissiontodelete = $user->rights->propal->supprimer; From 482c842895e925f547221787f8ce9f8ed0077ec1 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 23 Jan 2023 20:15:00 +0000 Subject: [PATCH 738/816] Fixing style errors. --- htdocs/comm/propal/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 93d2298795c..cc507041ac6 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -69,7 +69,7 @@ $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); $show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); -$cancel = GETPOST('cancel', 'alpha'); +$cancel = GETPOST('cancel', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'proposallist'; $mode = GETPOST('mode', 'alpha'); From 25a6be008a199bec10b4eeae055235d2296e946b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Mon, 23 Jan 2023 21:34:20 +0100 Subject: [PATCH 739/816] clean code emailcollectorfilter --- .../class/emailcollectorfilter.class.php | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollectorfilter.class.php b/htdocs/emailcollector/class/emailcollectorfilter.class.php index cff80aa4153..327159f61a4 100644 --- a/htdocs/emailcollector/class/emailcollectorfilter.class.php +++ b/htdocs/emailcollector/class/emailcollectorfilter.class.php @@ -206,16 +206,14 @@ class EmailCollectorFilter extends CommonObject // Clear fields $object->ref = "copy_of_".$object->ref; - $object->title = $langs->trans("CopyOf")." ".$object->title; - // ... + // $object->title = $langs->trans("CopyOf")." ".$object->title; + // Clear extrafields that are unique if (is_array($object->array_options) && count($object->array_options) > 0) { $extrafields->fetch_name_optionals_label($this->table_element); foreach ($object->array_options as $key => $option) { $shortkey = preg_replace('/options_/', '', $key); if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey])) { - //var_dump($key); - //var_dump($clonedObj->array_options[$key]); exit; unset($object->array_options[$key]); } } @@ -252,26 +250,10 @@ class EmailCollectorFilter extends CommonObject public function fetch($id, $ref = null) { $result = $this->fetchCommon($id, $ref); - if ($result > 0 && !empty($this->table_element_line)) { - $this->fetchLines(); - } + return $result; } - /** - * Load object lines in memory from the database - * - * @return int <0 if KO, 0 if not found, >0 if OK - */ - /*public function fetchLines() - { - $this->lines=array(); - - // Load lines with object EmailcollectorFilterLine - - return count($this->lines)?1:0; - }*/ - /** * Update object into database * @@ -317,7 +299,6 @@ class EmailCollectorFilter extends CommonObject } $result = ''; - $companylink = ''; $label = ''.$langs->trans("EmailcollectorFilter").''; $label .= '
    '; @@ -468,7 +449,7 @@ class EmailCollectorFilter extends CommonObject $this->user_creation_id = $obj->fk_user_creat; $this->user_modification_id = $obj->fk_user_modif; - $this->date_creation = $this->db->jdate($obj->datec); + $this->date_creation = $this->db->jdate($obj->datec); $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem); } From d08965c293ecee1409c4720e63bd6d19463d1afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Mon, 23 Jan 2023 21:42:09 +0100 Subject: [PATCH 740/816] Update emailcollectoraction.class.php --- .../class/emailcollectoraction.class.php | 60 ++----------------- 1 file changed, 4 insertions(+), 56 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollectoraction.class.php b/htdocs/emailcollector/class/emailcollectoraction.class.php index e43a86da515..5616abbbd35 100644 --- a/htdocs/emailcollector/class/emailcollectoraction.class.php +++ b/htdocs/emailcollector/class/emailcollectoraction.class.php @@ -24,8 +24,6 @@ // Put here all includes required by your class file require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; -//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; -//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; /** * Class for EmailCollectorAction @@ -113,37 +111,6 @@ class EmailCollectorAction extends CommonObject public $status; // END MODULEBUILDER PROPERTIES - - - // If this object has a subtable with lines - - // /** - // * @var string Name of subtable line - // */ - //public $table_element_line = 'emailcollectoractiondet'; - - // /** - // * @var string Field with ID of parent key if this field has a parent - // */ - //public $fk_element = 'fk_emailcollectoraction'; - - // /** - // * @var string Name of subtable class that manage subtable lines - // */ - //public $class_element_line = 'EmailcollectorActionline'; - - // /** - // * @var array List of child tables. To test if we can delete object. - // */ - //protected $childtables=array(); - - // /** - // * @var EmailcollectorActionLine[] Array of subtable lines - // */ - //public $lines = array(); - - - /** * Constructor * @@ -225,16 +192,14 @@ class EmailCollectorAction extends CommonObject // Clear fields $object->ref = "copy_of_".$object->ref; - $object->title = $langs->trans("CopyOf")." ".$object->title; - // ... + // $object->title = $langs->trans("CopyOf")." ".$object->title; + // Clear extrafields that are unique if (is_array($object->array_options) && count($object->array_options) > 0) { $extrafields->fetch_name_optionals_label($this->table_element); foreach ($object->array_options as $key => $option) { $shortkey = preg_replace('/options_/', '', $key); if (!empty($extrafields->attributes[$this->element]['unique'][$shortkey])) { - //var_dump($key); - //var_dump($clonedObj->array_options[$key]); exit; unset($object->array_options[$key]); } } @@ -271,26 +236,10 @@ class EmailCollectorAction extends CommonObject public function fetch($id, $ref = null) { $result = $this->fetchCommon($id, $ref); - // if ($result > 0 && !empty($this->table_element_line)) { - // $this->fetchLinesCommon(); - // } + return $result; } - /** - * Load object lines in memory from the database - * - * @return int <0 if KO, 0 if not found, >0 if OK - */ - /*public function fetchLines() - { - $this->lines=array(); - - // Load lines with object EmailcollectorActionLine - - return count($this->lines)?1:0; - }*/ - /** * Update object into database * @@ -336,7 +285,6 @@ class EmailCollectorAction extends CommonObject } $result = ''; - $companylink = ''; $label = ''.$langs->trans("EmailcollectorAction").''; $label .= '
    '; @@ -487,7 +435,7 @@ class EmailCollectorAction extends CommonObject $this->user_creation_id = $obj->fk_user_creat; $this->user_modification_id = $obj->fk_user_modif; - $this->date_creation = $this->db->jdate($obj->datec); + $this->date_creation = $this->db->jdate($obj->datec); $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem); } From 124a76029ecdf541c4eef2428aea7a567f1ec497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NASSIET?= Date: Mon, 23 Jan 2023 21:45:28 +0100 Subject: [PATCH 741/816] Protection against deletion of ref_employee and national_registration_number while fields are not presents in the user tab --- htdocs/user/card.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index dbe1764f54e..21e18c94e99 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -417,8 +417,18 @@ if (empty($reshook)) { $object->civility_code = GETPOST("civility_code", 'aZ09'); $object->lastname = GETPOST("lastname", 'alphanohtml'); $object->firstname = GETPOST("firstname", 'alphanohtml'); - $object->ref_employee = GETPOST("ref_employee", 'alphanohtml'); - $object->national_registration_number = GETPOST("national_registration_number", 'alphanohtml'); + /* + * Protection against deletion of ref_employee while the field is not present in the user tab + */ + if (GETPOSTISSET("ref_employee")){ + $object->ref_employee = GETPOST("ref_employee", 'alphanohtml'); + } + /* + * Protection against deletion of national_registration_number while the field is not present in the user tab + */ + if (GETPOSTISSET("national_registration_number")){ + $object->national_registration_number = GETPOST("national_registration_number", 'alphanohtml'); + } $object->gender = GETPOST("gender", 'aZ09'); $object->pass = GETPOST("password", 'none'); // We can keep 'none' for password fields $object->api_key = (GETPOST("api_key", 'alphanohtml')) ? GETPOST("api_key", 'alphanohtml') : $object->api_key; From cade14a80736678fa09c2033581bd1a4cb9c6415 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 23 Jan 2023 21:13:30 +0000 Subject: [PATCH 742/816] Fixing style errors. --- htdocs/user/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 21e18c94e99..688ac6c28ac 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -420,13 +420,13 @@ if (empty($reshook)) { /* * Protection against deletion of ref_employee while the field is not present in the user tab */ - if (GETPOSTISSET("ref_employee")){ + if (GETPOSTISSET("ref_employee")) { $object->ref_employee = GETPOST("ref_employee", 'alphanohtml'); } /* * Protection against deletion of national_registration_number while the field is not present in the user tab */ - if (GETPOSTISSET("national_registration_number")){ + if (GETPOSTISSET("national_registration_number")) { $object->national_registration_number = GETPOST("national_registration_number", 'alphanohtml'); } $object->gender = GETPOST("gender", 'aZ09'); From 7f6d993040979d61a4a359d722cb2109c26c90a1 Mon Sep 17 00:00:00 2001 From: David Pareja Rodriguez Date: Tue, 24 Jan 2023 10:54:48 +0100 Subject: [PATCH 743/816] Encase database name in backticks --- htdocs/core/db/mysqli.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index fa24e4a70ac..3514777dd45 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -678,7 +678,7 @@ class DoliDBMysqli extends DoliDB } $tmpdatabase = preg_replace('/[^a-z0-9\.\-\_]/i', '', $database); - $sql = "SHOW TABLES FROM ".$tmpdatabase." ".$like.";"; + $sql = "SHOW TABLES FROM `".$tmpdatabase."` ".$like.";"; //print $sql; $result = $this->query($sql); if ($result) { From 01e90a48541973b95743f27a7073a91fee1c07b3 Mon Sep 17 00:00:00 2001 From: David Pareja Rodriguez Date: Tue, 24 Jan 2023 11:04:26 +0100 Subject: [PATCH 744/816] Fix wrong variable used to fetch replaced invoice --- htdocs/fourn/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index d1cd74099ae..fe952a31893 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -2940,7 +2940,7 @@ if ($action == 'create') { } if (isset($objectidnext) && $objectidnext > 0) { $facthatreplace = new FactureFournisseur($db); - $facthatreplace->fetch($facidnext); + $facthatreplace->fetch($objectidnext); print ' ('.$langs->transnoentities("ReplacedByInvoice", $facthatreplace->getNomUrl(1)).')'; } if ($object->type == FactureFournisseur::TYPE_CREDIT_NOTE || $object->type == FactureFournisseur::TYPE_DEPOSIT) { From b2ac7a72bee80f7fe1ae197648cb707689db005d Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Tue, 24 Jan 2023 11:21:59 +0100 Subject: [PATCH 745/816] FIX simple quote in generated file name from build doc mass action --- htdocs/core/actions_massactions.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 34e2fe8b34e..3c33765c407 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1035,7 +1035,7 @@ if (!$error && $massaction == "builddoc" && $permissiontoread && !GETPOST('butto $arrayofinclusion[] = '^'.preg_quote(dol_sanitizeFileName($tmppdf), '/').'\.pdf$'; } foreach ($listofobjectref as $tmppdf) { - $arrayofinclusion[] = '^'.preg_quote(dol_sanitizeFileName($tmppdf), '/').'_[a-zA-Z0-9-_]+\.pdf$'; // To include PDF generated from ODX files + $arrayofinclusion[] = '^'.preg_quote(dol_sanitizeFileName($tmppdf), '/').'_[a-zA-Z0-9\-\_\']+\.pdf$'; // To include PDF generated from ODX files } $listoffiles = dol_dir_list($uploaddir, 'all', 1, implode('|', $arrayofinclusion), '\.meta$|\.png', 'date', SORT_DESC, 0, true); From c463f0972d9577fb1833f549326782fd854c20a0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Jan 2023 12:15:57 +0100 Subject: [PATCH 746/816] Clean code --- htdocs/accountancy/customer/list.php | 5 ++--- htdocs/accountancy/expensereport/list.php | 3 +-- htdocs/accountancy/supplier/list.php | 5 ++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index 021c1ec7821..a4a12b97b98 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -43,10 +43,11 @@ $langs->loadLangs(array("bills", "companies", "compta", "accountancy", "other", $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); -$show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'accountancycustomerlist'; // To manage different context of search $optioncss = GETPOST('optioncss', 'alpha'); + $default_account = GETPOST('default_account', 'int'); // Select Box @@ -73,8 +74,6 @@ $search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_en $search_country = GETPOST('search_country', 'alpha'); $search_tvaintra = GETPOST('search_tvaintra', 'alpha'); -$btn_ventil = GETPOST('ventil', 'alpha'); - // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); $sortfield = GETPOST('sortfield', 'aZ09comma'); diff --git a/htdocs/accountancy/expensereport/list.php b/htdocs/accountancy/expensereport/list.php index 25b86a8d527..39508332d40 100644 --- a/htdocs/accountancy/expensereport/list.php +++ b/htdocs/accountancy/expensereport/list.php @@ -40,10 +40,9 @@ $langs->loadLangs(array("bills", "companies", "compta", "accountancy", "other", $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); -$show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); -$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'expensereportlist'; // To manage different context of search +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'accountancyexpensereportlist'; // To manage different context of search $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index 3b8e93cb54b..dfd8af7f68f 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -44,10 +44,11 @@ $langs->loadLangs(array("bills", "companies", "compta", "accountancy", "other", $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); -$show_files = GETPOST('show_files', 'int'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'accountancysupplierlist'; // To manage different context of search $optioncss = GETPOST('optioncss', 'alpha'); + $default_account = GETPOST('default_account', 'int'); // Select Box @@ -75,8 +76,6 @@ $search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_en $search_country = GETPOST('search_country', 'alpha'); $search_tvaintra = GETPOST('search_tvaintra', 'alpha'); -$btn_ventil = GETPOST('ventil', 'alpha'); - // Load variable for pagination $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : (empty($conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION) ? $conf->liste_limit : $conf->global->ACCOUNTING_LIMIT_LIST_VENTILATION); $sortfield = GETPOST('sortfield', 'aZ09comma'); From 5b5a3547e29a870ed6fed0485e8384df33ea72df Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Jan 2023 13:00:09 +0100 Subject: [PATCH 747/816] Debug v17 --- .../class/accountingaccount.class.php | 4 +++- htdocs/accountancy/customer/list.php | 19 +++++++++++++------ htdocs/accountancy/expensereport/index.php | 18 +++++++++++++----- htdocs/accountancy/expensereport/list.php | 4 ++-- htdocs/accountancy/supplier/list.php | 15 ++++++++++----- htdocs/core/class/html.form.class.php | 2 +- htdocs/core/lib/functions.lib.php | 4 ++-- htdocs/langs/en_US/accountancy.lang | 9 +++++---- 8 files changed, 49 insertions(+), 26 deletions(-) diff --git a/htdocs/accountancy/class/accountingaccount.class.php b/htdocs/accountancy/class/accountingaccount.class.php index 94ee1ac6029..8e5f7690dd1 100644 --- a/htdocs/accountancy/class/accountingaccount.class.php +++ b/htdocs/accountancy/class/accountingaccount.class.php @@ -723,7 +723,7 @@ class AccountingAccount extends CommonObject } /** - * Return Suggest accounting accounts to bind + * Return a suggested account (from chart of accounts) to bind * * @param Societe $buyer Object buyer * @param Societe $seller Object seller @@ -733,6 +733,8 @@ class AccountingAccount extends CommonObject * @param array $accountingAccount Array of Accounting account * @param string $type Customer / Supplier * @return array|int Accounting accounts suggested or < 0 if technical error. + * 'suggestedaccountingaccountbydefaultfor'=>Will be used for the label to show on tooltip for account by default on any product + * 'suggestedaccountingaccountfor'=>Is the account suggested for this product */ public function getAccountingCodeToBind(Societe $buyer, Societe $seller, Product $product, $facture, $factureDet, $accountingAccount = array(), $type = '') { diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index a4a12b97b98..35be32d6b34 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -519,8 +519,8 @@ if ($result) { print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "s.nom", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Country", $_SERVER["PHP_SELF"], "co.label", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("VATIntraShort", $_SERVER["PHP_SELF"], "s.tva_intra", "", $param, '', $sortfield, $sortorder); - print_liste_field_titre("AccountAccountingSuggest", '', '', '', '', '', '', '', 'nowraponall '); - print_liste_field_titre("IntoAccount", '', '', '', '', '', '', '', 'center '); + print_liste_field_titre("DataUsedToSuggestAccount", '', '', '', '', '', '', '', 'nowraponall '); + print_liste_field_titre("AccountAccountingSuggest", '', '', '', '', '', '', '', 'center '); $checkpicto = ''; if ($massactionbutton) { $checkpicto = $form->showCheckAddButtons('checkforselect', 1); @@ -639,7 +639,7 @@ if ($result) { print '

    '.dol_print_date($facture_static->date, 'day').''; + print ''; if ($product_static->id > 0) { print $product_static->getNomUrl(1); } @@ -648,7 +648,7 @@ if ($result) { } print ''; $text = dolGetFirstLineOfText(dol_string_nohtmltag($facture_static_det->desc, 1)); $trunclength = empty($conf->global->ACCOUNTING_LENGTH_DESCRIPTION) ? 32 : $conf->global->ACCOUNTING_LENGTH_DESCRIPTION; @@ -682,15 +682,22 @@ if ($result) { // Found accounts print ''; + // First show default account for any products $s = '1. '.(($facture_static_det->product_type == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; - $shelp = ''; + $shelp = ''; $ttype = 'help'; if ($suggestedaccountingaccountbydefaultfor == 'eec') { $shelp .= $langs->trans("SaleEEC"); + } elseif ($suggestedaccountingaccountbydefaultfor == 'eecwithvat') { + $shelp = $langs->trans("SaleEECWithVAT"); + } elseif ($suggestedaccountingaccountbydefaultfor == 'eecwithoutvatnumber') { + $shelp = $langs->trans("SaleEECWithoutVATNumber"); + $ttype = 'warning'; } elseif ($suggestedaccountingaccountbydefaultfor == 'export') { $shelp .= $langs->trans("SaleExport"); } $s .= ($code_sell_l > 0 ? length_accountg($code_sell_l) : ''.$langs->trans("NotDefined").''); - print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); + print $form->textwithpicto($s, $shelp, 1, $ttype, '', 0, 2, '', 1); + // Now show account for product if ($product_static->id > 0) { print '
    '; $s = '2. '.(($facture_static_det->product_type == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index 5064003c7ff..948130dd98a 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -58,6 +58,8 @@ $year_current = $year_start; // Validate History $action = GETPOST('action', 'aZ09'); +$chartaccountcode = dol_getIdFromCode($db, $conf->global->CHARTOFACCOUNTS, 'accounting_system', 'rowid', 'pcg_version'); + // Security check if (!isModEnabled('accounting')) { accessforbidden(); @@ -65,7 +67,7 @@ if (!isModEnabled('accounting')) { if ($user->socid > 0) { accessforbidden(); } -if (empty($user->rights->accounting->mouvements->lire)) { +if (!$user->hasRight('accounting', 'mouvements', 'lire')) { accessforbidden(); } @@ -74,7 +76,7 @@ if (empty($user->rights->accounting->mouvements->lire)) { * Actions */ -if (($action == 'clean' || $action == 'validatehistory') && $user->rights->accounting->bind->write) { +if (($action == 'clean' || $action == 'validatehistory') && $user->hasRight('accounting', 'bind', 'write')) { // Clean database $db->begin(); $sql1 = "UPDATE ".MAIN_DB_PREFIX."expensereport_det as erd"; @@ -109,8 +111,7 @@ if ($action == 'validatehistory') { $sql1 = "SELECT erd.rowid, accnt.rowid as suggestedid"; $sql1 .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd"; $sql1 .= " LEFT JOIN ".MAIN_DB_PREFIX."c_type_fees as t ON erd.fk_c_type_fees = t.id"; - $sql1 .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as accnt ON t.accountancy_code = accnt.account_number AND accnt.active = 1 AND accnt.entity =".((int) $conf->entity); - $sql1 .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_system as syst ON accnt.fk_pcg_version = syst.pcg_version AND syst.rowid = ".((int) $conf->global->CHARTOFACCOUNTS).' AND syst.active = 1,'; + $sql1 .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as accnt ON t.accountancy_code = accnt.account_number AND accnt.active = 1 AND accnt.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND accnt.entity =".((int) $conf->entity); $sql1 .= " ".MAIN_DB_PREFIX."expensereport as er"; $sql1 .= " WHERE erd.fk_expensereport = er.rowid AND er.entity = ".((int) $conf->entity); $sql1 .= " AND er.fk_statut IN (".ExpenseReport::STATUS_APPROVED.", ".ExpenseReport::STATUS_CLOSED.") AND erd.fk_code_ventilation <= 0"; @@ -176,6 +177,7 @@ llxHeader('', $langs->trans("ExpenseReportsVentilation")); $textprevyear = ''.img_previous().''; $textnextyear = ' '.img_next().''; + print load_fiche_titre($langs->trans("ExpenseReportsVentilation")." ".$textprevyear." ".$langs->trans("Year")." ".$year_start." ".$textnextyear, '', 'title_accountancy'); print ''.$langs->trans("DescVentilExpenseReport").'
    '; @@ -247,7 +249,7 @@ $sql .= " AND aa.account_number IS NULL"; $sql .= " GROUP BY erd.fk_code_ventilation,aa.account_number,aa.label"; $sql .= ' ORDER BY aa.account_number'; -dol_syslog('/accountancy/expensereport/index.php:: sql='.$sql); +dol_syslog('/accountancy/expensereport/index.php', LOG_DEBUG); $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); @@ -277,6 +279,12 @@ if ($resql) { print '
    '; + print ''.$langs->trans("NoRecordFound").''; + print '
    '; $s = '1. '.(($facturefourn_static_det->product_type == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; - $shelp = ''; + $shelp = ''; $ttype = 'help'; if ($suggestedaccountingaccountbydefaultfor == 'eec') { $shelp .= $langs->trans("SaleEEC"); + } elseif ($suggestedaccountingaccountbydefaultfor == 'eecwithvat') { + $shelp = $langs->trans("SaleEECWithVAT"); + } elseif ($suggestedaccountingaccountbydefaultfor == 'eecwithoutvatnumber') { + $shelp = $langs->trans("SaleEECWithoutVATNumber"); + $ttype = 'warning'; } elseif ($suggestedaccountingaccountbydefaultfor == 'export') { $shelp .= $langs->trans("SaleExport"); } $s .= ($code_buy_l > 0 ? length_accountg($code_buy_l) : ''.$langs->trans("NotDefined").''); - print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); + print $form->textwithpicto($s, $shelp, 1, $ttype, '', 0, 2, '', 1); if ($product_static->id > 0) { print '
    '; $s = '2. '.(($facturefourn_static_det->product_type == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 1bdad2ed3c5..52f91f86963 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6273,7 +6273,7 @@ class Form if (!empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) { // If option to have vat for end customer for services is on require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; if (!isInEEC($societe_vendeuse) && (!is_object($societe_acheteuse) || (isInEEC($societe_acheteuse) && !$societe_acheteuse->isACompany()))) { - // We also add the buyer + // We also add the buyer country code if (is_numeric($type)) { if ($type == 1) { // We know product is a service $code_country .= ",'".$societe_acheteuse->country_code."'"; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 0d4e30f4a2a..6bfc788ddd4 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -6490,7 +6490,7 @@ function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, if (!empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) { if ($seller_in_cee && $buyer_in_cee) { $isacompany = $thirdparty_buyer->isACompany(); - if ($isacompany && !empty($conf->global->MAIN_USE_VAT_COMPANIES_IN_EEC_WITH_INVALID_VAT_ID_ARE_INDIVIDUAL)) { + if ($isacompany && getDolGlobalString('MAIN_USE_VAT_COMPANIES_IN_EEC_WITH_INVALID_VAT_ID_ARE_INDIVIDUAL')) { require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; if (!isValidVATID($thirdparty_buyer)) { $isacompany = 0; @@ -6526,7 +6526,7 @@ function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, // Si (vendeur et acheteur dans Communaute europeenne) et (acheteur = particulier) alors TVA par defaut=TVA du produit vendu. Fin de regle if (($seller_in_cee && $buyer_in_cee)) { $isacompany = $thirdparty_buyer->isACompany(); - if ($isacompany && !empty($conf->global->MAIN_USE_VAT_COMPANIES_IN_EEC_WITH_INVALID_VAT_ID_ARE_INDIVIDUAL)) { + if ($isacompany && getDolGlobalString('MAIN_USE_VAT_COMPANIES_IN_EEC_WITH_INVALID_VAT_ID_ARE_INDIVIDUAL')) { require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; if (!isValidVATID($thirdparty_buyer)) { $isacompany = 0; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 5a1e51a2269..d44c86ceccd 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -14,8 +14,8 @@ ACCOUNTING_EXPORT_ENDLINE=Select the carriage return type ACCOUNTING_EXPORT_PREFIX_SPEC=Specify the prefix for the file name ThisService=This service ThisProduct=This product -DefaultForService=Default for service -DefaultForProduct=Default for product +DefaultForService=Default for services +DefaultForProduct=Default for products ProductForThisThirdparty=Product for this thirdparty ServiceForThisThirdparty=Service for this thirdparty CantSuggest=Can't suggest @@ -101,7 +101,8 @@ ShowAccountingAccount=Show accounting account ShowAccountingJournal=Show accounting journal ShowAccountingAccountInLedger=Show accounting account in ledger ShowAccountingAccountInJournals=Show accounting account in journals -AccountAccountingSuggest=Accounting account suggested +DataUsedToSuggestAccount=Data used to suggest account +AccountAccountingSuggest=Account suggested MenuDefaultAccounts=Default accounts MenuBankAccounts=Bank accounts MenuVatAccounts=Vat accounts @@ -401,7 +402,7 @@ SaleLocal=Local sale SaleExport=Export sale SaleEEC=Sale in EEC SaleEECWithVAT=Sale in EEC with a VAT not null, so we suppose this is NOT an intracommunautary sale and the suggested account is the standard product account. -SaleEECWithoutVATNumber=Sale in EEC with no VAT but the VAT ID of thirdparty is not defined. We fallback on the product account for standard sales. You can fix the VAT ID of thirdparty or the product account if needed. +SaleEECWithoutVATNumber=Sale in EEC with no VAT but the VAT ID of thirdparty is not defined. We fall back on the account for standard sales. You can fix the VAT ID of the thirdparty, or change the product account suggested for binding if needed. ForbiddenTransactionAlreadyExported=Forbidden: The transaction has been validated and/or exported. ForbiddenTransactionAlreadyValidated=Forbidden: The transaction has been validated. ## Dictionary From b964f1a4761c8adf2de08162ced6cc50f2167e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?No=C3=A9=20Courtier?= Date: Tue, 24 Jan 2023 14:21:14 +0100 Subject: [PATCH 748/816] FIX: page was not reloaded after addline causing a new lline creation was page was reloaded --- htdocs/expensereport/card.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 31cf21c34ae..3f0541c89b4 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -1161,8 +1161,9 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } - - $action = ''; + + header("Location: ".$_SERVER["PHP_SELF"]."?id=".GETPOST('id', 'int')); + exit; } if ($action == 'confirm_delete_line' && GETPOST("confirm", 'alpha') == "yes" && $user->rights->expensereport->creer) { From 08bd8caaf255fe5ec08dc9608238d9e99334d8b0 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 24 Jan 2023 13:28:59 +0000 Subject: [PATCH 749/816] Fixing style errors. --- htdocs/expensereport/card.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 3f0541c89b4..0756cb1bc7f 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -1161,9 +1161,9 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } - - header("Location: ".$_SERVER["PHP_SELF"]."?id=".GETPOST('id', 'int')); - exit; + + header("Location: ".$_SERVER["PHP_SELF"]."?id=".GETPOST('id', 'int')); + exit; } if ($action == 'confirm_delete_line' && GETPOST("confirm", 'alpha') == "yes" && $user->rights->expensereport->creer) { From 32da192db44a043b6d8e32f1b3339c5f9964289b Mon Sep 17 00:00:00 2001 From: hystepik Date: Tue, 24 Jan 2023 14:32:20 +0100 Subject: [PATCH 750/816] fix : php 8.1 warnings --- htdocs/compta/localtax/card.php | 5 ++++- htdocs/contrat/services_list.php | 3 +++ htdocs/loan/card.php | 5 +++-- htdocs/loan/list.php | 2 ++ htdocs/product/card.php | 2 +- htdocs/product/reassort.php | 2 +- htdocs/reception/contact.php | 2 +- htdocs/salaries/payments.php | 9 ++++++++- 8 files changed, 23 insertions(+), 7 deletions(-) diff --git a/htdocs/compta/localtax/card.php b/htdocs/compta/localtax/card.php index 8b6119db13a..ad80b6d1b6d 100644 --- a/htdocs/compta/localtax/card.php +++ b/htdocs/compta/localtax/card.php @@ -144,9 +144,12 @@ $form = new Form($db); $title = $langs->trans("LT".$object->ltt)." - ".$langs->trans("Card"); $help_url = ''; -llxHeader('', $title, $helpurl); +llxHeader('', $title, $help_url); if ($action == 'create') { + $datev = dol_mktime(12, 0, 0, GETPOST("datevmonth"), GETPOST("datevday"), GETPOST("datevyear")); + $datep = dol_mktime(12, 0, 0, GETPOST("datepmonth"), GETPOST("datepday"), GETPOST("datepyear")); + print load_fiche_titre($langs->transcountry($lttype == 2 ? "newLT2Payment" : "newLT1Payment", $mysoc->country_code)); print '
    '."\n"; diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index fb50283991b..d42dc70f49a 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -822,6 +822,9 @@ while ($i < min($num, $limit)) { if (!$i) { $totalarray['pos'][$totalarray['nbfield']] = 'cd.qty'; } + if (!$i) { + $totalarray['val']['cd.qty'] = $obj->qty; + } $totalarray['val']['cd.qty'] += $obj->qty; } if (!empty($arrayfields['cd.total_ht']['checked'])) { diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index a45577b6608..afa7aa5eaa8 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -66,6 +66,7 @@ $error = 0; * Actions */ +$parameters = array(); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); @@ -291,13 +292,13 @@ if ($action == 'create') { // Date Start print "
    '.$langs->trans("DateStart").''; - print $form->selectDate($datestart ? $datestart : -1, 'start', '', '', '', 'add', 1, 1); + print $form->selectDate(!empty($datestart) ? $datestart : -1, 'start', '', '', '', 'add', 1, 1); print '
    '.$langs->trans("DateEnd").''; - print $form->selectDate($dateend ? $dateend : -1, 'end', '', '', '', 'add', 1, 1); + print $form->selectDate(!empty($dateend) ? $dateend : -1, 'end', '', '', '', 'add', 1, 1); print '
    '.$langs->trans("DefaultWorkstation").''; print img_picto($langs->trans("DefaultWorkstation"), 'workstation', 'class="pictofixedwidth"'); diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index 10581d19b7c..9946e7a9077 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -133,7 +133,7 @@ $helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; $form = new Form($db); $htmlother = new FormOther($db); -if ($objp->stock_physique < 0) { print ''; } +if (!empty($objp->stock_physique) && $objp->stock_physique < 0) { print ''; } $sql = 'SELECT p.rowid, p.ref, p.label, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,'; $sql .= ' p.fk_product_type, p.tms as datem,'; diff --git a/htdocs/reception/contact.php b/htdocs/reception/contact.php index 02cbc9af957..11ab664c6c0 100644 --- a/htdocs/reception/contact.php +++ b/htdocs/reception/contact.php @@ -72,7 +72,7 @@ if ($origin == 'reception') { } else { if ($origin == 'supplierorder' || $origin == 'order_supplier') { $result = restrictedArea($user, 'fournisseur', $origin_id, 'commande_fournisseur', 'commande'); - } elseif (empty($user->rights->{$origin}->lire) && empty($user->rights->{$origin}->read)) { + } elseif (empty($user->hasRight($origin, "lire")) && empty($user->hasRight($origin, "read"))) { accessforbidden(); } } diff --git a/htdocs/salaries/payments.php b/htdocs/salaries/payments.php index 5a5ccb08bf6..7bf61f3021f 100644 --- a/htdocs/salaries/payments.php +++ b/htdocs/salaries/payments.php @@ -97,6 +97,7 @@ $search_chq_number = GETPOST('search_chq_number', 'int'); $filtre = GETPOST("filtre", 'restricthtml'); +$search_type_id = ''; if (!GETPOST('search_type_id', 'int')) { $newfiltre = str_replace('filtre=', '', $filtre); $filterarray = explode('-', $newfiltre); @@ -532,6 +533,7 @@ if (isset($extrafields->attributes[$object->table_element]['computed']) && is_ar $i = 0; $total = 0; $totalarray = array(); +$totalarray['nbfield'] = 0; while ($i < ($limit ? min($num, $limit) : $num)) { $obj = $db->fetch_object($resql); if (empty($obj)) { @@ -697,7 +699,12 @@ while ($i < ($limit ? min($num, $limit) : $num)) { if (!$i) { $totalarray['pos'][$totalarray['nbfield']] = 'totalttcfield'; } - $totalarray['val']['totalttcfield'] += $obj->amount; + if (!$i) { + $totalarray['val']['totalttcfield'] = $obj->amount; + } else { + $totalarray['val']['totalttcfield'] += $obj->amount; + } + // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; From fe6d9730cdd8c2cc44749b56fed71401e4de9322 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Jan 2023 16:58:35 +0100 Subject: [PATCH 751/816] Fix messages to avoid confusion. --- htdocs/accountancy/bookkeeping/list.php | 11 +++++++---- htdocs/langs/en_US/accountancy.lang | 2 ++ htdocs/langs/en_US/main.lang | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index fa42b5bd6fd..983da7502d9 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -474,7 +474,7 @@ if (empty($reshook)) { if ($conf->global->ACCOUNTING_REEXPORT == 1) { setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsEnable"), null, 'mesgs'); } else { - setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsDisable"), null, 'mesgs'); + setEventMessages($langs->trans("ExportOfPiecesAlreadyExportedIsDisable"), null, 'warnings'); } } else { setEventMessages($langs->trans("Error"), null, 'errors'); @@ -953,11 +953,14 @@ $newcardbutton = empty($hookmanager->resPrint) ? '' : $hookmanager->resPrint; if (empty($reshook)) { // Button re-export if (!empty($conf->global->ACCOUNTING_REEXPORT)) { - $newcardbutton .= ''.img_picto($langs->trans("Activated"), 'switch_on').' '; + $newcardbutton .= ''.img_picto($langs->trans("ClickToHideAlreadyExportedLines"), 'switch_off', 'class="small size15x valignmiddle"'); + $newcardbutton .= ''.$langs->trans("ClickToHideAlreadyExportedLines").''; + $newcardbutton .= ''; } else { - $newcardbutton .= ''.img_picto($langs->trans("Disabled"), 'switch_off').' '; + $newcardbutton .= ''.img_picto($langs->trans("DocsAlreadyExportedAreExcluded"), 'switch_on', 'class="warning size15x valignmiddle"').''; + $newcardbutton .= ''.$langs->trans("DocsAlreadyExportedAreExcluded").''; + $newcardbutton .= ''; } - $newcardbutton .= ''.$langs->trans("IncludeDocsAlreadyExported").''; if ($user->hasRight('accounting', 'mouvements', 'export')) { $newcardbutton .= dolGetButtonTitle($buttonLabel, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', 'fa fa-file-export paddingleft', $_SERVER["PHP_SELF"].'?action=export_file&token='.newToken().($param ? '&'.$param : ''), $user->hasRight('accounting', 'mouvements', 'export')); diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index d44c86ceccd..801618352aa 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -472,5 +472,7 @@ FECFormatMulticurrencyCode=Multicurrency code (Idevise) DateExport=Date export WarningReportNotReliable=Warning, this report is not based on the Ledger, so does not contains transaction modified manually in the Ledger. If your journalization is up to date, the bookkeeping view is more accurate. ExpenseReportJournal=Expense Report Journal +DocsAlreadyExportedAreExcluded=Docs already exported are excluded +ClickToHideAlreadyExportedLines=Click to hide already exported lines NAccounts=%s accounts diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 73dfee80a69..45119814420 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -912,8 +912,8 @@ ExportFilteredList=Export filtered list ExportList=Export list ExportOptions=Export Options IncludeDocsAlreadyExported=Include docs already exported -ExportOfPiecesAlreadyExportedIsEnable=Export of pieces already exported is enable -ExportOfPiecesAlreadyExportedIsDisable=Export of pieces already exported is disable +ExportOfPiecesAlreadyExportedIsEnable=Documents already exported are visible and will be exported +ExportOfPiecesAlreadyExportedIsDisable=Documents already exported are hidden and won't be exported AllExportedMovementsWereRecordedAsExported=All exported movements were recorded as exported NotAllExportedMovementsCouldBeRecordedAsExported=Not all exported movements could be recorded as exported Miscellaneous=Miscellaneous From 891ba8f4ef6362639710058bc0d2f7242ef9fdea Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Jan 2023 17:05:42 +0100 Subject: [PATCH 752/816] Debug v17 --- htdocs/core/class/conf.class.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 279ccded71c..2d6cc4f5715 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -783,6 +783,11 @@ class Conf $this->global->USE_STRICT_CSV_RULES = 2; } + // By default, option is on. Once set by user, this code is useless + if (!isset($this->global->ACCOUNTING_REEXPORT)) { + $this->global->ACCOUNTING_REEXPORT = 1; + } + // Use a SCA ready workflow with Stripe module (STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION by default if nothing defined) if (!isset($this->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION) && empty($this->global->STRIPE_USE_NEW_CHECKOUT)) { $this->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = 1; From 5429882147db304bd3fa533f443e6436a79290d6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Jan 2023 18:23:46 +0100 Subject: [PATCH 753/816] Debug v17 --- htdocs/accountancy/bookkeeping/list.php | 7 +- htdocs/core/lib/functions.lib.php | 2 +- htdocs/hrm/job_list.php | 290 +++++++++++++++--------- 3 files changed, 182 insertions(+), 117 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 983da7502d9..086a5acd918 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -994,7 +994,7 @@ if ($massaction == 'preunletteringauto') { include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields if ($massactionbutton && $contextpage != 'poslist') { $selectedfields .= $form->showCheckAddButtons('checkforselect', 1); } @@ -1010,7 +1010,7 @@ if (empty($reshook)) { } print '
    '; -print ''; +print '
    '; // Filters lines print ''; @@ -1166,8 +1166,7 @@ print "\n"; print ''; if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); -} + print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch actioncolumn ');} if (!empty($arrayfields['t.piece_num']['checked'])) { print_liste_field_titre($arrayfields['t.piece_num']['label'], $_SERVER['PHP_SELF'], "t.piece_num", "", $param, "", $sortfield, $sortorder); } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 6bfc788ddd4..4d38c7e5e5d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4085,7 +4085,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ 'delete', 'dolly', 'dollyrevert', 'donation', 'download', 'dynamicprice', 'edit', 'ellipsis-h', 'email', 'entity', 'envelope', 'eraser', 'establishment', 'expensereport', 'external-link-alt', 'external-link-square-alt', 'eye', 'filter', 'file-code', 'file-export', 'file-import', 'file-upload', 'autofill', 'folder', 'folder-open', 'folder-plus', - 'generate', 'globe', 'globe-americas', 'graph', 'grip', 'grip_title', 'group', + 'gears', 'generate', 'globe', 'globe-americas', 'graph', 'grip', 'grip_title', 'group', 'help', 'holiday', 'images', 'incoterm', 'info', 'intervention', 'inventory', 'intracommreport', 'knowledgemanagement', 'label', 'language', 'line', 'link', 'list', 'list-alt', 'listlight', 'loan', 'lock', 'lot', 'long-arrow-alt-right', diff --git a/htdocs/hrm/job_list.php b/htdocs/hrm/job_list.php index ed0fb480a3a..6cb1a4bf62c 100644 --- a/htdocs/hrm/job_list.php +++ b/htdocs/hrm/job_list.php @@ -115,11 +115,11 @@ $arrayfields = array(); foreach ($object->fields as $key => $val) { // If $val['visible']==0, then we never show the field if (!empty($val['visible'])) { - $visible = (int) dol_eval($val['visible'], 1, 1, '1'); + $visible = (int) dol_eval($val['visible'], 1); $arrayfields['t.'.$key] = array( 'label'=>$val['label'], 'checked'=>(($visible < 0) ? 0 : 1), - 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1, 1, '1')), + 'enabled'=>(abs($visible) != 3 && dol_eval($val['enabled'], 1)), 'position'=>$val['position'], 'help'=> isset($val['help']) ? $val['help'] : '' ); @@ -136,18 +136,15 @@ $permissiontoread = $user->rights->hrm->all->read; $permissiontoadd = $user->rights->hrm->all->write; $permissiontodelete = $user->rights->hrm->all->delete; -// Security check -if (empty($conf->hrm->enabled)) { - accessforbidden('Module not enabled'); -} - // Security check (enable the most restrictive one) if ($user->socid > 0) accessforbidden(); //if ($user->socid > 0) accessforbidden(); //$socid = 0; if ($user->socid > 0) $socid = $user->socid; //$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); //restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); -if (empty($conf->hrm->enabled)) accessforbidden(); +if (!isModEnabled('hrm')) { + accessforbidden('Module hrm not enabled'); +} if (!$permissiontoread) accessforbidden(); @@ -256,17 +253,17 @@ foreach ($search as $key => $val) { $mode_search = 2; } if ($search[$key] != '') { - $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); + $sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search)); } } else { if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') { $columnName=preg_replace('/(_dtstart|_dtend)$/', '', $key); if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) { if (preg_match('/_dtstart$/', $key)) { - $sql .= " AND t." . $columnName . " >= '" . $db->idate($search[$key]) . "'"; + $sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'"; } if (preg_match('/_dtend$/', $key)) { - $sql .= " AND t." . $columnName . " <= '" . $db->idate($search[$key]) . "'"; + $sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'"; } } } @@ -286,7 +283,7 @@ $sql .= $hookmanager->resPrint; /* If a group by is required $sql .= " GROUP BY "; foreach($object->fields as $key => $val) { - $sql .= "t.".$key.", "; + $sql .= "t.".$db->escape($key).", "; } // Add fields from extrafields if (!empty($extrafields->attributes[$object->table_element]['label'])) { @@ -301,8 +298,6 @@ $sql .= $hookmanager->resPrint; $sql = preg_replace('/,\s*$/', '', $sql); */ -$sql .= $db->order($sortfield, $sortorder); - // Count total nb of records $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { @@ -312,24 +307,24 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { $page = 0; $offset = 0; } + $db->free($resql); } -// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set. -if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit))) { - $num = $nbtotalofrecords; -} else { - if ($limit) { - $sql .= $db->plimit($limit + 1, $offset); - } - $resql = $db->query($sql); - if (!$resql) { - dol_print_error($db); - exit; - } - - $num = $db->num_rows($resql); +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); } +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + + // 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); @@ -362,6 +357,9 @@ llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', ''); $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); } @@ -369,11 +367,17 @@ if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } foreach ($search as $key => $val) { - if (is_array($search[$key]) && count($search[$key])) { + if (is_array($search[$key])) { foreach ($search[$key] as $skey) { - $param .= '&search_'.$key.'[]='.urlencode($skey); + if ($skey != '') { + $param .= '&search_'.$key.'[]='.urlencode($skey); + } } - } else { + } elseif (preg_match('/(_dtstart|_dtend)$/', $key) && !empty($val)) { + $param .= '&search_'.$key.'month='.((int) GETPOST('search_'.$key.'month', 'int')); + $param .= '&search_'.$key.'day='.((int) GETPOST('search_'.$key.'day', 'int')); + $param .= '&search_'.$key.'year='.((int) GETPOST('search_'.$key.'year', 'int')); + } elseif ($search[$key] != '') { $param .= '&search_'.$key.'='.urlencode($search[$key]); } } @@ -394,7 +398,7 @@ $arrayofmassactions = array( //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), ); -if ($permissiontodelete) { +if (!empty($permissiontodelete)) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { @@ -413,6 +417,7 @@ print ''; print ''; print ''; print ''; +print ''; $newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/hrm/job_card.php', 1).'?action=create', '', $permissiontoadd); @@ -426,9 +431,12 @@ $trackid = 'xxxx'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; if ($search_all) { + $setupstring = ''; foreach ($fieldstosearchall as $key => $val) { $fieldstosearchall[$key] = $langs->trans($val); + $setupstring .= $key."=".$val.";"; } + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '; } @@ -452,7 +460,7 @@ if (!empty($moreforfilter)) { } $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; -$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields = $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 @@ -462,7 +470,15 @@ print '
    '; +// Action column +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} foreach ($object->fields as $key => $val) { + $searchkey = empty($search[$key]) ? '' : $search[$key]; $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if ($key == 'status') { $cssforfield .= ($cssforfield ? ' ' : '').'center'; @@ -470,7 +486,7 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } if (!empty($arrayfields['t.'.$key]['checked'])) { @@ -478,9 +494,7 @@ foreach ($object->fields as $key => $val) { if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { - print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', 'maxwidth125', 1); - } elseif (!preg_match('/^(date|timestamp|datetime)/', $val['type'])) { - print ''; + print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', $cssforfield.' maxwidth125', 1); } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { print '
    '; print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); @@ -488,6 +502,12 @@ foreach ($object->fields as $key => $val) { print '
    '; print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); print '
    '; + } elseif ($key == 'lang') { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($db); + print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth150 maxwidth200', 2); + } else { + print ''; } print ''; } @@ -500,16 +520,23 @@ $parameters = array('arrayfields'=>$arrayfields); $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -print '
    '; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; +} print ''."\n"; +$totalarray = array(); +$totalarray['nbfield'] = 0; // Fields title label // -------------------------------------------------------------------- print ''; +if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +} foreach ($object->fields as $key => $val) { $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); if ($key == 'status') { @@ -518,21 +545,26 @@ foreach ($object->fields as $key => $val) { $cssforfield .= ($cssforfield ? ' ' : '').'center'; } elseif (in_array($val['type'], array('timestamp'))) { $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $key != 'rowid' && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { $cssforfield .= ($cssforfield ? ' ' : '').'right'; } + $cssforfield = preg_replace('/small\s*/', '', $cssforfield); // the 'small' css must not be used for the title label if (!empty($arrayfields['t.'.$key]['checked'])) { print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + $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); +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray); $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; // Action column -print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print getTitleFieldOfList(($mode != 'kanban' ? $selectedfields : ''), 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +} +$totalarray['nbfield']++; print ''."\n"; @@ -550,9 +582,11 @@ if (isset($extrafields->attributes[$object->table_element]['computed']) && is_ar // 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 @@ -561,77 +595,109 @@ while ($i < ($limit ? min($num, $limit) : $num)) { // Store properties in $object $object->setVarsFromFetchObj($obj); - // Show here line of result - print ''; - foreach ($object->fields as $key => $val) { - $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); - if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { - $cssforfield .= ($cssforfield ? ' ' : '').'center'; - } elseif ($key == 'status') { - $cssforfield .= ($cssforfield ? ' ' : '').'center'; + if ($mode == 'kanban') { + if ($i == 0) { + print ''; } - - if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { - $cssforfield .= ($cssforfield ? ' ' : '').'right'; - } - //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; - - if (!empty($arrayfields['t.'.$key]['checked'])) { - print ''; - if ($key == 'status') { - print $object->getLibStatut(5); - } elseif ($key == 'rowid') { - print $object->showOutputField($val, $key, $object->id, ''); - } elseif ($key == 'label') { - print $object->getNomUrl(1); - } else { - print $object->showOutputField($val, $key, $object->$key, ''); + } else { + // Show here line of result + $j = 0; + print ''; + // Action column + if (!empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; - if (!$i) { - $totalarray['nbfield']++; - } - if (!empty($val['isameasure']) && $val['isameasure'] == 1) { - if (!$i) { - $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; - } - if (!isset($totalarray['val'])) { - $totalarray['val'] = array(); - } - if (!isset($totalarray['val']['t.'.$key])) { - $totalarray['val']['t.'.$key] = 0; - } - $totalarray['val']['t.'.$key] += $object->$key; - } } - } - // Extra fields - 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; - // Action column - print ''; - if (!$i) { - $totalarray['nbfield']++; - } + foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } - print ''."\n"; + if (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif ($key == 'ref') { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + if ($key == 'status') { + print $object->getLibStatut(5); + } elseif ($key == 'rowid') { + print $object->showOutputField($val, $key, $object->id, ''); + } elseif ($key == 'label') { + print $object->getNomUrl(1); + } else { + print $object->showOutputField($val, $key, $object->$key, ''); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + } + if (!isset($totalarray['val'])) { + $totalarray['val'] = array(); + } + if (!isset($totalarray['val']['t.'.$key])) { + $totalarray['val']['t.'.$key] = 0; + } + $totalarray['val']['t.'.$key] += $object->$key; + } + } + } + // Extra fields + 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; + // Action column + if (empty($conf->global->MAIN_CHECKBOX_LEFT_COLUMN)) { + print ''; + } + if (!$i) { + $totalarray['nbfield']++; + } + + print ''."\n"; + } $i++; } @@ -647,14 +713,14 @@ if ($num == 0) { $colspan++; } } - print ''; + print ''; } $db->free($resql); $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); -$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; print '
    '; + $searchpicto = $form->showFilterButtons('left'); + print $searchpicto; + print ''; -$searchpicto = $form->showFilterButtons(); -print $searchpicto; -print ''; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
    '; + print '
    '; } - - if (in_array($val['type'], array('timestamp'))) { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; - } elseif ($key == 'ref') { - $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + // Output Kanban + print $object->getKanbanView(''); + if ($i == ($imaxinloop - 1)) { + 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($object->id, $arrayofselected)) { + $selected = 1; + } + 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($object->id, $arrayofselected)) { - $selected = 1; - } - 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($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
    '.$langs->trans("NoRecordFound").'
    '.$langs->trans("NoRecordFound").'
    '."\n"; From 87d9b8075bb88d8a12fb2a82a45f96c7be42514e Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Tue, 24 Jan 2023 20:40:16 +0100 Subject: [PATCH 754/816] fix error style --- htdocs/hrm/position_list.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/hrm/position_list.php b/htdocs/hrm/position_list.php index de86b3d41c5..4518d28bf65 100644 --- a/htdocs/hrm/position_list.php +++ b/htdocs/hrm/position_list.php @@ -247,7 +247,6 @@ if ($object->ismultientitymanaged == 1) { } else { $sql .= " WHERE 1 = 1"; } -$sql .= " AND t.fk_user = u.rowid"; $sql .= " AND t.fk_job = j.rowid"; foreach ($search as $key => $val) { if (array_key_exists($key, $object->fields)) { From 373c8d83df1c50cea5270b126c35af984a1966ba Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Jan 2023 23:26:17 +0100 Subject: [PATCH 755/816] Doc --- htdocs/core/class/commoninvoice.class.php | 8 +++++--- htdocs/stripe/class/stripe.class.php | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 17c9c7deae3..cb737a8bdd4 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -1079,10 +1079,12 @@ abstract class CommonInvoice extends CommonObject if ($companypaymentmode->type == 'ban') { $sepaMode = true; // Check into societe_rib if a payment mode for Stripe and ban payment exists + // To make a Stripe SEPA payment request, we must have the payment mode source already saved into societe_rib and retreived with ->sepaStripe + // The payment mode source is created when we create the bank account on Stripe with paymentmodes.php?action=create $stripecard = $stripe->sepaStripe($customer, $companypaymentmode, $stripeacc, $servicestatus, 0); } - if ($stripecard) { // Can be src_... (for sepa). Note that card_... (old card mode) or pm_... (new card mode) should not happen here. + if ($stripecard) { // Can be src_... (for sepa) or pm_... (new card mode). Note that card_... (old card mode) should not happen here. $FULLTAG = 'INV=' . $this->id . '-CUS=' . $thirdparty->id; $description = 'Stripe payment from makeStripeSepaRequest: ' . $FULLTAG . ' ref=' . $this->ref; @@ -1097,7 +1099,7 @@ abstract class CommonInvoice extends CommonObject $paymentintent = $stripe->getPaymentIntent($amounttopay, $currency, $FULLTAG, $description, $this, $customer->id, $stripeacc, $servicestatus, 0, 'automatic', true, $stripecard->id, 1); $charge = new stdClass(); - //erics add processing sepa is like success ? + if ($paymentintent->status === 'succeeded' || $paymentintent->status === 'processing') { $charge->status = 'ok'; $charge->id = $paymentintent->id; @@ -1185,7 +1187,7 @@ abstract class CommonInvoice extends CommonObject $description = 'Stripe payment request OK (' . $charge->id . ') from makeStripeSepaRequest: ' . $FULLTAG; - // TODO Save request to status pending. Done should be set with a webhook. + // @TODO LMR Save request to status pending instead of done. Done should be set with a webhook. $db = $this->db; diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 6a6ad66a96a..bc98a085d08 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -1013,8 +1013,8 @@ class Stripe extends CommonObject $s = new \Stripe\StripeClient($stripeacc); - // TODO Deprecated with the new Stripe API and SCA. - // TODO Replace ->create() and ->createSource() and replace with ->getSetupIntent() to get a Payment mode with $payment_method = \Stripe\PaymentMethod::retrieve($setupintent->payment_method); ? + // TODO LMR Deprecated with the new Stripe API and SCA. + // TODO LMR Replace ->create() and ->createSource() and replace with ->getSetupIntent() to then, get the Payment mode with $payment_method = \Stripe\PaymentMethod::retrieve($setupintent->payment_method); ? $sepa = $s->sources->create($dataforcard); if (!$sepa) { $this->error = 'Creation of sepa_debit on Stripe has failed'; From fe8a870f5a4dadb581c10433daba81b3e4feb21d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 25 Jan 2023 09:51:18 +0100 Subject: [PATCH 756/816] Add TODO --- htdocs/core/class/commoninvoice.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index cb737a8bdd4..d1eb324cc7f 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -1175,9 +1175,9 @@ abstract class CommonInvoice extends CommonObject $postactionmessages[] = $errmsg . ' (' . $stripearrayofkeys['publishable_key'] . ')'; $this->errors[] = $errmsg; } else { - dol_syslog('Successfuly charge direct debit ' . $stripecard->id); + dol_syslog('Successfuly request direct debit ' . $stripecard->id); - $postactionmessages[] = 'Success to charge direct debit (' . $charge->id . ' with ' . $stripearrayofkeys['publishable_key'] . ')'; + $postactionmessages[] = 'Success to request direct debit (' . $charge->id . ' with ' . $stripearrayofkeys['publishable_key'] . ')'; // Save a stripe payment was done in realy life so later we will be able to force a commit on recorded payments // even if in batch mode (method doTakePaymentStripe), we will always make all action in one transaction with a forced commit. @@ -1229,6 +1229,7 @@ abstract class CommonInvoice extends CommonObject $ispostactionok = 1; // Creation of payment line + // TODO LMR This must be move into the stripe server listening hooks public/stripe/ipn.php include_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php'; $paiement = new Paiement($this->db); $paiement->datepaye = $now; From ae118f2109b171f28bef55b6205df209b56d1423 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 25 Jan 2023 14:48:41 +0100 Subject: [PATCH 757/816] Clean code --- htdocs/contrat/list.php | 51 ++++++++++++------- .../modulebuilder/template/myobject_list.php | 2 +- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php index 7ea26bf6f1b..ce3ac212b68 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -63,7 +63,7 @@ $search_type_thirdparty = GETPOST("search_type_thirdparty", 'int'); $search_contract = GETPOST('search_contract', 'alpha'); $search_ref_customer = GETPOST('search_ref_customer', 'alpha'); $search_ref_supplier = GETPOST('search_ref_supplier', 'alpha'); -$sall = (GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'); +$search_all = (GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'); $search_status = GETPOST('search_status', 'alpha'); $socid = GETPOST('socid', 'int'); $search_user = GETPOST('search_user', 'int'); @@ -167,9 +167,12 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; $object->fields = dol_sort_array($object->fields, 'position'); $arrayfields = dol_sort_array($arrayfields, 'position'); +$permissiontoread = $user->rights->contrat->lire; +$permissiontodelete = $user->rights->contrat->supprimer; + /* - * Action + * Actions */ if (GETPOST('cancel', 'alpha')) { @@ -213,7 +216,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_date_endyear = ''; $search_date_start = ''; $search_date_end = ''; - $sall = ""; + $search_all = ""; $search_status = ""; $toselect = array(); $search_type_thirdparty = ''; @@ -224,8 +227,6 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' if (empty($reshook)) { $objectclass = 'Contrat'; $objectlabel = 'Contracts'; - $permissiontoread = $user->rights->contrat->lire; - $permissiontodelete = $user->rights->contrat->supprimer; $uploaddir = $conf->contrat->dir_output; include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; } @@ -265,6 +266,9 @@ if (!empty($extrafields->attributes[$object->table_element]['label'])) { $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; + +$sqlfields = $sql; // $sql fields to remove for count total + $sql .= " FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_typent as typent on (typent.id = s.fk_typent)"; @@ -325,8 +329,8 @@ if ($search_country && $search_country != '-1') { if ($search_sale > 0) { $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $search_sale); } -if ($sall) { - $sql .= natural_search(array_keys($fieldstosearchall), $sall); +if ($search_all) { + $sql .= natural_search(array_keys($fieldstosearchall), $search_all); } if ($search_user > 0) { $sql .= " AND ec.fk_c_type_contact = tc.rowid AND tc.element='contrat' AND tc.source='internal' AND ec.element_id = c.rowid AND ec.fk_socpeople = ".((int) $search_user); @@ -456,13 +460,17 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { } } } else { - $sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/Ui', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql); - $sqlforcount = preg_replace('/LEFT JOIN '.MAIN_DB_PREFIX.'contratdet as cd ON c.rowid = cd.fk_contrat/', '', $sqlforcount); + /* 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); - $objforcount = $db->fetch_object($resql); - $nbtotalofrecords = $objforcount->nbtotalofrecords; + if ($resql) { + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + } else { + dol_print_error($db); + } } if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 @@ -485,7 +493,7 @@ if (!$resql) { $num = $db->num_rows($resql); // Direct jump if only one record found -if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $sall && !$page) { +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.'/contrat/card.php?id='.$id); @@ -520,8 +528,8 @@ if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.urlencode($limit); } -if ($sall != '') { - $param .= '&sall='.urlencode($sall); +if ($search_all != '') { + $param .= '&search_all='.urlencode($search_all); } if ($search_contract != '') { $param .= '&search_contract='.urlencode($search_contract); @@ -598,10 +606,10 @@ $arrayofmassactions = array( 'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), 'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), ); -if ($user->rights->contrat->supprimer) { +if (!empty($permissiontodelete)) { $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); } -if (in_array($massaction, array('presend', 'predelete'))) { +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { $arrayofmassactions = array(); } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); @@ -615,7 +623,7 @@ $newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars i $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')); $newcardbutton .= dolGetButtonTitle($langs->trans('NewContractSubscription'), '', 'fa fa-plus-circle', $url, '', $user->rights->contrat->creer); -print ''; +print ''; if ($optioncss != '') { print ''; } @@ -624,7 +632,9 @@ print ''; print ''; print ''; +print ''; print ''; +print ''; print ''; print_barre_liste($langs->trans("Contracts"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'contract', 0, $newcardbutton, '', $limit, 0, 0, 1); @@ -635,11 +645,14 @@ $objecttmp = new Contrat($db); $trackid = 'con'.$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 = ''; diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 58231ee7de5..e9a33177f67 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -527,7 +527,7 @@ $moreforfilter.= $langs->trans('MyFilter') . ': '."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index e9a33177f67..88775b823f5 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -517,7 +517,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } From d0e9290dafaed4b781425b0d23da6a7bf4339413 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 25 Jan 2023 15:27:10 +0100 Subject: [PATCH 759/816] NEW An external module can modify the quick search fields --- htdocs/bom/bom_list.php | 2 +- htdocs/bookcal/availabilities_list.php | 2 +- htdocs/bookcal/booking_list.php | 2 +- .../compta/cashcontrol/cashcontrol_list.php | 2 +- htdocs/contrat/class/contrat.class.php | 9 ++++---- htdocs/contrat/list.php | 23 ++++++++++++------- .../conferenceorbooth_list.php | 2 +- .../knowledgerecord_list.php | 2 +- .../modulebuilder/template/myobject_list.php | 9 +++++++- htdocs/partnership/partnership_list.php | 2 +- .../recruitmentcandidature_list.php | 2 +- htdocs/ticket/list.php | 2 +- htdocs/user/group/list.php | 2 +- 13 files changed, 38 insertions(+), 23 deletions(-) diff --git a/htdocs/bom/bom_list.php b/htdocs/bom/bom_list.php index 601eb9b75b3..c5e5491dff8 100644 --- a/htdocs/bom/bom_list.php +++ b/htdocs/bom/bom_list.php @@ -517,7 +517,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/bookcal/availabilities_list.php b/htdocs/bookcal/availabilities_list.php index 26d66ce0ca4..414faf2dc5a 100644 --- a/htdocs/bookcal/availabilities_list.php +++ b/htdocs/bookcal/availabilities_list.php @@ -470,7 +470,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/bookcal/booking_list.php b/htdocs/bookcal/booking_list.php index 2e4fbfccd16..3c78ffea120 100644 --- a/htdocs/bookcal/booking_list.php +++ b/htdocs/bookcal/booking_list.php @@ -470,7 +470,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/compta/cashcontrol/cashcontrol_list.php b/htdocs/compta/cashcontrol/cashcontrol_list.php index a1e5dae0c91..05612f54166 100644 --- a/htdocs/compta/cashcontrol/cashcontrol_list.php +++ b/htdocs/compta/cashcontrol/cashcontrol_list.php @@ -423,7 +423,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 4d08fdb96cd..bf945eeae96 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -225,9 +225,10 @@ class Contrat extends CommonObject */ public $fields = array( 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10), - 'ref' =>array('type'=>'varchar(50)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>-1, 'showoncombobox'=>1, 'position'=>15), + 'ref' =>array('type'=>'varchar(50)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>-1, 'showoncombobox'=>1, 'position'=>15, 'searchall'=>1), 'ref_ext' =>array('type'=>'varchar(255)', 'label'=>'Ref ext', 'enabled'=>1, 'visible'=>0, 'position'=>20), - 'ref_supplier' =>array('type'=>'varchar(50)', 'label'=>'Ref supplier', 'enabled'=>1, 'visible'=>-1, 'position'=>25), + 'ref_customer' =>array('type'=>'varchar(50)', 'label'=>'RefCustomer', 'enabled'=>1, 'visible'=>-1, 'position'=>25, 'searchall'=>1), + 'ref_supplier' =>array('type'=>'varchar(50)', 'label'=>'RefSupplier', 'enabled'=>1, 'visible'=>-1, 'position'=>26, 'searchall'=>1), 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>30, 'index'=>1), 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35), 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>40), @@ -237,8 +238,8 @@ class Contrat extends CommonObject 'fk_commercial_signature' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'SaleRepresentative Signature', 'enabled'=>1, 'visible'=>-1, 'position'=>80), 'fk_commercial_suivi' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'SaleRepresentative follower', 'enabled'=>1, 'visible'=>-1, 'position'=>85), 'fk_user_author' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>90), - 'note_public' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>105), - 'note_private' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>110), + 'note_public' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>105, 'searchall'=>1), + 'note_private' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>110, 'searchall'=>1), 'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>1, 'visible'=>0, 'position'=>115), 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>120), 'extraparams' =>array('type'=>'varchar(255)', 'label'=>'Extraparams', 'enabled'=>1, 'visible'=>-1, 'position'=>125), diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php index f24bbad4a85..31d489c4b1f 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -133,16 +133,23 @@ $extrafields->fetch_name_optionals_label($object->table_element); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); // List of fields to search into when doing a "search in all" -$fieldstosearchall = array( - 'c.ref'=>'Ref', - 'c.ref_customer'=>'RefCustomer', - 'c.ref_supplier'=>'RefSupplier', - 's.nom'=>"ThirdParty", - 'c.note_public'=>'NotePublic', -); +$fieldstosearchall = array(); +foreach ($object->fields as $key => $val) { + if (!empty($val['searchall'])) { + $fieldstosearchall['c.'.$key] = $val['label']; + } +} +$fieldstosearchall["s.nom"] = "ThirdParty"; if (empty($user->socid)) { $fieldstosearchall["c.note_private"] = "NotePrivate"; } +$parameters = array('fieldstosearchall'=>$fieldstosearchall); +$reshook = $hookmanager->executeHooks('completeFieldsToSearchAll', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook > 0) { + $fieldstosearchall = $hookmanager->resArray['fieldstosearchall']; +} elseif ($reshook == 0) { + $fieldstosearchall = array_merge($fieldstosearchall, $hookmanager->resArray['fieldstosearchall']); +} $arrayfields = array( 'c.ref'=>array('label'=>$langs->trans("Ref"), 'checked'=>1, 'position'=>10), @@ -651,7 +658,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/eventorganization/conferenceorbooth_list.php b/htdocs/eventorganization/conferenceorbooth_list.php index 21172d774d9..06fb65a8b10 100644 --- a/htdocs/eventorganization/conferenceorbooth_list.php +++ b/htdocs/eventorganization/conferenceorbooth_list.php @@ -721,7 +721,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/knowledgemanagement/knowledgerecord_list.php b/htdocs/knowledgemanagement/knowledgerecord_list.php index 7f3e3cec2c1..7cd5a24c764 100644 --- a/htdocs/knowledgemanagement/knowledgerecord_list.php +++ b/htdocs/knowledgemanagement/knowledgerecord_list.php @@ -469,7 +469,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 88775b823f5..66aa7b0b35e 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -118,7 +118,7 @@ $pagenext = $page + 1; $object = new MyObject($db); $extrafields = new ExtraFields($db); $diroutputmassaction = $conf->mymodule->dir_output.'/temp/massgeneration/'.$user->id; -$hookmanager->initHooks(array('myobjectlist')); // Note that conf->hooks_modules contains array +$hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array of activated contexes // Fetch optionals attributes and labels $extrafields->fetch_name_optionals_label($object->table_element); @@ -155,6 +155,13 @@ foreach ($object->fields as $key => $val) { $fieldstosearchall['t.'.$key] = $val['label']; } } +$parameters = array('fieldstosearchall'=>$fieldstosearchall); +$reshook = $hookmanager->executeHooks('completeFieldsToSearchAll', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook > 0) { + $fieldstosearchall = $hookmanager->resArray['fieldstosearchall']; +} elseif ($reshook == 0) { + $fieldstosearchall = array_merge($fieldstosearchall, $hookmanager->resArray['fieldstosearchall']); +} // Definition of array of fields for columns $arrayfields = array(); diff --git a/htdocs/partnership/partnership_list.php b/htdocs/partnership/partnership_list.php index a795d8d33f4..7144f201022 100644 --- a/htdocs/partnership/partnership_list.php +++ b/htdocs/partnership/partnership_list.php @@ -664,7 +664,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/recruitment/recruitmentcandidature_list.php b/htdocs/recruitment/recruitmentcandidature_list.php index aff8c86a955..95b6ac6203d 100644 --- a/htdocs/recruitment/recruitmentcandidature_list.php +++ b/htdocs/recruitment/recruitmentcandidature_list.php @@ -571,7 +571,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index 1d2cefaf622..f3e2c82d703 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -782,7 +782,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } diff --git a/htdocs/user/group/list.php b/htdocs/user/group/list.php index 7e707b6b4fc..b0327eebe08 100644 --- a/htdocs/user/group/list.php +++ b/htdocs/user/group/list.php @@ -285,7 +285,7 @@ if ($search_all) { $fieldstosearchall[$key] = $langs->trans($val); $setupstring .= $key."=".$val.";"; } - print ''."\n"; + print ''."\n"; print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '."\n"; } From e8c2c6b6999f2ef060565c92f0e971d1de0a2ca5 Mon Sep 17 00:00:00 2001 From: kkhelifa Date: Wed, 25 Jan 2023 15:28:34 +0100 Subject: [PATCH 760/816] FIX: Rights on action for payments by bank transfer --- htdocs/compta/prelevement/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/prelevement/card.php b/htdocs/compta/prelevement/card.php index c9f90b8b240..33a4409bac9 100644 --- a/htdocs/compta/prelevement/card.php +++ b/htdocs/compta/prelevement/card.php @@ -272,7 +272,7 @@ if ($id > 0 || $ref) { print $formconfirm; - if (empty($object->date_trans) && $user->rights->prelevement->bons->send && $action == 'settransmitted') { + if (empty($object->date_trans) && (($user->rights->prelevement->bons->send && $object->type != 'bank-transfer') || ($user->rights->paymentbybanktransfer->send && $object->type == 'bank-transfer')) && $action == 'settransmitted') { print ''; print ''; print ''; @@ -291,7 +291,7 @@ if ($id > 0 || $ref) { print '
    '; } - if (!empty($object->date_trans) && empty($object->date_credit) && $user->rights->prelevement->bons->credit && $action == 'setcredited') { + if (!empty($object->date_trans) && empty($object->date_credit) && (($user->rights->prelevement->bons->credit && $object->type != 'bank-transfer') || ($user->rights->paymentbybanktransfer->debit && $object->type == 'bank-transfer')) && $action == 'setcredited') { $btnLabel = ($object->type == 'bank-transfer') ? $langs->trans("ClassDebited") : $langs->trans("ClassCredited"); print ''; print ''; From 79b7b106fc1f1fdf6baf93bb5c1fe42c9a7c8c14 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 25 Jan 2023 15:35:09 +0100 Subject: [PATCH 761/816] FIX - PHP8 Warnning admin commande --- htdocs/admin/commande.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php index 79c42f6e2db..20064ca099c 100644 --- a/htdocs/admin/commande.php +++ b/htdocs/admin/commande.php @@ -117,7 +117,7 @@ if ($action == 'updateMask') { } elseif ($action == 'del') { $ret = delDocumentModel($value, $type); if ($ret > 0) { - if ($conf->global->COMMANDE_ADDON_PDF == "$value") { + if (getDolGlobalString('COMMANDE_ADDON_PDF') == $value) { dolibarr_del_const($db, 'COMMANDE_ADDON_PDF', $conf->entity); } } From 4e289bf5baf343a10db140561e8b90587aa0fa2a Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Wed, 25 Jan 2023 15:36:47 +0100 Subject: [PATCH 762/816] next --- htdocs/admin/commande.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/commande.php b/htdocs/admin/commande.php index 20064ca099c..b366ea928ef 100644 --- a/htdocs/admin/commande.php +++ b/htdocs/admin/commande.php @@ -461,7 +461,7 @@ foreach ($dirmodels as $reldir) { // Default print '
    '; - if ($conf->global->COMMANDE_ADDON_PDF == $name) { + if (getDolGlobalString('COMMANDE_ADDON_PDF') == $name) { print img_picto($langs->trans("Default"), 'on'); } else { print 'scandir).'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; From 8c7f0e8e93739e2781d3cce2ab9a8ed8fe7f5efe Mon Sep 17 00:00:00 2001 From: hystepik Date: Wed, 25 Jan 2023 16:06:41 +0100 Subject: [PATCH 763/816] fix travis --- htdocs/reception/contact.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/reception/contact.php b/htdocs/reception/contact.php index 11ab664c6c0..97d6d19a4f9 100644 --- a/htdocs/reception/contact.php +++ b/htdocs/reception/contact.php @@ -72,7 +72,7 @@ if ($origin == 'reception') { } else { if ($origin == 'supplierorder' || $origin == 'order_supplier') { $result = restrictedArea($user, 'fournisseur', $origin_id, 'commande_fournisseur', 'commande'); - } elseif (empty($user->hasRight($origin, "lire")) && empty($user->hasRight($origin, "read"))) { + } elseif (!$user->hasRight($origin, "lire") && !$user->hasRight($origin, "read")) { accessforbidden(); } } From 8c0c69c4952ebb4c73ef4d416aa7278d06f51ecd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 25 Jan 2023 16:38:05 +0100 Subject: [PATCH 764/816] Debug set/edit date/end of contrat lines --- htdocs/contrat/card.php | 61 +++++++++++--------------- htdocs/contrat/class/contrat.class.php | 14 +++--- 2 files changed, 32 insertions(+), 43 deletions(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index b29f001bda2..54779bb692d 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -143,7 +143,16 @@ if (empty($reshook)) { include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be include, not include_once if ($action == 'confirm_active' && $confirm == 'yes' && $user->rights->contrat->activer) { - $result = $object->active_line($user, GETPOST('ligne', 'int'), GETPOST('date'), GETPOST('dateend'), GETPOST('comment')); + $date_start = ''; + $date_end = ''; + if (GETPOST('startmonth') && GETPOST('startday') && GETPOST('startyear')) { + $date_start = dol_mktime(GETPOST('starthour'), GETPOST('startmin'), 0, GETPOST('startmonth'), GETPOST('startday'), GETPOST('startyear')); + } + if (GETPOST('endmonth') && GETPOST('endday') && GETPOST('endyear')) { + $date_end = dol_mktime(GETPOST('endhour'), GETPOST('endmin'), 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear')); + } + + $result = $object->active_line($user, GETPOST('ligne', 'int'), $date_start, $date_end, GETPOST('comment')); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); @@ -152,12 +161,16 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'confirm_closeline' && $confirm == 'yes' && $user->rights->contrat->activer) { - if (!GETPOST('dateend')) { + $date_end = ''; + if (GETPOST('endmonth') && GETPOST('endday') && GETPOST('endyear')) { + $date_end = dol_mktime(GETPOST('endhour'), GETPOST('endmin'), 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear')); + } + if (!$date_end) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateEnd")), null, 'errors'); } if (!$error) { - $result = $object->close_line($user, GETPOST('ligne', 'int'), GETPOST('dateend'), urldecode(GETPOST('comment'))); + $result = $object->close_line($user, GETPOST('ligne', 'int'), $date_end, urldecode(GETPOST('comment'))); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); exit; @@ -1838,34 +1851,6 @@ if ($action == 'create') { print '
    '; } - /* - * Confirmation de la validation activation - */ - if ($action == 'active' && !$cancel && $user->rights->contrat->activer && $object->lines[$cursorline - 1]->id == GETPOST('ligne', 'int')) { - $dateactstart = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); - $dateactend = dol_mktime(12, 0, 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear')); - $comment = GETPOST('comment', 'alpha'); - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id."&ligne=".GETPOST('ligne', 'int')."&date=".$dateactstart."&dateend=".$dateactend."&comment=".urlencode($comment), $langs->trans("ActivateService"), $langs->trans("ConfirmActivateService", dol_print_date($dateactstart, "%A %d %B %Y")), "confirm_active", '', 0, 1); - print '
    '; - } - - /* - * Confirmation de la validation fermeture - */ - if ($action == 'closeline' && !$cancel && $user->rights->contrat->activer && $object->lines[$cursorline - 1]->id == GETPOST('ligne', 'int')) { - $dateactstart = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); - $dateactend = dol_mktime(12, 0, 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear')); - $comment = GETPOST('comment', 'alpha'); - - if (empty($dateactend)) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateEndReal")), null, 'errors'); - } else { - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id."&ligne=".GETPOST('ligne', 'int')."&date=".$dateactstart."&dateend=".$dateactend."&comment=".urlencode($comment), $langs->trans("CloseService"), $langs->trans("ConfirmCloseService", dol_print_date($dateactend, "%A %d %B %Y")), "confirm_closeline", '', 0, 1); - } - print '
    '; - } - - // Area with status and activation info of line if ($object->statut > 0) { print ''; @@ -1931,8 +1916,12 @@ if ($action == 'create') { // Form to activate line if ($user->rights->contrat->activer && $action == 'activateline' && $object->lines[$cursorline - 1]->id == GETPOST('ligne', 'int')) { - print ''; + print ''; print ''; + print ''; + print ''; + print ''; + print ''; print '
    '; @@ -1957,7 +1946,7 @@ if ($action == 'create') { print ''; print ''; print '
    '.$langs->trans("DateServiceActivate").''; - print $form->selectDate($dateactstart, '', $usehm, $usehm, '', "active", 1, 0); + print $form->selectDate($dateactstart, 'start', $usehm, $usehm, '', "active", 1, 0); print ''.$langs->trans("DateEndPlanned").''; print $form->selectDate($dateactend, "end", $usehm, $usehm, '', "active", 1, 0); @@ -1985,10 +1974,10 @@ if ($action == 'create') { * Disable a contract line */ print ''."\n"; - print ''; - + print ''; print ''; - print ''; + print ''; + print ''; print ''; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index bf945eeae96..0357459052b 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -321,15 +321,15 @@ class Contrat extends CommonObject * * @param User $user Objet User who activate contract * @param int $line_id Id of line to activate - * @param int $date Opening date + * @param int $date_start Opening date * @param int|string $date_end Expected end date * @param string $comment A comment typed by user * @return int <0 if KO, >0 if OK */ - public function active_line($user, $line_id, $date, $date_end = '', $comment = '') + public function active_line($user, $line_id, $date_start, $date_end = '', $comment = '') { // phpcs:enable - $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->active_line($user, $date, $date_end, $comment); + $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->active_line($user, $date_start, $date_end, $comment); if ($result < 0) { $this->error = $this->lines[$this->lines_id_index_mapper[$line_id]]->error; $this->errors = $this->lines[$this->lines_id_index_mapper[$line_id]]->errors; @@ -3588,7 +3588,7 @@ class ContratLigne extends CommonObjectLine * Activate a contract line * * @param User $user Objet User who activate contract - * @param int $date Date activation + * @param int $date Date real activation * @param int|string $date_end Date planned end. Use '-1' to keep it unchanged. * @param string $comment A comment typed by user * @return int <0 if KO, >0 if OK @@ -3603,13 +3603,13 @@ class ContratLigne extends CommonObjectLine $this->db->begin(); $this->statut = ContratLigne::STATUS_OPEN; - $this->date_start = $date; + $this->date_start_real = $date; $this->date_end = $date_end; $this->fk_user_ouverture = $user->id; $this->date_end_real = null; $this->commentaire = $comment; - $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET statut = ".$this->statut.","; + $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET statut = ".((int) $this->statut).","; $sql .= " date_ouverture = ".(dol_strlen($this->date_start_real) != 0 ? "'".$this->db->idate($this->date_start_real)."'" : "null").","; if ($date_end >= 0) { $sql .= " date_fin_validite = ".(dol_strlen($this->date_end) != 0 ? "'".$this->db->idate($this->date_end)."'" : "null").","; @@ -3648,7 +3648,7 @@ class ContratLigne extends CommonObjectLine * Close a contract line * * @param User $user Objet User who close contract - * @param int $date_end_real Date end + * @param int $date_end_real Date end * @param string $comment A comment typed by user * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers * @return int <0 if KO, >0 if OK From 1d5e2bd0256a3c2ea3b204a3a0b8fd304d8c826c Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Wed, 25 Jan 2023 16:39:45 +0100 Subject: [PATCH 765/816] fix : Warning: Undefined array key xStartPos in /home/httpd/vhosts/aflac.fr/domains/dev.aflac.fr/httpdocs/core/class/commondocgenerator.class.php on line 1109 --- 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 7c136f446d9..b4eddcc252f 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -1104,7 +1104,7 @@ abstract class CommonDocGenerator public function getColumnContentXStart($colKey) { $colDef = $this->cols[$colKey]; - return $colDef['xStartPos'] + $colDef['content']['padding'][3]; + return (isset($colDef['xStartPos']) ? $colDef['xStartPos'] : 0) + $colDef['content']['padding'][3]; } /** From 3d814ac3d3fb6982e6b5cc391d721827746b64f3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 25 Jan 2023 16:38:05 +0100 Subject: [PATCH 766/816] Debug set/edit date/end of contrat lines --- htdocs/contrat/card.php | 61 +++++++++++--------------- htdocs/contrat/class/contrat.class.php | 14 +++--- 2 files changed, 32 insertions(+), 43 deletions(-) diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index db501e113fb..6b3937df76a 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -143,7 +143,16 @@ if (empty($reshook)) { include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be include, not include_once if ($action == 'confirm_active' && $confirm == 'yes' && $user->rights->contrat->activer) { - $result = $object->active_line($user, GETPOST('ligne', 'int'), GETPOST('date'), GETPOST('dateend'), GETPOST('comment')); + $date_start = ''; + $date_end = ''; + if (GETPOST('startmonth') && GETPOST('startday') && GETPOST('startyear')) { + $date_start = dol_mktime(GETPOST('starthour'), GETPOST('startmin'), 0, GETPOST('startmonth'), GETPOST('startday'), GETPOST('startyear')); + } + if (GETPOST('endmonth') && GETPOST('endday') && GETPOST('endyear')) { + $date_end = dol_mktime(GETPOST('endhour'), GETPOST('endmin'), 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear')); + } + + $result = $object->active_line($user, GETPOST('ligne', 'int'), $date_start, $date_end, GETPOST('comment')); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); @@ -152,12 +161,16 @@ if (empty($reshook)) { setEventMessages($object->error, $object->errors, 'errors'); } } elseif ($action == 'confirm_closeline' && $confirm == 'yes' && $user->rights->contrat->activer) { - if (!GETPOST('dateend')) { + $date_end = ''; + if (GETPOST('endmonth') && GETPOST('endday') && GETPOST('endyear')) { + $date_end = dol_mktime(GETPOST('endhour'), GETPOST('endmin'), 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear')); + } + if (!$date_end) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateEnd")), null, 'errors'); } if (!$error) { - $result = $object->close_line($user, GETPOST('ligne', 'int'), GETPOST('dateend'), urldecode(GETPOST('comment'))); + $result = $object->close_line($user, GETPOST('ligne', 'int'), $date_end, urldecode(GETPOST('comment'))); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id); exit; @@ -1837,34 +1850,6 @@ if ($action == 'create') { print '
    '; } - /* - * Confirmation de la validation activation - */ - if ($action == 'active' && !$cancel && $user->rights->contrat->activer && $object->lines[$cursorline - 1]->id == GETPOST('ligne', 'int')) { - $dateactstart = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); - $dateactend = dol_mktime(12, 0, 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear')); - $comment = GETPOST('comment', 'alpha'); - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id."&ligne=".GETPOST('ligne', 'int')."&date=".$dateactstart."&dateend=".$dateactend."&comment=".urlencode($comment), $langs->trans("ActivateService"), $langs->trans("ConfirmActivateService", dol_print_date($dateactstart, "%A %d %B %Y")), "confirm_active", '', 0, 1); - print '
    '; - } - - /* - * Confirmation de la validation fermeture - */ - if ($action == 'closeline' && !$cancel && $user->rights->contrat->activer && $object->lines[$cursorline - 1]->id == GETPOST('ligne', 'int')) { - $dateactstart = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); - $dateactend = dol_mktime(12, 0, 0, GETPOST('endmonth'), GETPOST('endday'), GETPOST('endyear')); - $comment = GETPOST('comment', 'alpha'); - - if (empty($dateactend)) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DateEndReal")), null, 'errors'); - } else { - print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id."&ligne=".GETPOST('ligne', 'int')."&date=".$dateactstart."&dateend=".$dateactend."&comment=".urlencode($comment), $langs->trans("CloseService"), $langs->trans("ConfirmCloseService", dol_print_date($dateactend, "%A %d %B %Y")), "confirm_closeline", '', 0, 1); - } - print '
    '; - } - - // Area with status and activation info of line if ($object->statut > 0) { print ''; @@ -1930,8 +1915,12 @@ if ($action == 'create') { // Form to activate line if ($user->rights->contrat->activer && $action == 'activateline' && $object->lines[$cursorline - 1]->id == GETPOST('ligne', 'int')) { - print ''; + print ''; print ''; + print ''; + print ''; + print ''; + print ''; print '
    '; @@ -1956,7 +1945,7 @@ if ($action == 'create') { print ''; print ''; print '
    '.$langs->trans("DateServiceActivate").''; - print $form->selectDate($dateactstart, '', $usehm, $usehm, '', "active", 1, 0); + print $form->selectDate($dateactstart, 'start', $usehm, $usehm, '', "active", 1, 0); print ''.$langs->trans("DateEndPlanned").''; print $form->selectDate($dateactend, "end", $usehm, $usehm, '', "active", 1, 0); @@ -1984,10 +1973,10 @@ if ($action == 'create') { * Disable a contract line */ print ''."\n"; - print ''; - + print ''; print ''; - print ''; + print ''; + print ''; print ''; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 486a647fb68..1e8f0e1f7e5 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -320,15 +320,15 @@ class Contrat extends CommonObject * * @param User $user Objet User who activate contract * @param int $line_id Id of line to activate - * @param int $date Opening date + * @param int $date_start Opening date * @param int|string $date_end Expected end date * @param string $comment A comment typed by user * @return int <0 if KO, >0 if OK */ - public function active_line($user, $line_id, $date, $date_end = '', $comment = '') + public function active_line($user, $line_id, $date_start, $date_end = '', $comment = '') { // phpcs:enable - $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->active_line($user, $date, $date_end, $comment); + $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->active_line($user, $date_start, $date_end, $comment); if ($result < 0) { $this->error = $this->lines[$this->lines_id_index_mapper[$line_id]]->error; $this->errors = $this->lines[$this->lines_id_index_mapper[$line_id]]->errors; @@ -3554,7 +3554,7 @@ class ContratLigne extends CommonObjectLine * Activate a contract line * * @param User $user Objet User who activate contract - * @param int $date Date activation + * @param int $date Date real activation * @param int|string $date_end Date planned end. Use '-1' to keep it unchanged. * @param string $comment A comment typed by user * @return int <0 if KO, >0 if OK @@ -3569,13 +3569,13 @@ class ContratLigne extends CommonObjectLine $this->db->begin(); $this->statut = ContratLigne::STATUS_OPEN; - $this->date_start = $date; + $this->date_start_real = $date; $this->date_end = $date_end; $this->fk_user_ouverture = $user->id; $this->date_end_real = null; $this->commentaire = $comment; - $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET statut = ".$this->statut.","; + $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET statut = ".((int) $this->statut).","; $sql .= " date_ouverture = ".(dol_strlen($this->date_start_real) != 0 ? "'".$this->db->idate($this->date_start_real)."'" : "null").","; if ($date_end >= 0) { $sql .= " date_fin_validite = ".(dol_strlen($this->date_end) != 0 ? "'".$this->db->idate($this->date_end)."'" : "null").","; @@ -3614,7 +3614,7 @@ class ContratLigne extends CommonObjectLine * Close a contract line * * @param User $user Objet User who close contract - * @param int $date_end_real Date end + * @param int $date_end_real Date end * @param string $comment A comment typed by user * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers * @return int <0 if KO, >0 if OK From d8ce744e4c4dc70c897775203f56f1c28c1ce588 Mon Sep 17 00:00:00 2001 From: hystepik Date: Wed, 25 Jan 2023 16:56:27 +0100 Subject: [PATCH 767/816] New : Export for module ticket --- htdocs/core/modules/modTicket.class.php | 28 +++++++++++++++++++++++++ htdocs/langs/en_US/ticket.lang | 3 +++ 2 files changed, 31 insertions(+) diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php index 37e6552af2f..ff80385235f 100644 --- a/htdocs/core/modules/modTicket.class.php +++ b/htdocs/core/modules/modTicket.class.php @@ -208,6 +208,13 @@ class modTicket extends DolibarrModules $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut $this->rights[$r][4] = 'manage'; + $r++; + $this->rights[$r][0] = 56006; // id de la permission + $this->rights[$r][1] = "Export ticket"; // libelle de la permission + //$this->rights[$r][2] = 'd'; // type de la permission (deprecie a ce jour) + $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut + $this->rights[$r][4] = 'export'; + /* Seems not used and in conflict with societe->client->voir (see all thirdparties) $r++; $this->rights[$r][0] = 56005; // id de la permission @@ -318,6 +325,27 @@ class modTicket extends DolibarrModules 'target' => '', 'user' => 0); $r++; + + // Exports + //-------- + $r = 1; + + // Export list of tickets and attributes + $langs->load("ticket"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='ExportDataset_ticket_1'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_permission[$r] = array(array("ticket", "export")); + $this->export_icon[$r]='ticket'; + $keyforclass = 'Ticket';$keyforclassfile='/ticket/class/ticket.class.php';$keyforelement='ticket'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='ticket'; $keyforaliasextra='extra'; $keyforelement='ticket'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'ticket as t'; + $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'ticket_extrafields as extra on (t.rowid = extra.fk_object)'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('ticket').')'; + $r++; } /** diff --git a/htdocs/langs/en_US/ticket.lang b/htdocs/langs/en_US/ticket.lang index ea560012afc..de54d475591 100644 --- a/htdocs/langs/en_US/ticket.lang +++ b/htdocs/langs/en_US/ticket.lang @@ -26,6 +26,7 @@ Permission56002=Modify tickets Permission56003=Delete tickets Permission56004=Manage tickets Permission56005=See tickets of all third parties (not effective for external users, always be limited to the third party they depend on) +Permission56006=Export tickets Tickets=Tickets TicketDictType=Ticket - Types @@ -61,6 +62,8 @@ TypeContact_ticket_external_CONTRIBUTOR=External contributor OriginEmail=Reporter Email Notify_TICKET_SENTBYMAIL=Send ticket message by email +ExportDataset_ticket_1=Tickets + # Status Read=Read Assigned=Assigned From 934bcc72c489799d451f0c49642728460bed1880 Mon Sep 17 00:00:00 2001 From: GregM Date: Wed, 25 Jan 2023 17:34:57 +0100 Subject: [PATCH 768/816] update space --- htdocs/core/class/html.formsetup.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index 0c9adf0be59..a7fb11e624f 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -1069,7 +1069,7 @@ class FormSetupItem } elseif ($this->type == 'yesno') { $out.= ajax_constantonoff($this->confKey); } elseif (preg_match('/emailtemplate:/', $this->type)) { - if ($this->fieldValue > 0){ + if ($this->fieldValue > 0) { include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; $formmail = new FormMail($this->db); From faa44379e81aef112835b254644ea5b49ffb28eb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 25 Jan 2023 17:38:04 +0100 Subject: [PATCH 769/816] Debug view of thumbs for svg --- htdocs/core/class/commonobject.class.php | 5 ++++- htdocs/core/lib/functions.lib.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 88fefed035f..b67f518d2af 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -8652,7 +8652,10 @@ abstract class CommonObject // Find name of thumb file $photo_vignette = basename(getImageFileNameForSize($dir.$file, '_small')); if (!dol_is_file($dirthumb.$photo_vignette)) { - $photo_vignette = ''; + // The thumb does not exists, so we will use the original file + $dirthumb = $dir; + $pdirthumb = $pdir; + $photo_vignette = basename($file); } // Get filesize of original file diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 1076d32602f..fe47ecc64d7 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -9943,7 +9943,7 @@ function showDirectDownloadLink($object) * @param string $file Original filename (full or relative path) * @param string $extName Extension to differenciate thumb file name ('', '_small', '_mini') * @param string $extImgTarget Force image extension for thumbs. Use '' to keep same extension than original image (default). - * @return string New file name (full or relative path, including the thumbs/) + * @return string New file name (full or relative path, including the thumbs/). May be the original path if no thumb can exists. */ function getImageFileNameForSize($file, $extName, $extImgTarget = '') { From dbfa172e195be8d007792aaefbfa50cbddc04f65 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 25 Jan 2023 17:38:04 +0100 Subject: [PATCH 770/816] Debug view of thumbs for svg --- htdocs/core/class/commonobject.class.php | 5 ++++- htdocs/core/lib/functions.lib.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 471d835f4a3..2c9bb0c14c0 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -8650,7 +8650,10 @@ abstract class CommonObject // Find name of thumb file $photo_vignette = basename(getImageFileNameForSize($dir.$file, '_small')); if (!dol_is_file($dirthumb.$photo_vignette)) { - $photo_vignette = ''; + // The thumb does not exists, so we will use the original file + $dirthumb = $dir; + $pdirthumb = $pdir; + $photo_vignette = basename($file); } // Get filesize of original file diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 4d38c7e5e5d..81f830d6456 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -9903,7 +9903,7 @@ function showDirectDownloadLink($object) * @param string $file Original filename (full or relative path) * @param string $extName Extension to differenciate thumb file name ('', '_small', '_mini') * @param string $extImgTarget Force image extension for thumbs. Use '' to keep same extension than original image (default). - * @return string New file name (full or relative path, including the thumbs/) + * @return string New file name (full or relative path, including the thumbs/). May be the original path if no thumb can exists. */ function getImageFileNameForSize($file, $extName, $extImgTarget = '') { From 35f16e821da3843fa93cefe5a284f9676b6501e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 25 Jan 2023 21:56:49 +0100 Subject: [PATCH 771/816] fix php8.2 warnings --- htdocs/debugbar/class/DataCollector/DolLogsCollector.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/debugbar/class/DataCollector/DolLogsCollector.php b/htdocs/debugbar/class/DataCollector/DolLogsCollector.php index 44885296bae..3d3b3b25a0e 100644 --- a/htdocs/debugbar/class/DataCollector/DolLogsCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolLogsCollector.php @@ -41,6 +41,11 @@ class DolLogsCollector extends MessagesCollector */ protected $maxnboflines; + /** + * @var int number of lines + */ + protected $nboflines; + /** * Constructor * @@ -54,7 +59,7 @@ class DolLogsCollector extends MessagesCollector parent::__construct($name); $this->nboflines = 0; - $this->maxnboflines = empty($conf->global->DEBUGBAR_LOGS_LINES_NUMBER) ? 250 : $conf->global->DEBUGBAR_LOGS_LINES_NUMBER; // High number slows seriously output + $this->maxnboflines = getDolGlobalInt('DEBUGBAR_LOGS_LINES_NUMBER', 250); // High number slows seriously output $this->path = $path ?: $this->getLogsFile(); } From 1a4cb5b4e2057f2b66254fdcaf9100abb438fe1f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 26 Jan 2023 02:06:40 +0100 Subject: [PATCH 772/816] FIX #22964 #23012 --- htdocs/core/class/commonobject.class.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 63858fa28e2..ed74194d492 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1207,7 +1207,7 @@ abstract class CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Delete all links between an object $this and all its contacts + * Delete all links between an object $this and all its contacts in llx_element_contact * * @param string $source '' or 'internal' or 'external' * @param string $code Type of contact (code or id) @@ -1224,12 +1224,16 @@ abstract class CommonObject } $listId = implode(",", $temp); - $sql = "DELETE FROM ".MAIN_DB_PREFIX."element_contact"; - $sql .= " WHERE element_id = ".((int) $this->id); - if ($listId) { - $sql .= " AND fk_c_type_contact IN (".$this->db->sanitize($listId).")"; + // If $listId is empty, we have not criteria on fk_c_type_contact so we will delete record on element_id for + // any type or record instead of only the ones of the current object. So we do nothing in such a case. + if (empty($listId)) { + return 0; } + $sql = "DELETE FROM ".$this->db->prefix()."element_contact"; + $sql .= " WHERE element_id = ".((int) $this->id); + $sql .= " AND fk_c_type_contact IN (".$this->db->sanitize($listId).")"; + dol_syslog(get_class($this)."::delete_linked_contact", LOG_DEBUG); if ($this->db->query($sql)) { return 1; From 59f163f6998d5929607528513e305e5538539332 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 26 Jan 2023 02:12:42 +0100 Subject: [PATCH 773/816] Fix regression --- htdocs/expensereport/card.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 0756cb1bc7f..0201dfdd7f6 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -1158,12 +1158,17 @@ if (empty($reshook)) { unset($date); } else { + $error++; setEventMessages($object->error, $object->errors, 'errors'); } } - header("Location: ".$_SERVER["PHP_SELF"]."?id=".GETPOST('id', 'int')); - exit; + if (!$error) { + header("Location: ".$_SERVER["PHP_SELF"]."?id=".GETPOST('id', 'int')); + exit; + } else { + $action = ''; + } } if ($action == 'confirm_delete_line' && GETPOST("confirm", 'alpha') == "yes" && $user->rights->expensereport->creer) { From 6aadb7b9ccf4150c5b1dbf45ff974cf3eb5cbea3 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 26 Jan 2023 10:36:44 +0100 Subject: [PATCH 774/816] =?UTF-8?q?FIX=20-=20Error=20to=20g=C3=A9n=C3=A9ra?= =?UTF-8?q?te=20product=20doc=20-=20NEW=20-=20Add=20photo=20on=20product?= =?UTF-8?q?=20doc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/doc/pdf_standard.modules.php | 73 ++++++++++++++----- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/htdocs/core/modules/product/doc/pdf_standard.modules.php b/htdocs/core/modules/product/doc/pdf_standard.modules.php index 8baef2ffa75..9247e8c7e34 100644 --- a/htdocs/core/modules/product/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/product/doc/pdf_standard.modules.php @@ -209,10 +209,10 @@ class pdf_standard extends ModelePDFProduct $pdf->SetDrawColor(128, 128, 128); $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); - $pdf->SetSubject($outputlangs->transnoentities("Order")); + $pdf->SetSubject($outputlangs->transnoentities("Product")); $pdf->SetCreator("Dolibarr ".DOL_VERSION); $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); - $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Order")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Product")); if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) { $pdf->SetCompression(false); } @@ -242,6 +242,53 @@ class pdf_standard extends ModelePDFProduct $pdf->writeHTMLCell(190, 3, $this->marge_gauche, $tab_top, dol_htmlentitiesbr($object->label), 0, 1); $nexY = $pdf->GetY(); + // Show photo + if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) { + $pdir[0] = get_exdir($object->id, 2, 0, 0, $object, 'product').$object->id."/photos/"; + $pdir[1] = get_exdir(0, 0, 0, 0, $object, 'product').dol_sanitizeFileName($object->ref).'/'; + } else { + $pdir[0] = get_exdir(0, 0, 0, 0, $object, 'product'); // default + $pdir[1] = get_exdir($object->id, 2, 0, 0, $object, 'product').$object->id."/photos/"; // alternative + } + + $arephoto = false; + foreach ($pdir as $midir) { + if (!$arephoto) { + if ($conf->entity != $object->entity) { + $dir = $conf->product->multidir_output[$object->entity].'/'.$midir; //Check repertories of current entities + } else { + $dir = $conf->product->dir_output.'/'.$midir; //Check repertory of the current product + } + foreach ($object->liste_photos($dir, 1) as $key => $obj) { + if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo + if ($obj['photo_vignette']) { + $filename = $obj['photo_vignette']; + } else { + $filename = $obj['photo']; + } + } else { + $filename = $obj['photo']; + } + $realpath = $dir.$filename; + $arephoto = true; + } + } + } + // Define size of image if we need it + $imglinesize = array(); + if (!empty($realpath) && $arephoto) { + $imgsize = pdf_getSizeForImage($realpath); + $imgsizewidth = $imgsize['width'] + 20; + $imgsizeheight = $imgsize['height'] + 20; + + $midelpage = ($this->page_largeur - $this->marge_gauche - $this->marge_droite) / 2; + $posxphoto = $midelpage + ($midelpage / 2) - ($imgsizewidth / 2); + $posyphoto = $tab_top - 1; + $pdf->Image($realpath, $posxphoto, $posyphoto, $imgsizewidth, $imgsizeheight, '', '', '', 2, 300); // Use 300 dpi + $nexyafterphoto = $tab_top + $imgsizeheight; + } + + // Description $pdf->SetFont('', '', $default_font_size); $pdf->writeHTMLCell(190, 3, $this->marge_gauche, $nexY, dol_htmlentitiesbr($object->description), 0, 1); $nexY = $pdf->GetY(); @@ -276,30 +323,22 @@ class pdf_standard extends ModelePDFProduct $nexY = $pdf->GetY(); } + $tab_top = 88; + if (!empty($nexyafterphoto) && $nexyafterphoto > $tab_top) { + $tab_top = $nexyafterphoto; + } + // Show notes // TODO There is no public note on product yet $notetoshow = empty($object->note_public) ? '' : $object->note_public; - if (!empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) { - // Get first sale rep - if (is_object($object->thirdparty)) { - $salereparray = $object->thirdparty->getSalesRepresentatives($user); - $salerepobj = new User($this->db); - $salerepobj->fetch($salereparray[0]['id']); - if (!empty($salerepobj->signature)) { - $notetoshow = dol_concatdesc($notetoshow, $salerepobj->signature); - } - } - } if ($notetoshow) { $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object); complete_substitutions_array($substitutionarray, $outputlangs, $object); $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs); $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow); - $tab_top = 88; - $pdf->SetFont('', '', $default_font_size - 1); - $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1); + $pdf->writeHTMLCell(190, 3, $this->marge_gauche - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1); $nexY = $pdf->GetY(); $height_note = $nexY - $tab_top; @@ -687,7 +726,7 @@ class pdf_standard extends ModelePDFProduct pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); // Show Draft Watermark - if ($object->statut == 0 && getDolGlobalString('COMMANDE_DRAFT_WATERMARK')) { + if ($object->statut == 0 && getDolGlobalString('PRODUCT_DRAFT_WATERMARK')) { pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', getDolGlobalString('COMMANDE_DRAFT_WATERMARK')); } From 2a26ca7212c177091e3e68ed91f46acde90a52cc Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 26 Jan 2023 10:40:41 +0100 Subject: [PATCH 775/816] Cop --- htdocs/core/modules/product/doc/pdf_standard.modules.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/modules/product/doc/pdf_standard.modules.php b/htdocs/core/modules/product/doc/pdf_standard.modules.php index 9247e8c7e34..44d75b99726 100644 --- a/htdocs/core/modules/product/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/product/doc/pdf_standard.modules.php @@ -1,5 +1,6 @@ +/* Copyright (C) 2017 Laurent Destailleur + * Copyright (C) 2017 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 890f9120d71e59af514a02fcb5f8a10cf7e5a49d Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 26 Jan 2023 10:48:27 +0100 Subject: [PATCH 776/816] Cop --- htdocs/core/modules/product/doc/pdf_standard.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/product/doc/pdf_standard.modules.php b/htdocs/core/modules/product/doc/pdf_standard.modules.php index 44d75b99726..7427fc7170e 100644 --- a/htdocs/core/modules/product/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/product/doc/pdf_standard.modules.php @@ -1,6 +1,6 @@ - * Copyright (C) 2017 Anthony Berton + * 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 35b05cfc7b45ad79cad9c3ebccb0135c65d7158d Mon Sep 17 00:00:00 2001 From: mgabriel Date: Thu, 26 Jan 2023 11:00:00 +0100 Subject: [PATCH 777/816] Implements MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS for product refs and labels. --- htdocs/product/card.php | 12 ++++++++++-- htdocs/product/class/product.class.php | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/htdocs/product/card.php b/htdocs/product/card.php index ac465b16bd7..ba1bc47046f 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -93,7 +93,11 @@ $refalreadyexists = 0; // Get parameters $id = GETPOST('id', 'int'); -$ref = (GETPOSTISSET('ref') ? GETPOST('ref', 'alpha') : null); +if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) { + $ref = (GETPOSTISSET('ref') ? GETPOST('ref', 'nohtml') : null); +} else { + $ref = (GETPOSTISSET('ref') ? GETPOST('ref', 'alpha') : null); +} $type = (GETPOSTISSET('type') ? GETPOST('type', 'int') : Product::TYPE_PRODUCT); $action = (GETPOST('action', 'alpha') ? GETPOST('action', 'alpha') : 'view'); $cancel = GETPOST('cancel', 'alpha'); @@ -113,7 +117,11 @@ $accountancy_code_buy_export = GETPOST('accountancy_code_buy_export', 'alpha'); $checkmandatory = GETPOST('accountancy_code_buy_export', 'alpha'); // by default 'alphanohtml' (better security); hidden conf MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML allows basic html -$label_security_check = empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML) ? 'alphanohtml' : 'restricthtml'; +if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) { + $label_security_check = 'nohtml'; +} else { + $label_security_check = empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_LABELS_WITH_HTML) ? 'alphanohtml' : 'restricthtml'; +} if (!empty($user->socid)) { $socid = $user->socid; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index d464871941a..1a2b3fa4cf2 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -572,7 +572,11 @@ class Product extends CommonObject */ public function check() { - $this->ref = dol_sanitizeFileName(stripslashes($this->ref)); + if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) { + $this->ref = trim($this->ref); + } else { + $this->ref = dol_sanitizeFileName(stripslashes($this->ref)); + } $err = 0; if (dol_strlen(trim($this->ref)) == 0) { @@ -604,7 +608,11 @@ class Product extends CommonObject $error = 0; // Clean parameters - $this->ref = dol_sanitizeFileName(dol_string_nospecial(trim($this->ref))); + if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) { + $this->ref = trim($this->ref); + } else { + $this->ref = dol_sanitizeFileName(dol_string_nospecial(trim($this->ref))); + } $this->label = trim($this->label); $this->price_ttc = price2num($this->price_ttc); $this->price = price2num($this->price); @@ -999,7 +1007,11 @@ class Product extends CommonObject } // Clean parameters - $this->ref = dol_string_nospecial(trim($this->ref)); + if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) { + $this->ref = trim($this->ref); + } else { + $this->ref = dol_string_nospecial(trim($this->ref)); + } $this->label = trim($this->label); $this->description = trim($this->description); $this->note_private = (isset($this->note_private) ? trim($this->note_private) : null); From d4f7b3e42f0aa3e2c0e8e69812f25aade4c0a79f Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Thu, 26 Jan 2023 11:01:44 +0100 Subject: [PATCH 778/816] FIX - Logo MYCOMPANY --- .../product/doc/pdf_standard.modules.php | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/htdocs/core/modules/product/doc/pdf_standard.modules.php b/htdocs/core/modules/product/doc/pdf_standard.modules.php index 7427fc7170e..c8190a362f5 100644 --- a/htdocs/core/modules/product/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/product/doc/pdf_standard.modules.php @@ -713,6 +713,9 @@ class pdf_standard extends ModelePDFProduct { global $conf, $langs, $hookmanager; + $ltrdirection = 'L'; + if ($outputlangs->trans("DIRECTION") == 'rtl') $ltrdirection = 'R'; + // Load traductions files required by page $outputlangs->loadLangs(array("main", "propal", "companies", "bills", "orders")); @@ -734,28 +737,41 @@ class pdf_standard extends ModelePDFProduct $pdf->SetTextColor(0, 0, 60); $pdf->SetFont('', 'B', $default_font_size + 3); + $w = 100; + $posy = $this->marge_haute; $posx = $this->page_largeur - $this->marge_droite - 100; $pdf->SetXY($this->marge_gauche, $posy); // Logo - $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo; - if ($this->emetteur->logo) { - if (is_readable($logo)) { - $height = pdf_getHeightForLogo($logo); - $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) + if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) { + if ($this->emetteur->logo) { + $logodir = $conf->mycompany->dir_output; + if (!empty($conf->mycompany->multidir_output[$object->entity])) { + $logodir = $conf->mycompany->multidir_output[$object->entity]; + } + if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) { + $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small; + } else { + $logo = $logodir.'/logos/'.$this->emetteur->logo; + } + if (is_readable($logo)) { + $height = pdf_getHeightForLogo($logo); + $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) + } else { + $pdf->SetTextColor(200, 0, 0); + $pdf->SetFont('', 'B', $default_font_size - 2); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L'); + $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); + } } else { - $pdf->SetTextColor(200, 0, 0); - $pdf->SetFont('', 'B', $default_font_size - 2); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L'); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); + $text = $this->emetteur->name; + $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection); } - } else { - $text = $this->emetteur->name; - $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); } + $pdf->SetFont('', 'B', $default_font_size + 3); $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); From c5f0ac9f29557c9842738f1e637f7c73d2663fcc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 26 Jan 2023 12:07:04 +0100 Subject: [PATCH 779/816] Fix public page for user --- htdocs/public/users/view.php | 26 ++++++++++++++++---------- htdocs/theme/eldy/global.inc.php | 7 +++++++ htdocs/theme/md/style.css.php | 7 +++++++ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/htdocs/public/users/view.php b/htdocs/public/users/view.php index d63a2a66eee..b0b4b3ae32f 100644 --- a/htdocs/public/users/view.php +++ b/htdocs/public/users/view.php @@ -229,6 +229,12 @@ if ($object->job && !getDolUserInt('USER_PUBLIC_HIDE_JOBPOSITION', 0, $object)) print dol_escape_htmltag($object->job); print ''; } +if (!getDolUserInt('USER_PUBLIC_HIDE_COMPANY', 0, $object)) { + print '
    '; + print dol_escape_htmltag($mysoc->name); + print '
    '; +} + print ''; @@ -240,7 +246,7 @@ print ''; if (!empty($conf->global->USER_IMAGE_PUBLIC_INTERFACE)) { print '
    '; - print ''; + print ''; print '
    '; } @@ -292,19 +298,19 @@ if ($object->office_phone && !getDolUserInt('USER_PUBLIC_HIDE_OFFICE_PHONE', 0, $usersection .= '
    '; $usersection .= img_picto('', 'phone', 'class="pictofixedwidth"'); $usersection .= dol_print_phone($object->office_phone, $object->country_code, 0, $mysoc->id, 'tel', ' ', 0, ''); - $usersection .= '
    '; + $usersection .= '
    '; } if ($object->office_fax && !getDolUserInt('USER_PUBLIC_HIDE_OFFICE_FAX', 0, $object)) { $usersection .= '
    '; $usersection .= img_picto('', 'phoning_fax', 'class="pictofixedwidth"'); $usersection .= dol_print_phone($object->office_fax, $object->country_code, 0, $mysoc->id, 'fax', ' ', 0, ''); - $usersection .= '
    '; + $usersection .= '
    '; } if ($object->user_mobile && !getDolUserInt('USER_PUBLIC_HIDE_USER_MOBILE', 0, $object)) { $usersection .= '
    '; $usersection .= img_picto('', 'phone', 'class="pictofixedwidth"'); $usersection .= dol_print_phone($object->user_mobile, $object->country_code, 0, $mysoc->id, 'tel', ' ', 0, ''); - $usersection .= '
    '; + $usersection .= '
    '; } // Social networks @@ -324,7 +330,7 @@ if ($usersection) { // Output payment summary form print '
    '; - print ''; + if (!empty($conf->global->PRODUCT_USE_UNITS)) { + print ''; + } print ''; } else { print ''; - print ''; - print ''; + if (!empty($conf->global->PRODUCT_USE_UNITS)) { + print ''; + } + print ''; } From 1200174b83e2974d9c07c5d442527feb55a7a2d4 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Thu, 26 Jan 2023 18:03:18 +0100 Subject: [PATCH 785/816] FIX : The folder on BOM card who display or not the sub BOM was not working --- htdocs/bom/bom_card.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 333b6232f9f..b25785ae368 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -613,9 +613,6 @@ if (empty($reshook)) { print "\n"; - mrpCollapseBomManagement(); - - //Services $filtertype = 1; $res = $object->fetchLinesbytypeproduct(1); From 072ee3f1eac56895ef660761213f456bf634d123 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 26 Jan 2023 19:20:03 +0100 Subject: [PATCH 786/816] Fix regression --- htdocs/comm/card.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 9c848883332..2e259a2c8bc 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -1427,7 +1427,7 @@ if ($object->id > 0) { $sql .= " WHERE f.fk_soc = s.rowid AND s.rowid = ".((int) $object->id); $sql .= " AND f.entity IN (".getEntity('invoice').")"; $sql .= ' GROUP BY f.rowid, f.ref, f.type, f.total_ht, f.total_tva, f.total_ttc,'; - $sql .= ' f.entity, f.datef, f.datec, f.paye, f.fk_statut,'; + $sql .= ' f.entity, f.datef, f.date_lim_reglement, f.datec, f.paye, f.fk_statut,'; $sql .= ' s.nom, s.rowid'; $sql .= " ORDER BY f.datef DESC, f.datec DESC"; @@ -1441,7 +1441,7 @@ if ($object->id > 0) { print '
    '; - print '
    '; + print '
    '; print $usersection; @@ -344,7 +350,7 @@ if (!getDolUserInt('USER_PUBLIC_HIDE_COMPANY', 0, $object)) { $companysection .= '
    '; $companysection .= img_picto('', 'email', 'class="pictofixedwidth"'); $companysection .= dol_print_email($mysoc->email, 0, 0, 1); - $companysection .= '
    '; + $companysection .= '
    '; } if ($mysoc->url) { @@ -358,13 +364,13 @@ if (!getDolUserInt('USER_PUBLIC_HIDE_COMPANY', 0, $object)) { $companysection .= '
    '; $companysection .= img_picto('', 'phone', 'class="pictofixedwidth"'); $companysection .= dol_print_phone($mysoc->phone, $mysoc->country_code, 0, $mysoc->id, 'tel', ' ', 0, ''); - $companysection .= '
    '; + $companysection .= '
    '; } if ($mysoc->fax) { $companysection .= '
    '; $companysection .= img_picto('', 'phoning_fax', 'class="pictofixedwidth"'); $companysection .= dol_print_phone($mysoc->fax, $mysoc->country_code, 0, $mysoc->id, 'fax', ' ', 0, ''); - $companysection .= '
    '; + $companysection .= '
    '; } // Social networks @@ -414,12 +420,12 @@ if (!getDolUserInt('USER_PUBLIC_HIDE_COMPANY', 0, $object)) { // Output payment summary form print '
    '; - print '
    '; + print '
    '; // Add company info if ($mysoc->name) { print '
    '; - print $mysoc->name; + print dol_escape_htmltag($mysoc->name); print '
    '; print '
    '; } diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 0b987de469e..e3df53d52cb 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1770,6 +1770,13 @@ select.widthcentpercentminusxx, span.widthcentpercentminusxx:not(.select2-select .smallonsmartphone { font-size: 0.8em; } + + .nopaddingtoponsmartphone { + padding-top: 0 !important; + } + .nopaddingbottomonsmartphone { + padding-bottom: 0 !important; + } } /* Force values for small screen 570 */ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 0fde8b72044..429940fd537 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1981,6 +1981,13 @@ select.widthcentpercentminusxx, span.widthcentpercentminusxx:not(.select2-select .smallonsmartphone { font-size: 0.8em; } + + .nopaddingtoponsmartphone { + padding-top: 0 !important; + } + .nopaddingbottomonsmartphone { + padding-bottom: 0 !important; + } } /* Force values for small screen 570 */ From 8735894a61e8b4dfb2e383e1b9432bce1796899b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 26 Jan 2023 12:09:33 +0100 Subject: [PATCH 780/816] Fix missing new Form --- htdocs/admin/company_socialnetworks.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/admin/company_socialnetworks.php b/htdocs/admin/company_socialnetworks.php index e9171431187..fb496c1dce1 100644 --- a/htdocs/admin/company_socialnetworks.php +++ b/htdocs/admin/company_socialnetworks.php @@ -84,6 +84,8 @@ if (($action == 'update' && !GETPOST("cancel", 'alpha'))) { * View */ +$form = new Form($db); + $wikihelp = 'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones'; llxHeader('', $langs->trans("Setup"), $wikihelp); From 3de3b421b92938e037fc26a3e56996fcca2ba22d Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Thu, 26 Jan 2023 14:37:15 +0100 Subject: [PATCH 781/816] fix : Warning: Trying to access array offset on value of type bool in /home/httpd/vhosts/aflac.fr/domains/dev.aflac.fr/httpdocs/includes/tcpdi/tcpdi_parser.php on line 1377 --- htdocs/includes/tcpdi/tcpdi_parser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/includes/tcpdi/tcpdi_parser.php b/htdocs/includes/tcpdi/tcpdi_parser.php index 13e9839f2b4..6d3cf789b6a 100644 --- a/htdocs/includes/tcpdi/tcpdi_parser.php +++ b/htdocs/includes/tcpdi/tcpdi_parser.php @@ -1373,7 +1373,7 @@ class tcpdi_parser { return false; } else { $res = $this->_getPageRotation($obj[1][1]['/Parent']); - if ($res[0] == PDF_TYPE_OBJECT) + if ($res && $res[0] == PDF_TYPE_OBJECT) return $res[1]; return $res; } From 777cfd5753a3d41fe75d3724a736a1e81e0426c8 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Thu, 26 Jan 2023 15:26:24 +0100 Subject: [PATCH 782/816] FIX : Sub-Bom costs were not good --- htdocs/bom/tpl/objectline_view.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 5992578a6e0..2df13e9af83 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -171,7 +171,7 @@ $tmpbom->calculateCosts(); print '
    '; $coldisplay++; if (!empty($line->fk_bom_child)) { - echo ''.price($tmpbom->total_cost).''; + echo ''.price($tmpbom->total_cost * $line->qty).''; } else { echo ''.price($line->total_cost).''; } From 52c39d05f796f2435f061e3ee18d0555f2e5590a Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Thu, 26 Jan 2023 15:32:37 +0100 Subject: [PATCH 783/816] FIX : Make help text part bold --- htdocs/langs/fr_FR/mrp.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/fr_FR/mrp.lang b/htdocs/langs/fr_FR/mrp.lang index 557b1f09175..47e8dcf13d3 100644 --- a/htdocs/langs/fr_FR/mrp.lang +++ b/htdocs/langs/fr_FR/mrp.lang @@ -82,7 +82,7 @@ ProductsToConsume=Produits à consommer ProductsToProduce=Produits à produire UnitCost=Coût unitaire TotalCost=Coût total -BOMTotalCost=Le coût de production de cette nomenclature basé sur chaque quantité et produit à consommer (utilise le cout de la sous BOM si existante, sinon le prix de revient du produit si défini, sinon le PMP si défini, sinon le meilleur prix d'achat) +BOMTotalCost=Le coût de production de cette nomenclature basé sur chaque quantité et produit à consommer (utilise le cout de la sous BOM si existante, sinon le prix de revient du produit si défini, sinon le PMP si défini, sinon le meilleur prix d'achat) BOMTotalCostService=Si le module "Poste de travail" est activé et qu'un poste de travail est défini par défaut sur la ligne, alors le calcul est "quantité (convertie en heures) x poste de travail ahr", sinon "quantité (convertie en heures) x prix de revient du service" GoOnTabProductionToProduceFirst=Vous devez avoir la production pour clôturer un Ordre de Fabrication (voir onglet '%s'). Mais vous pouvez l'annuler. ErrorAVirtualProductCantBeUsedIntoABomOrMo=Un kit ne peut pas être utilisé dans une Nomenclature ou un Ordre de fabrication. From 331dd7d4792ab881701845a053628da4087fa7c8 Mon Sep 17 00:00:00 2001 From: Adrien Raze Date: Thu, 26 Jan 2023 15:56:04 +0100 Subject: [PATCH 784/816] FIX : Sub-Bom indentations were not good --- htdocs/bom/tpl/objectline_view.tpl.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 2df13e9af83..ac277f6e880 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -269,16 +269,20 @@ if ($resql) { $label = $sub_bom_product->getLabelOfUnit('long'); if ($sub_bom_line->qty_frozen > 0) { print ''.price($sub_bom_line->qty, 0, '', 0, 0).''; - if ($label !== '') print $langs->trans($label); - print ''; + if ($label !== '') print $langs->trans($label); + print ''.$langs->trans('Yes').''.price($sub_bom_line->qty * $line->qty, 0, '', 0, 0).''; - if ($label !== '') print $langs->trans($label); - print ''; + if ($label !== '') print $langs->trans($label); + print ' 
    '; print ''; - print '
    '; + print ''; print ''; @@ -1493,14 +1493,14 @@ if ($object->id > 0) { //print $formfile->getDocumentsLink($facturestatic->element, $filename, $filedir); print ''; if ($objp->df > 0) { - print ''; + print ''; } else { - print ''; + print ''; } if ($objp->dl > 0) { - print ''; + print ''; } else { - print ''; + print ''; } print ''; print '\n"; if (!$i) { From 82f73da1ac7288d1cda74cb272b09cd69d225e83 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 10:31:12 +0100 Subject: [PATCH 790/816] Fix debug filter list services --- htdocs/contrat/services_list.php | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index fb50283991b..e66b5eaa273 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -36,6 +36,7 @@ require_once DOL_DOCUMENT_ROOT."/societe/class/societe.class.php"; $langs->loadLangs(array('products', 'contracts', 'companies')); $optioncss = GETPOST('optioncss', 'aZ09'); +$mode = GETPOST("mode"); $massaction = GETPOST('massaction', 'alpha'); $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; @@ -55,11 +56,10 @@ if (!$sortorder) { $sortorder = "ASC"; } -$mode = GETPOST("mode"); $filter = GETPOST("filter"); $search_name = GETPOST("search_name", 'alpha'); $search_subprice = GETPOST("search_subprice", 'alpha'); -$search_qty = GETPOST("search_name", 'alpha'); +$search_qty = GETPOST("search_qty", 'alpha'); $search_total_ht = GETPOST("search_total_ht", 'alpha'); $search_total_tva = GETPOST("search_total_tva", 'alpha'); $search_total_ttc = GETPOST("search_total_ttc", 'alpha'); @@ -144,10 +144,10 @@ $arrayfields = array( 'cd.qty'=>array('label'=>"Qty", 'checked'=>1, 'position'=>108), 'cd.total_ht'=>array('label'=>"TotalHT", 'checked'=>-1, 'position'=>109, 'isameasure'=>1), 'cd.total_tva'=>array('label'=>"TotalVAT", 'checked'=>-1, 'position'=>110), - 'cd.date_ouverture_prevue'=>array('label'=>"DateStartPlannedShort", 'checked'=>(($mode == "" || $mode == -1) || $mode == "0"), 'position'=>150), - 'cd.date_ouverture'=>array('label'=>"DateStartRealShort", 'checked'=>(($mode == "" || $mode == -1) || $mode > 0), 'position'=>160), - 'cd.date_fin_validite'=>array('label'=>"DateEndPlannedShort", 'checked'=>(($mode == "" || $mode == -1) || $mode < 5), 'position'=>170), - 'cd.date_cloture'=>array('label'=>"DateEndRealShort", 'checked'=>(($mode == "" || $mode == -1) || $mode >= 5), 'position'=>180), + 'cd.date_ouverture_prevue'=>array('label'=>"DateStartPlannedShort", 'checked'=>1, 'position'=>150), + 'cd.date_ouverture'=>array('label'=>"DateStartRealShort", 'checked'=>1, 'position'=>160), + 'cd.date_fin_validite'=>array('label'=>"DateEndPlannedShort", 'checked'=>1, 'position'=>170), + 'cd.date_cloture'=>array('label'=>"DateEndRealShort", 'checked'=>1, 'position'=>180), //'cd.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), 'cd.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>500), 'status'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000) @@ -294,7 +294,7 @@ if ($search_subprice) { $sql .= natural_search("cd.subprice", $search_subprice, 1); } if ($search_qty) { - $sql .= natural_search("cd.total_qty", $search_qty, 1); + $sql .= natural_search("cd.qty", $search_qty, 1); } if ($search_total_ht) { $sql .= natural_search("cd.total_ht", $search_total_ht, 1); @@ -563,7 +563,7 @@ if (!empty($arrayfields['c.ref']['checked'])) { print ''; } // Service label @@ -961,6 +961,17 @@ while ($i < min($num, $limit)) { // Show total line include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} + $db->free($resql); $parameters = array('sql' => $sql); From b84bd58fdc35252673a4dd1c35e91f87ed3b5126 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 10:42:32 +0100 Subject: [PATCH 791/816] Standardize code --- htdocs/contrat/class/contrat.class.php | 6 ++--- htdocs/contrat/index.php | 6 ++--- htdocs/contrat/services_list.php | 33 ++++++++++--------------- htdocs/core/menus/init_menu_auguria.sql | 8 +++--- htdocs/core/menus/standard/eldy.lib.php | 8 +++--- 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 4c7fe585d32..ad2cbcea84b 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2249,15 +2249,15 @@ class Contrat extends CommonObject $warning_delay = $conf->contrat->services->inactifs->warning_delay; $label = $langs->trans("BoardNotActivatedServices"); $labelShort = $langs->trans("BoardNotActivatedServicesShort"); - $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=0&sortfield=cd.date_fin_validite&sortorder=asc'; + $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=0&sortfield=cd.date_fin_validite&sortorder=asc'; } elseif ($mode == 'expired') { $warning_delay = $conf->contrat->services->expires->warning_delay; - $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4&filter=expired&sortfield=cd.date_fin_validite&sortorder=asc'; + $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&filter=expired&sortfield=cd.date_fin_validite&sortorder=asc'; $label = $langs->trans("BoardExpiredServices"); $labelShort = $langs->trans("BoardExpiredServicesShort"); } else { $warning_delay = $conf->contrat->services->expires->warning_delay; - $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4&sortfield=cd.date_fin_validite&sortorder=asc'; + $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&sortfield=cd.date_fin_validite&sortorder=asc'; //$url.= '&op2day='.$arraydatetouse['mday'].'&op2month='.$arraydatetouse['mon'].'&op2year='.$arraydatetouse['year']; //if ($warning_delay >= 0) $url.='&filter=expired'; $label = $langs->trans("BoardRunningServices"); diff --git a/htdocs/contrat/index.php b/htdocs/contrat/index.php index c14775449c6..c40453ec7af 100644 --- a/htdocs/contrat/index.php +++ b/htdocs/contrat/index.php @@ -194,7 +194,7 @@ foreach ($listofstatus as $status) { if (empty($conf->use_javascript_ajax)) { print ''; print ''; - print ''; + print ''; print "\n"; } if ($status == 4 && !$bool) { @@ -224,7 +224,7 @@ foreach ($listofstatus as $status) { if (empty($conf->use_javascript_ajax)) { print ''; print ''; - print ''; + print ''; if ($status == 4 && !$bool) { $bool = true; } else { @@ -622,7 +622,7 @@ if ($resql) { print '
    '; print '
    '.$langs->trans("LastCustomersBills", ($num <= $MAXLIST ? "" : $MAXLIST)).''.$langs->trans("AllBills").''.$num.''; print ''; print '
    '.$langs->trans("LastCustomersBills", ($num <= $MAXLIST ? "" : $MAXLIST)).''.$langs->trans("AllBills").''.$num.''.img_picto($langs->trans("Statistics"), 'stats').'
    '.$langs->trans('DateInvoice').": ".dol_print_date($db->jdate($objp->df), 'day').''.dol_print_date($db->jdate($objp->df), 'day').'!!!!!!'.$langs->trans('DateMaxPayment').": ".dol_print_date($db->jdate($objp->dl), 'day').''.dol_print_date($db->jdate($objp->dl), 'day').'!!!!!!'; print price($objp->total_ht); From 2493732edb0dc0ea3081e6537e051e47dd272308 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 26 Jan 2023 19:23:43 +0100 Subject: [PATCH 787/816] Fix properties --- htdocs/comm/card.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 2e259a2c8bc..46343919cb6 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -1458,6 +1458,8 @@ if ($object->id > 0) { $facturestatic->total_tva = $objp->total_tva; $facturestatic->total_ttc = $objp->total_ttc; $facturestatic->statut = $objp->status; + $facturestatic->date = $db->jdate($objp->df); + $facturestatic->date_lim_reglement = $db->jdate($objp->dl); print '
    '; From cedd0792f38598d6183e5531ef2d35035fce69ba Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 01:03:44 +0100 Subject: [PATCH 788/816] Fix duplicate --- htdocs/contrat/class/contrat.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 0357459052b..4c7fe585d32 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -243,7 +243,6 @@ class Contrat extends CommonObject 'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>1, 'visible'=>0, 'position'=>115), 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>120), 'extraparams' =>array('type'=>'varchar(255)', 'label'=>'Extraparams', 'enabled'=>1, 'visible'=>-1, 'position'=>125), - 'ref_customer' =>array('type'=>'varchar(50)', 'label'=>'Ref customer', 'enabled'=>1, 'visible'=>-1, 'position'=>130), 'fk_user_modif' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'position'=>135), 'last_main_doc' =>array('type'=>'varchar(255)', 'label'=>'Last main doc', 'enabled'=>1, 'visible'=>-1, 'position'=>140), 'statut' =>array('type'=>'smallint(6)', 'label'=>'Statut', 'enabled'=>1, 'visible'=>-1, 'position'=>500, 'notnull'=>1, 'arrayofkeyval'=>array(0=>'Draft', 1=>'Validated', 2=>'Closed')) From 31652fd7324ceb755111fcafcbb035e5a380728c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 02:43:41 +0100 Subject: [PATCH 789/816] css --- htdocs/product/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index f9a353b81b0..3b911a4c2c7 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -1456,7 +1456,7 @@ while ($i < $imaxinloop) { // Ref if (!empty($arrayfields['p.ref']['checked'])) { - print ''; + print ''; print $product_static->getNomUrl(1); print "'; print ''; print ''; - print ''; + print ''; print '
    '.$langs->trans("NoRecordFound").'
    '.$staticcontratligne->LibStatut($status, 0, ($bool ? 1 : 0)).''.($nb[$status.$bool] ? $nb[$status.$bool] : 0).' '.$staticcontratligne->LibStatut($status, 3, ($bool ? 1 : 0)).''.($nb[$status.$bool] ? $nb[$status.$bool] : 0).' '.$staticcontratligne->LibStatut($status, 3, ($bool ? 1 : 0)).'
    '.$staticcontratligne->LibStatut($status, 0, ($bool ? 1 : 0)).''.($nb[$status.$bool] ? $nb[$status.$bool] : 0).' '.$staticcontratligne->LibStatut($status, 3, ($bool ? 1 : 0)).''.($nb[$status.$bool] ? $nb[$status.$bool] : 0).' '.$staticcontratligne->LibStatut($status, 3, ($bool ? 1 : 0)).'
    '; - print ''; + print ''; print "\n"; while ($i < $num) { diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index a4713c14b6b..47818081448 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -56,7 +56,7 @@ if (!$sortorder) { $sortorder = "ASC"; } -$filter = GETPOST("filter"); +$filter = GETPOST("filter", 'alpha'); $search_name = GETPOST("search_name", 'alpha'); $search_subprice = GETPOST("search_subprice", 'alpha'); $search_qty = GETPOST("search_qty", 'alpha'); @@ -110,7 +110,6 @@ $result = restrictedArea($user, 'contrat', $contratid); if ($search_status != '') { $tmp = explode('&', $search_status); - $mode = $tmp[0]; if (empty($tmp[1])) { $filter = ''; } else { @@ -121,14 +120,6 @@ if ($search_status != '') { $filter = 'expired'; } } -} else { - $search_status = $mode; - if ($filter == 'expired') { - $search_status .= '&filter=expired'; - } - if ($filter == 'notexpired') { - $search_status .= '&filter=notexpired'; - } } $staticcontrat = new Contrat($db); @@ -209,7 +200,6 @@ if (empty($reshook)) { $opclotureday = ""; $opclotureyear = ""; $filter_opcloture = ""; - $mode = ''; $filter = ''; $toselect = array(); $search_array_options = array(); @@ -275,13 +265,13 @@ $sql .= " AND c.fk_soc = s.rowid"; if (empty($user->rights->societe->client->voir) && !$socid) { $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id); } -if ($mode == "0") { +if ($search_status == "0") { $sql .= " AND cd.statut = 0"; } -if ($mode == "4") { +if ($search_status == "4") { $sql .= " AND cd.statut = 4"; } -if ($mode == "5") { +if ($search_status == "5") { $sql .= " AND cd.statut = 5"; } if ($filter == "expired") { @@ -417,6 +407,9 @@ if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { if ($limit > 0 && $limit != $conf->liste_limit) { $param .= '&limit='.$limit; } +if ($mode) { + $param .= '&mode='.urlencode($mode); +} if ($search_contract) { $param .= '&search_contract='.urlencode($search_contract); } @@ -441,8 +434,8 @@ if ($search_total_ttc) { if ($search_service) { $param .= '&search_service='.urlencode($search_service); } -if ($mode) { - $param .= '&mode='.urlencode($mode); +if ($search_status) { + $param .= '&search_status='.urlencode($search_status); } if ($filter) { $param .= '&filter='.urlencode($filter); @@ -500,16 +493,16 @@ print ''; print ''; $title = $langs->trans("ListOfServices"); -if ($mode == "0") { +if ($search_status == "0") { $title = $langs->trans("ListOfInactiveServices"); // Must use == "0" } -if ($mode == "4" && $filter != "expired") { +if ($search_status == "4" && $filter != "expired") { $title = $langs->trans("ListOfRunningServices"); } -if ($mode == "4" && $filter == "expired") { +if ($search_status == "4" && $filter == "expired") { $title = $langs->trans("ListOfExpiredServices"); } -if ($mode == "5") { +if ($search_status == "5") { $title = $langs->trans("ListOfClosedServices"); } diff --git a/htdocs/core/menus/init_menu_auguria.sql b/htdocs/core/menus/init_menu_auguria.sql index cef586ad1da..5c819488971 100644 --- a/htdocs/core/menus/init_menu_auguria.sql +++ b/htdocs/core/menus/init_menu_auguria.sql @@ -205,10 +205,10 @@ insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, left insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled', __HANDLER__, 'left', 1401__+MAX_llx_menu__, 'commercial', '', 1400__+MAX_llx_menu__, '/contrat/card.php?mainmenu=commercial&action=create&leftmenu=contracts', 'NewContract', 1, 'contracts', '$user->rights->contrat->creer', '', 2, 0, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled', __HANDLER__, 'left', 1402__+MAX_llx_menu__, 'commercial', '', 1400__+MAX_llx_menu__, '/contrat/list.php?mainmenu=commercial&leftmenu=contracts', 'List', 1, 'contracts', '$user->rights->contrat->lire', '', 2, 1, __ENTITY__); insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled', __HANDLER__, 'left', 1403__+MAX_llx_menu__, 'commercial', '', 1400__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts', 'MenuServices', 1, 'contracts', '$user->rights->contrat->lire', '', 2, 2, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled && $leftmenu=="contracts"', __HANDLER__, 'left', 1404__+MAX_llx_menu__, 'commercial', '', 1403__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=0', 'MenuInactiveServices', 2, 'contracts', '$user->rights->contrat->lire', '', 2, 0, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled && $leftmenu=="contracts"', __HANDLER__, 'left', 1405__+MAX_llx_menu__, 'commercial', '', 1403__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4', 'MenuRunningServices', 2, 'contracts', '$user->rights->contrat->lire', '', 2, 1, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled && $leftmenu=="contracts"', __HANDLER__, 'left', 1406__+MAX_llx_menu__, 'commercial', '', 1403__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4&filter=expired', 'MenuExpiredServices', 2, 'contracts', '$user->rights->contrat->lire', '', 2, 2, __ENTITY__); -insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled && $leftmenu=="contracts"', __HANDLER__, 'left', 1407__+MAX_llx_menu__, 'commercial', '', 1403__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=5', 'MenuClosedServices', 2, 'contracts', '$user->rights->contrat->lire', '', 2, 3, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled && $leftmenu=="contracts"', __HANDLER__, 'left', 1404__+MAX_llx_menu__, 'commercial', '', 1403__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=0', 'MenuInactiveServices', 2, 'contracts', '$user->rights->contrat->lire', '', 2, 0, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled && $leftmenu=="contracts"', __HANDLER__, 'left', 1405__+MAX_llx_menu__, 'commercial', '', 1403__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4', 'MenuRunningServices', 2, 'contracts', '$user->rights->contrat->lire', '', 2, 1, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled && $leftmenu=="contracts"', __HANDLER__, 'left', 1406__+MAX_llx_menu__, 'commercial', '', 1403__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&filter=expired', 'MenuExpiredServices', 2, 'contracts', '$user->rights->contrat->lire', '', 2, 2, __ENTITY__); +insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->contrat->enabled && $leftmenu=="contracts"', __HANDLER__, 'left', 1407__+MAX_llx_menu__, 'commercial', '', 1403__+MAX_llx_menu__, '/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=5', 'MenuClosedServices', 2, 'contracts', '$user->rights->contrat->lire', '', 2, 3, __ENTITY__); -- Commercial - Interventions insert into llx_menu (module, enabled, menu_handler, type, rowid, mainmenu, leftmenu, fk_menu, url, titre, level, langs, perms, target, usertype, position, entity) values ('', '$conf->ficheinter->enabled', __HANDLER__, 'left', 1500__+MAX_llx_menu__, 'commercial', 'ficheinter', 5__+MAX_llx_menu__, '/fichinter/list.php?mainmenu=commercial&leftmenu=ficheinter', 'Interventions', 0, 'interventions', '$user->rights->ficheinter->lire', '', 2, 8, __ENTITY__); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index dbc2be872eb..a0b8be128c4 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1385,10 +1385,10 @@ function get_left_menu_commercial($mainmenu, &$newmenu, $usemenuhider = 1, $left $newmenu->add("/contrat/list.php?leftmenu=contracts", $langs->trans("List"), 1, $user->hasRight('contrat', 'lire')); $newmenu->add("/contrat/services_list.php?leftmenu=contracts", $langs->trans("MenuServices"), 1, $user->hasRight('contrat', 'lire')); if ($usemenuhider || empty($leftmenu) || $leftmenu == "contracts") { - $newmenu->add("/contrat/services_list.php?leftmenu=contracts&mode=0", $langs->trans("MenuInactiveServices"), 2, $user->hasRight('contrat', 'lire')); - $newmenu->add("/contrat/services_list.php?leftmenu=contracts&mode=4", $langs->trans("MenuRunningServices"), 2, $user->hasRight('contrat', 'lire')); - $newmenu->add("/contrat/services_list.php?leftmenu=contracts&mode=4&filter=expired", $langs->trans("MenuExpiredServices"), 2, $user->hasRight('contrat', 'lire')); - $newmenu->add("/contrat/services_list.php?leftmenu=contracts&mode=5", $langs->trans("MenuClosedServices"), 2, $user->hasRight('contrat', 'lire')); + $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=0", $langs->trans("MenuInactiveServices"), 2, $user->hasRight('contrat', 'lire')); + $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=4", $langs->trans("MenuRunningServices"), 2, $user->hasRight('contrat', 'lire')); + $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=4&filter=expired", $langs->trans("MenuExpiredServices"), 2, $user->hasRight('contrat', 'lire')); + $newmenu->add("/contrat/services_list.php?leftmenu=contracts&search_status=5", $langs->trans("MenuClosedServices"), 2, $user->hasRight('contrat', 'lire')); } } From f6ad2c3a7628e73c815bcbe7863d380c1bea5af9 Mon Sep 17 00:00:00 2001 From: hystepik Date: Fri, 27 Jan 2023 11:01:16 +0100 Subject: [PATCH 792/816] Fix : php 8.1 warning --- htdocs/compta/paiement/card.php | 4 ++++ htdocs/compta/paiement/list.php | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/paiement/card.php b/htdocs/compta/paiement/card.php index 073365fa876..14442e6c965 100644 --- a/htdocs/compta/paiement/card.php +++ b/htdocs/compta/paiement/card.php @@ -46,6 +46,10 @@ $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $backtopage = GETPOST('backtopage', 'alpha'); +$socid = GETPOST('socid', 'int'); if ($socid < 0) { + $socid = 0; +} + $object = new Paiement($db); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('paymentcard', 'globalcard')); diff --git a/htdocs/compta/paiement/list.php b/htdocs/compta/paiement/list.php index 658f2c150f1..6db18f6aa55 100644 --- a/htdocs/compta/paiement/list.php +++ b/htdocs/compta/paiement/list.php @@ -513,6 +513,7 @@ foreach ($arrayfields as $column) { $i = 0; $totalarray = array(); +$totalarray['nbfield'] = 0; while ($i < min($num, $limit)) { $objp = $db->fetch_object($resql); @@ -620,7 +621,11 @@ while ($i < min($num, $limit)) { $totalarray['nbfield']++; } $totalarray['pos'][$checkedCount] = 'amount'; - $totalarray['val']['amount'] += $objp->amount; + if (empty($totalarray['val']['amount'])) { + $totalarray['val']['amount'] = $objp->amount; + } else { + $totalarray['val']['amount'] += $objp->amount; + } } // Status From 923e63c8e31bda7139fe3f973c307fb2101ba8da Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 11:05:06 +0100 Subject: [PATCH 793/816] Trans --- htdocs/langs/en_US/main.lang | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 405417d7da6..f22666c4197 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1220,4 +1220,5 @@ NoSpecificContactAddressBis=This tab is dedicated to force specific contacts or HideOnVCard=Hide %s AddToContacts=Add address to my contacts LastAccess=Last access -UploadAnImageToSeeAPhotoHere=Upload an image from the tab %s to see a photo here \ No newline at end of file +UploadAnImageToSeeAPhotoHere=Upload an image from the tab %s to see a photo here +LastPasswordChangeDate=Last password change date \ No newline at end of file From 9c904236c43998d5b04e828fc2b7b93a9a4e0fcb Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 27 Jan 2023 11:25:55 +0100 Subject: [PATCH 794/816] NEW - Add hook online sign --- htdocs/public/onlinesign/newonlinesign.php | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index c47bbd7f734..c6f11e6b2ac 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -156,6 +156,8 @@ if ($source == 'proposal') { httponly_accessforbidden($langs->trans('ErrorBadParameters')." - Bad value for source", 400, 1); } +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('onlinesign')); /* * Actions @@ -346,10 +348,21 @@ if ($source == 'proposal') { print ''."\n"; // Amount - print ''."\n"; + $amount = ''."\n"; + + // Call Hook formConfirm + $parameters = array('source' => $source); + $reshook = $hookmanager->executeHooks('amountpropalsign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $amount .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $amount = $hookmanager->resPrint; + } + + print $amount; // Object $text = ''.$langs->trans("SignatureProposalRef", $object->ref).''; @@ -457,6 +470,7 @@ if ($source == 'proposal') { $langs->load("fichinter"); $result = $object->fetch_thirdparty($object->socid); + // Proposer print ''."\n"; } +// Call Hook addformsign +$parameters = array('source' => $source); +$reshook = $hookmanager->executeHooks('addformsign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (!$found && !$mesg) { $mesg = $langs->transnoentitiesnoconv("ErrorBadParameters"); From 6715cdec0fa4719920148a29627d23c90edfcbba Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 27 Jan 2023 11:27:25 +0100 Subject: [PATCH 795/816] case --- htdocs/public/onlinesign/newonlinesign.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index c6f11e6b2ac..e5a195471de 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -353,9 +353,9 @@ if ($source == 'proposal') { $amount .= ''.price($object->total_ttc, 0, $langs, 1, -1, -1, $conf->currency).''; $amount .= ''."\n"; - // Call Hook formConfirm + // Call Hook amountPropalSign $parameters = array('source' => $source); - $reshook = $hookmanager->executeHooks('amountpropalsign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + $reshook = $hookmanager->executeHooks('amountPropalSign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) { $amount .= $hookmanager->resPrint; } elseif ($reshook > 0) { @@ -515,9 +515,9 @@ if ($source == 'proposal') { print ''."\n"; } -// Call Hook addformsign +// Call Hook addFormSign $parameters = array('source' => $source); -$reshook = $hookmanager->executeHooks('addformsign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$reshook = $hookmanager->executeHooks('addFormSign', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (!$found && !$mesg) { $mesg = $langs->transnoentitiesnoconv("ErrorBadParameters"); From c4245e2c05ede1ac4a0d9072e6d0d822542909c6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 11:52:58 +0100 Subject: [PATCH 796/816] Prepare use of upgrade.unlock --- htdocs/install/step5.php | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/htdocs/install/step5.php b/htdocs/install/step5.php index 31b086636f2..c516cc70aef 100644 --- a/htdocs/install/step5.php +++ b/htdocs/install/step5.php @@ -368,13 +368,16 @@ if ($action == "set" || empty($action) || preg_match('/upgrade/i', $action)) { if ($action == "set") { if ($success) { if (empty($conf->global->MAIN_VERSION_LAST_UPGRADE) || ($conf->global->MAIN_VERSION_LAST_UPGRADE == DOL_VERSION)) { - // Install is finished + // Install is finished (database is on same version than files) print '
    '.$langs->trans("SystemIsInstalled")."
    "; + // Create install.lock file + // No need for the moment to create it automatically, creation by web assistant means permissions are given + // to the web user, it is better to show a warning to say to create it manually with correct user/permission (not erasable by a web process) $createlock = 0; - if (!empty($force_install_lockinstall) || !empty($conf->global->MAIN_ALWAYS_CREATE_LOCK_AFTER_LAST_UPGRADE)) { - // Install is finished, we create the lock file + // Install is finished, we create the "install.lock" file, so install won't be possible anymore. + // TODO Upgrade will be still be possible if a file "upgrade.unlock" is present $lockfile = DOL_DATA_ROOT.'/install.lock'; $fp = @fopen($lockfile, "w"); if ($fp) { @@ -413,13 +416,14 @@ if ($action == "set") { } elseif (empty($action) || preg_match('/upgrade/i', $action)) { // If upgrade if (empty($conf->global->MAIN_VERSION_LAST_UPGRADE) || ($conf->global->MAIN_VERSION_LAST_UPGRADE == DOL_VERSION)) { - // Upgrade is finished + // Upgrade is finished (database is on same version than files) print 'Configuration '.$langs->trans("SystemIsUpgraded")."
    "; + // Create install.lock file if it does not exists. + // Note: it should always exists. A better solution to allow upgrade will be to add an upgrade.unlock file $createlock = 0; - if (!empty($force_install_lockinstall) || !empty($conf->global->MAIN_ALWAYS_CREATE_LOCK_AFTER_LAST_UPGRADE)) { - // Upgrade is finished, we create the lock file + // Upgrade is finished, we modify the lock file $lockfile = DOL_DATA_ROOT.'/install.lock'; $fp = @fopen($lockfile, "w"); if ($fp) { @@ -436,6 +440,10 @@ if ($action == "set") { print '
    '.$langs->trans("WarningRemoveInstallDir")."
    "; } + // Delete the upgrade.unlock file it it exists + $unlockupgradefile = DOL_DATA_ROOT.'/upgrade.unlock'; + dol_delete_file($unlockupgradefile, 0, 0, 0, null, false, 0); + print "
    "; $morehtml = '
    '; From dfcba305775af1d5fd1fab9515e87a52ee6421c0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 14:06:31 +0100 Subject: [PATCH 797/816] FIX Check of date of validity --- htdocs/api/class/api_access.class.php | 18 +++++++------ htdocs/core/lib/security2.lib.php | 3 ++- htdocs/core/login/functions_dolibarr.php | 20 +-------------- htdocs/dav/fileserver.php | 19 +++++++++++--- htdocs/main.inc.php | 23 ++++++++++++----- htdocs/user/class/user.class.php | 32 ++++++++++++++++++++++-- 6 files changed, 76 insertions(+), 39 deletions(-) diff --git a/htdocs/api/class/api_access.class.php b/htdocs/api/class/api_access.class.php index e5cc664fa0e..6874d3faaed 100644 --- a/htdocs/api/class/api_access.class.php +++ b/htdocs/api/class/api_access.class.php @@ -155,17 +155,19 @@ class DolibarrApiAccess implements iAuthenticate throw new RestException(503, 'Error when fetching user. This user has been locked or disabled'); } - $now = dol_now(); - - // Check date start validity - if ($fuser->datestartvalidity && $this->db->jdate($fuser->datestartvalidity) > $now) { - throw new RestException(503, $genericmessageerroruser); - } - // Check date end validity - if ($fuser->dateendvalidity && $this->db->jdate($fuser->dateendvalidity) < dol_get_first_hour($now)) { + // Check if session was unvalidated by a password change + if (($fuser->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $fuser->flagdelsessionsbefore > $_SESSION["dol_logindate"])) { + // Session is no more valid + dol_syslog("The user has a date for session invalidation = ".$fuser->flagdelsessionsbefore." and a session date = ".$_SESSION["dol_logindate"].". We must invalidate its sessions."); throw new RestException(503, $genericmessageerroruser); } + // Check date validity + if ($fuser->isNotIntoValidityDateRange()) { + // User validity dates are no more valid + dol_syslog("The user login has a validity between [".$fuser->datestartvalidity." and ".$fuser->dateendvalidity."], curren date is ".dol_now()); + throw new RestException(503, $genericmessageerroruser); + } // User seems valid $fuser->getrights(); diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index f450d390dff..93da106aebd 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -96,7 +96,8 @@ function checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $auth // Call function to check user/password $function = 'check_user_password_'.$mode; $login = call_user_func($function, $usertotest, $passwordtotest, $entitytotest, $context); - if ($login && $login != '--bad-login-validity--') { // Login is successfull + if ($login && $login != '--bad-login-validity--') { + // Login is successfull with this method $test = false; // To stop once at first login success $conf->authmode = $mode; // This properties is defined only when logged to say what mode was successfully used /*$dol_tz = GETPOST('tz'); diff --git a/htdocs/core/login/functions_dolibarr.php b/htdocs/core/login/functions_dolibarr.php index 5f4b722ea1c..9b65bf4d877 100644 --- a/htdocs/core/login/functions_dolibarr.php +++ b/htdocs/core/login/functions_dolibarr.php @@ -74,24 +74,6 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { - $now = dol_now(); - // Check date start validity - if ($obj->datestartvalidity && $db->jdate($obj->datestartvalidity) > $now) { - // Load translation files required by the page - $langs->loadLangs(array('main', 'errors')); - $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity"); - dol_syslog("functions_dolibarr::check_user_password_dolibarr bad datestart validity", LOG_WARNING); - return '--bad-login-validity--'; - } - // Check date end validity - if ($obj->dateendvalidity && $db->jdate($obj->dateendvalidity) < dol_get_first_hour($now)) { - // Load translation files required by the page - $langs->loadLangs(array('main', 'errors')); - $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity"); - dol_syslog("functions_dolibarr::check_user_password_dolibarr bad date end validity", LOG_WARNING); - return '--bad-login-validity--'; - } - $passclear = $obj->pass; $passcrypted = $obj->pass_crypted; $passtyped = $passwordtotest; @@ -121,7 +103,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes if ((!$passcrypted || $passtyped) && ($passclear && ($passtyped == $passclear))) { $passok = true; - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ok - found pass in database"); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ok - found old pass in database", LOG_WARNING); } } diff --git a/htdocs/dav/fileserver.php b/htdocs/dav/fileserver.php index 7abe3f2bacf..15d9cd1764f 100644 --- a/htdocs/dav/fileserver.php +++ b/htdocs/dav/fileserver.php @@ -92,8 +92,7 @@ $tmpDir = $conf->dav->multidir_output[$entity]; // We need root dir, not a dir t // Authentication callback function $authBackend = new \Sabre\DAV\Auth\Backend\BasicCallBack(function ($username, $password) { - global $user; - global $conf; + global $user, $conf; global $dolibarr_main_authentication, $dolibarr_auto_user; if (empty($user->login)) { @@ -101,7 +100,7 @@ $authBackend = new \Sabre\DAV\Auth\Backend\BasicCallBack(function ($username, $p return false; } if ($user->socid > 0) { - dol_syslog("Failed to authenticate to DAV, use is an external user", LOG_WARNING); + dol_syslog("Failed to authenticate to DAV, user is an external user", LOG_WARNING); return false; } if ($user->login != $username) { @@ -132,6 +131,20 @@ $authBackend = new \Sabre\DAV\Auth\Backend\BasicCallBack(function ($username, $p return false; } + // Check if session was unvalidated by a password change + if (($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"])) { + // Session is no more valid + dol_syslog("The user has a date for session invalidation = ".$user->flagdelsessionsbefore." and a session date = ".$_SESSION["dol_logindate"].". We must invalidate its sessions."); + return false; + } + + // Check date validity + if ($user->isNotIntoValidityDateRange()) { + // User validity dates are no more valid + dol_syslog("The user login has a validity between [".$user->datestartvalidity." and ".$user->dateendvalidity."], curren date is ".dol_now()); + return false; + } + return true; }); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 115be3cf0cf..24ce10ea7c1 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -879,8 +879,8 @@ if (!defined('NOLOGIN')) { exit; } - $resultFetchUser = $user->fetch('', $login, '', 1, ($entitytotest > 0 ? $entitytotest : -1)); // login was retrieved previously when checking password. - if ($resultFetchUser <= 0) { + $resultFetchUser = $user->fetch('', $login, '', 1, ($entitytotest > 0 ? $entitytotest : -1)); // value for $login was retrieved previously when checking password. + if ($resultFetchUser <= 0 || $user->isNotIntoValidityDateRange()) { dol_syslog('User not found, connexion refused'); session_destroy(); session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie @@ -894,11 +894,17 @@ if (!defined('NOLOGIN')) { $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorCantLoadUserFromDolibarrDatabase", $login); $user->trigger_mesg = 'ErrorCantLoadUserFromDolibarrDatabase - login='.$login; - } - if ($resultFetchUser < 0) { + } elseif ($resultFetchUser < 0) { $_SESSION["dol_loginmesg"] = $user->error; $user->trigger_mesg = $user->error; + } else { + // Load translation files required by the page + $langs->loadLangs(array('main', 'errors')); + + $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity"); + + $user->trigger_mesg = $langs->trans("ErrorLoginDateValidity").' - login='.$login; } // Call trigger @@ -943,13 +949,18 @@ if (!defined('NOLOGIN')) { dol_syslog("- This is an already logged session. _SESSION['dol_login']=".$login." _SESSION['dol_entity']=".$entity, LOG_DEBUG); $resultFetchUser = $user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1)); - if ($resultFetchUser <= 0 || ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"])) { + if ($resultFetchUser <= 0 + || ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"]) + || ($user->isNotIntoValidtyDateRange())) { if ($resultFetchUser <= 0) { // Account has been removed after login dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING); - } else { + } elseif ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"]) { // Session is no more valid dol_syslog("The user has a date for session invalidation = ".$user->flagdelsessionsbefore." and a session date = ".$_SESSION["dol_logindate"].". We must invalidate its sessions."); + } else { + // User validity dates are no more valid + dol_syslog("The user login has a validity between [".$user->datestartvalidity." and ".$user->dateendvalidity."], curren date is ".dol_now()); } session_destroy(); session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index b32c23ab7fc..f8d437d4fa0 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -1885,8 +1885,12 @@ class User extends CommonObject $this->employee = ($this->employee > 0 ? $this->employee : 0); $this->login = trim((string) $this->login); $this->gender = trim((string) $this->gender); + $this->pass = trim((string) $this->pass); $this->api_key = trim((string) $this->api_key); + $this->datestartvalidity = empty($this->datestartvalidity) ? '' : $this->datestartvalidity; + $this->dateendvalidity = empty($this->dateendvalidity) ? '' : $this->dateendvalidity; + $this->address = trim((string) $this->address); $this->zip = trim((string) $this->zip); $this->town = trim((string) $this->town); @@ -1911,8 +1915,7 @@ class User extends CommonObject $this->color = trim((string) $this->color); $this->dateemployment = empty($this->dateemployment) ? '' : $this->dateemployment; $this->dateemploymentend = empty($this->dateemploymentend) ? '' : $this->dateemploymentend; - $this->datestartvalidity = empty($this->datestartvalidity) ? '' : $this->datestartvalidity; - $this->dateendvalidity = empty($this->dateendvalidity) ? '' : $this->dateendvalidity; + $this->birth = empty($this->birth) ? '' : $this->birth; $this->fk_warehouse = (int) $this->fk_warehouse; @@ -2695,6 +2698,31 @@ class User extends CommonObject } + /** + * Return a link with photo + * Use this->id,this->photo + * + * @return int 0=No more valid, >0 if OK + */ + public function isNotIntoValidtyDateRange() + { + include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + + $now = dol_now(); + + // Check date start validity + if ($this->datestartvalidity && $this->datestartvalidity > dol_get_last_hour($now)) { + return 0; + } + // Check date end validity + if ($this->dateendvalidity && $this->dateendvalidity < dol_get_first_hour($now)) { + return 0; + } + + return 1; + } + + /** * Return a link with photo * Use this->id,this->photo From e7c63bfe1ba64c520bf382f62bb467ba3e8265cf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 14:27:51 +0100 Subject: [PATCH 798/816] FIX Check of date of validity --- htdocs/langs/en_US/errors.lang | 2 +- htdocs/main.inc.php | 7 +++++-- htdocs/user/class/user.class.php | 12 +++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index b779c901b54..240dd7c4c41 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -303,7 +303,7 @@ ErrorValueForTooLow=Value for %s is too low ErrorValueCantBeNull=Value for %s can't be null ErrorDateOfMovementLowerThanDateOfFileTransmission=The date of the bank transaction can't be lower than the date of the file transmission ErrorTooMuchFileInForm=Too much files in form, the maximum number is %s file(s) -ErrorSessionInvalidatedAfterPasswordChange=The session was invalidated after a password change. Please relogin. +ErrorSessionInvalidatedAfterPasswordChange=The session was invalidated after a password or dates of validity change. Please relogin. # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 24ce10ea7c1..df62eea68c4 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -881,7 +881,7 @@ if (!defined('NOLOGIN')) { $resultFetchUser = $user->fetch('', $login, '', 1, ($entitytotest > 0 ? $entitytotest : -1)); // value for $login was retrieved previously when checking password. if ($resultFetchUser <= 0 || $user->isNotIntoValidityDateRange()) { - dol_syslog('User not found, connexion refused'); + dol_syslog('User not found or not valid, connexion refused'); session_destroy(); session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie session_name($sessionname); @@ -949,9 +949,12 @@ if (!defined('NOLOGIN')) { dol_syslog("- This is an already logged session. _SESSION['dol_login']=".$login." _SESSION['dol_entity']=".$entity, LOG_DEBUG); $resultFetchUser = $user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1)); + + //var_dump(dol_print_date($user->flagdelsessionsbefore, 'dayhour', 'gmt')." ".dol_print_date($_SESSION["dol_logindate"], 'dayhour', 'gmt')); + if ($resultFetchUser <= 0 || ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"]) - || ($user->isNotIntoValidtyDateRange())) { + || ($user->isNotIntoValidityDateRange())) { if ($resultFetchUser <= 0) { // Account has been removed after login dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index f8d437d4fa0..2893378bdd9 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2702,24 +2702,26 @@ class User extends CommonObject * Return a link with photo * Use this->id,this->photo * - * @return int 0=No more valid, >0 if OK + * @return int 0=Valid, >0 if not valid */ - public function isNotIntoValidtyDateRange() + public function isNotIntoValidityDateRange() { include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; $now = dol_now(); + //dol_syslog("isNotIntoValidityDateRange ".$this->datestartvalidity); + // Check date start validity if ($this->datestartvalidity && $this->datestartvalidity > dol_get_last_hour($now)) { - return 0; + return 1; } // Check date end validity if ($this->dateendvalidity && $this->dateendvalidity < dol_get_first_hour($now)) { - return 0; + return 1; } - return 1; + return 0; } From 0765a1196f421c4aeff269c416985ea4d61ddf00 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 14:27:51 +0100 Subject: [PATCH 799/816] FIX Check of date of validity --- htdocs/api/class/api_access.class.php | 9 +++++++-- htdocs/dav/fileserver.php | 7 +++++++ htdocs/langs/en_US/errors.lang | 2 +- htdocs/main.inc.php | 11 +++++++++-- htdocs/user/class/user.class.php | 12 +++++++----- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/htdocs/api/class/api_access.class.php b/htdocs/api/class/api_access.class.php index 6874d3faaed..541682101c6 100644 --- a/htdocs/api/class/api_access.class.php +++ b/htdocs/api/class/api_access.class.php @@ -144,6 +144,7 @@ class DolibarrApiAccess implements iAuthenticate throw new RestException(503, 'Error when searching login user from api key'); } + $genericmessageerroruser = 'Error user not valid (not found or bad status or bad validity dates) (conf->entity='.$conf->entity.')'; $fuser = new User($this->db); @@ -151,8 +152,12 @@ class DolibarrApiAccess implements iAuthenticate if ($result <= 0) { throw new RestException(503, $genericmessageerroruser); } - if ($fuser->statut == 0) { - throw new RestException(503, 'Error when fetching user. This user has been locked or disabled'); + + // Check if user status is enabled + if ($fuser->statut != $fuser::STATUS_ENABLED) { + // Status is disabled + dol_syslog("The user has been disabled"); + throw new RestException(503, $genericmessageerroruser); } // Check if session was unvalidated by a password change diff --git a/htdocs/dav/fileserver.php b/htdocs/dav/fileserver.php index 15d9cd1764f..af23fde5fff 100644 --- a/htdocs/dav/fileserver.php +++ b/htdocs/dav/fileserver.php @@ -131,6 +131,13 @@ $authBackend = new \Sabre\DAV\Auth\Backend\BasicCallBack(function ($username, $p return false; } + // Check if user status is enabled + if ($user->statut != $user::STATUS_ENABLED) { + // Status is disabled + dol_syslog("The user has been disabled."); + return false; + } + // Check if session was unvalidated by a password change if (($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"])) { // Session is no more valid diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index b779c901b54..240dd7c4c41 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -303,7 +303,7 @@ ErrorValueForTooLow=Value for %s is too low ErrorValueCantBeNull=Value for %s can't be null ErrorDateOfMovementLowerThanDateOfFileTransmission=The date of the bank transaction can't be lower than the date of the file transmission ErrorTooMuchFileInForm=Too much files in form, the maximum number is %s file(s) -ErrorSessionInvalidatedAfterPasswordChange=The session was invalidated after a password change. Please relogin. +ErrorSessionInvalidatedAfterPasswordChange=The session was invalidated after a password or dates of validity change. Please relogin. # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 24ce10ea7c1..8a4efc8466b 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -881,7 +881,7 @@ if (!defined('NOLOGIN')) { $resultFetchUser = $user->fetch('', $login, '', 1, ($entitytotest > 0 ? $entitytotest : -1)); // value for $login was retrieved previously when checking password. if ($resultFetchUser <= 0 || $user->isNotIntoValidityDateRange()) { - dol_syslog('User not found, connexion refused'); + dol_syslog('User not found or not valid, connexion refused'); session_destroy(); session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie session_name($sessionname); @@ -949,15 +949,22 @@ if (!defined('NOLOGIN')) { dol_syslog("- This is an already logged session. _SESSION['dol_login']=".$login." _SESSION['dol_entity']=".$entity, LOG_DEBUG); $resultFetchUser = $user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1)); + + //var_dump(dol_print_date($user->flagdelsessionsbefore, 'dayhour', 'gmt')." ".dol_print_date($_SESSION["dol_logindate"], 'dayhour', 'gmt')); + if ($resultFetchUser <= 0 || ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"]) - || ($user->isNotIntoValidtyDateRange())) { + || ($user->status != $user::STATUS_ENABLED) + || ($user->isNotIntoValidityDateRange())) { if ($resultFetchUser <= 0) { // Account has been removed after login dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING); } elseif ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"]) { // Session is no more valid dol_syslog("The user has a date for session invalidation = ".$user->flagdelsessionsbefore." and a session date = ".$_SESSION["dol_logindate"].". We must invalidate its sessions."); + } elseif ($user->status != $user::STATUS_ENABLED) { + // User is not enabled + dol_syslog("The user login is disabled"); } else { // User validity dates are no more valid dol_syslog("The user login has a validity between [".$user->datestartvalidity." and ".$user->dateendvalidity."], curren date is ".dol_now()); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index f8d437d4fa0..2893378bdd9 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2702,24 +2702,26 @@ class User extends CommonObject * Return a link with photo * Use this->id,this->photo * - * @return int 0=No more valid, >0 if OK + * @return int 0=Valid, >0 if not valid */ - public function isNotIntoValidtyDateRange() + public function isNotIntoValidityDateRange() { include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; $now = dol_now(); + //dol_syslog("isNotIntoValidityDateRange ".$this->datestartvalidity); + // Check date start validity if ($this->datestartvalidity && $this->datestartvalidity > dol_get_last_hour($now)) { - return 0; + return 1; } // Check date end validity if ($this->dateendvalidity && $this->dateendvalidity < dol_get_first_hour($now)) { - return 0; + return 1; } - return 1; + return 0; } From 9ecd2c4beef7af17e3e029e05a12827cb12c63b1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 27 Jan 2023 14:47:43 +0100 Subject: [PATCH 800/816] Trans --- htdocs/langs/en_US/errors.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 240dd7c4c41..50d5c0e90d7 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -303,7 +303,7 @@ ErrorValueForTooLow=Value for %s is too low ErrorValueCantBeNull=Value for %s can't be null ErrorDateOfMovementLowerThanDateOfFileTransmission=The date of the bank transaction can't be lower than the date of the file transmission ErrorTooMuchFileInForm=Too much files in form, the maximum number is %s file(s) -ErrorSessionInvalidatedAfterPasswordChange=The session was invalidated after a password or dates of validity change. Please relogin. +ErrorSessionInvalidatedAfterPasswordChange=The session was been invalidated following a change of password, status or dates of validity. Please relogin. # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. From 2a104af20e111b7c92bbd9e7e375a2b2bc3cee14 Mon Sep 17 00:00:00 2001 From: Anthony Berton Date: Fri, 27 Jan 2023 15:11:14 +0100 Subject: [PATCH 801/816] Cop --- htdocs/public/onlinesign/newonlinesign.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index e5a195471de..cd793a91bfc 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -2,6 +2,7 @@ /* Copyright (C) 2001-2002 Rodolphe Quiedeville * Copyright (C) 2006-2017 Laurent Destailleur * Copyright (C) 2009-2012 Regis Houssin + * 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 791a69dd09b8c487f57ce4b7175f22f68355e732 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sat, 28 Jan 2023 04:48:55 +0100 Subject: [PATCH 802/816] FIX Accountancy - Quadra export --- .../class/accountancyexport.class.php | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 73035c55d5d..2215ed1352e 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -5,7 +5,7 @@ * Copyright (C) 2015 Florian Henry * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Pierre-Henry Favre - * Copyright (C) 2016-2021 Alexandre Spangaro + * Copyright (C) 2016-2023 Alexandre Spangaro * Copyright (C) 2013-2017 Olivier Geffroy * Copyright (C) 2017 Elarifr. Ari Elbaz * Copyright (C) 2017-2019 Frédéric France @@ -518,7 +518,7 @@ class AccountancyExport /** * Export format : Quadratus (Format ASCII) * Format since 2015 compatible QuadraCOMPTA - * Last review for this format : 2021/09/13 Alexandre Spangaro (aspangaro@open-dsi.fr) + * Last review for this format : 2023/01/28 Alexandre Spangaro (aspangaro@open-dsi.fr) * * Help : https://docplayer.fr/20769649-Fichier-d-entree-ascii-dans-quadracompta.html * In QuadraCompta | Use menu : "Outils" > "Suivi des dossiers" > "Import ASCII(Compta)" @@ -536,6 +536,14 @@ class AccountancyExport // $date_ecriture = dol_print_date(dol_now(), $conf->global->ACCOUNTING_EXPORT_DATE); // format must be ddmmyy // $date_ecriture = dol_print_date(time(), $conf->global->ACCOUNTING_EXPORT_DATE); // format must be ddmmyy foreach ($TData as $data) { + // Clean some data + $data->doc_ref = dol_string_unaccent($data->doc_ref); + $data->label_operation = dol_string_unaccent($data->label_operation); + $data->numero_compte = dol_string_unaccent($data->numero_compte); + $data->label_compte = dol_string_unaccent($data->label_compte); + $data->subledger_account = dol_string_unaccent($data->subledger_account); + $data->subledger_label = dol_string_unaccent($data->subledger_label); + $code_compta = $data->numero_compte; if (!empty($data->subledger_account)) { $code_compta = $data->subledger_account; @@ -567,9 +575,9 @@ class AccountancyExport if ($data->doc_type == 'customer_invoice') { $Tab['type_compte'] = 'C'; } elseif ($data->doc_type == 'supplier_invoice') { - $Tab['coll_compte'] = 'F'; + $Tab['type_compte'] = 'F'; } else { - $Tab['coll_compte'] = 'G'; + $Tab['type_compte'] = 'G'; } $Tab['filler3'] = str_repeat(' ', 235); @@ -590,7 +598,7 @@ class AccountancyExport //$Tab['date_ecriture'] = $date_ecriture; $Tab['date_ecriture'] = dol_print_date($data->doc_date, '%d%m%y'); $Tab['filler'] = ' '; - $Tab['libelle_ecriture'] = str_pad(self::trunc(dol_string_unaccent($data->doc_ref).' '.dol_string_unaccent($data->label_operation), 20), 20); + $Tab['libelle_ecriture'] = str_pad(self::trunc($data->doc_ref.' '.$data->label_operation, 20), 20); // Credit invoice - invert sens /* @@ -640,8 +648,8 @@ class AccountancyExport // TODO: we should filter more than only accent to avoid wrong line size // TODO: remove invoice number doc_ref in libelle, // TODO: we should offer an option for customer to build the libelle using invoice number / name / date in accounting software - //$Tab['libelle_ecriture2'] = str_pad(self::trunc(dol_string_unaccent($data->doc_ref) . ' ' . dol_string_unaccent($data->label_operation), 30), 30); - $Tab['libelle_ecriture2'] = str_pad(self::trunc(dol_string_unaccent($data->label_operation), 30), 30); + //$Tab['libelle_ecriture2'] = str_pad(self::trunc($data->doc_ref . ' ' . $data->label_operation, 30), 30); + $Tab['libelle_ecriture2'] = str_pad(self::trunc($data->label_operation, 30), 30); $Tab['codetva'] = str_repeat(' ', 2); // We need to keep the 10 lastest number of invoice doc_ref not the beginning part that is the unusefull almost same part From a27642cbfe91dd09627af0ab7600e9d5602aedf7 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Sat, 28 Jan 2023 10:32:07 +0100 Subject: [PATCH 803/816] better comment --- htdocs/core/class/commondocgenerator.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index b4eddcc252f..dda475e8c89 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -1279,7 +1279,7 @@ abstract class CommonDocGenerator $extrafieldOptionsKey = $extrafieldsKeyPrefix.$extrafieldKey; - // Load extrafiels if not allready does + // Load extra fields if they haven't been loaded already. if (empty($this->extrafieldsCache)) { $this->extrafieldsCache = new ExtraFields($this->db); } @@ -1605,7 +1605,7 @@ abstract class CommonDocGenerator return 0; } - // Load extrafiels if not allready does + // Load extra fields if they haven't been loaded already. if (empty($this->extrafieldsCache)) { $this->extrafieldsCache = new ExtraFields($this->db); } From 6cfe70dfe5144b07ef2c63bd6e74a96c12bcc9e9 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Sat, 28 Jan 2023 10:36:34 +0100 Subject: [PATCH 804/816] fix : Warning: Undefined array key label --- 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 dda475e8c89..9d18fccf423 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -1615,7 +1615,7 @@ abstract class CommonDocGenerator $extrafields = $this->extrafieldsCache; - if (!empty($extrafields->attributes[$object->table_element]) && is_array($extrafields->attributes[$object->table_element]['label'])) { + if (!empty($extrafields->attributes[$object->table_element]) && is_array($extrafields->attributes[$object->table_element]) && array_key_exists('label', $extrafields->attributes[$object->table_element]) && is_array($extrafields->attributes[$object->table_element]['label'])) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $label) { // Dont display separator yet even is set to be displayed (not compatible yet) if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') { From d3b1ee367ac0dec93e5d5be52a6f2b7a40500ff3 Mon Sep 17 00:00:00 2001 From: Eric Seigne Date: Sat, 28 Jan 2023 14:27:45 +0100 Subject: [PATCH 805/816] fix #23716 : handle hookmanagers returns --- htdocs/public/payment/newpayment.php | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 9cecbc90885..69ce8977030 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -212,6 +212,11 @@ $parameters = [ 'validpaymentmethod' => &$validpaymentmethod ]; $reshook = $hookmanager->executeHooks('doValidatePayment', $parameters, $object, $action); +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} elseif ($reshook > 0) { + print $hookmanager->resPrint; +} // Check security token $valid = true; @@ -1674,6 +1679,12 @@ if ($action != 'dopayment') 'object' => $object ]; $reshook = $hookmanager->executeHooks('doCheckStatus', $parameters, $object, $action); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } elseif ($reshook > 0) { + print $hookmanager->resPrint; + } + if ($source == 'order' && $object->billed) { print '

    '.$langs->trans("OrderBilled").''; @@ -1699,6 +1710,12 @@ if ($action != 'dopayment') 'paymentmethod' => $paymentmethod ]; $reshook = $hookmanager->executeHooks('doAddButton', $parameters, $object, $action); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } elseif ($reshook > 0) { + print $hookmanager->resPrint; + } + if ((empty($paymentmethod) || $paymentmethod == 'paybox') && !empty($conf->paybox->enabled)) { print '
    '; @@ -2299,9 +2316,13 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment 'dopayment' => GETPOST('dopayment', 'alpha') ]; $reshook = $hookmanager->executeHooks('doPayment', $parameters, $object, $action); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } elseif ($reshook > 0) { + print $hookmanager->resPrint; + } } - htmlPrintOnlinePaymentFooter($mysoc, $langs, 1, $suffix, $object); llxFooter('', 'public'); From f4bfe865214047ebdec4deefb901469e9f2b4016 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 28 Jan 2023 17:48:43 +0100 Subject: [PATCH 806/816] css --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index d464871941a..2a1ac8dc932 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -515,7 +515,7 @@ class Product extends CommonObject 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'index'=>1, 'position'=>1, 'comment'=>'Id'), 'ref' =>array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>5), - 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>2, 'position'=>15), + 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>2, 'position'=>15, 'csslist'=>'tdoverflowmax250'), 'barcode' =>array('type'=>'varchar(255)', 'label'=>'Barcode', 'enabled'=>'isModEnabled("barcode")', 'position'=>20, 'visible'=>-1, 'showoncombobox'=>3), 'fk_barcode_type' => array('type'=>'integer', 'label'=>'BarcodeType', 'enabled'=>'1', 'position'=>21, 'notnull'=>0, 'visible'=>-1,), 'note_public' =>array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>61), From a2a18ffb7173f05befdab55ebe8e827df39af969 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 28 Jan 2023 18:35:01 +0100 Subject: [PATCH 807/816] Trans --- htdocs/langs/en_US/mrp.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang index 6bdea0cc951..82cf7c38012 100644 --- a/htdocs/langs/en_US/mrp.lang +++ b/htdocs/langs/en_US/mrp.lang @@ -102,6 +102,7 @@ NbOperatorsRequired=Number of operators required THMOperatorEstimated=Estimated operator THM THMMachineEstimated=Estimated machine THM WorkstationType=Workstation type +DefaultWorkstation=Default workstation Human=Human Machine=Machine HumanMachine=Human / Machine From da3e228504bb3444c5e29af99cfd9159d95d536f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sat, 28 Jan 2023 18:45:37 +0100 Subject: [PATCH 808/816] input is too small --- htdocs/admin/mails_senderprofile_list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/mails_senderprofile_list.php b/htdocs/admin/mails_senderprofile_list.php index 95f57d5dfc5..a73b899dd00 100644 --- a/htdocs/admin/mails_senderprofile_list.php +++ b/htdocs/admin/mails_senderprofile_list.php @@ -416,7 +416,7 @@ if ($action != 'create') { print '
    '; print ''; + print ''; print '
    '.$langs->trans("ListOfExpiredServices").' '.$num.'
    '.$langs->trans("ListOfExpiredServices").' '.$num.'
    '.$langs->trans("Amount"); - print ''; - print ''.price($object->total_ttc, 0, $langs, 1, -1, -1, $conf->currency).''; - print '
    '.$langs->trans("Amount"); + $amount .= ''; + $amount .= ''.price($object->total_ttc, 0, $langs, 1, -1, -1, $conf->currency).''; + $amount .= '
    '.$langs->trans("Proposer"); print ''; @@ -496,13 +510,14 @@ if ($source == 'proposal') { print $langs->trans("DownloadDocument").''; } } - - print ''; print ''; print '
    '.$langs->trans("Label").'
    '.$langs->trans("Email").''; print img_picto('', 'email', 'class="pictofixedwidth"'); - print '
    '.$langs->trans("Signature").''; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; $doleditor = new DolEditor('signature', GETPOST('signature'), '', 138, 'dolibarr_notes', 'In', true, true, empty($conf->global->FCKEDITOR_ENABLE_USERSIGN) ? 0 : 1, ROWS_4, '90%'); From 474f5d74a2262b8d3937f5cd398269e5ba038eae Mon Sep 17 00:00:00 2001 From: notmarrco Date: Sun, 29 Jan 2023 01:31:44 +0100 Subject: [PATCH 809/816] feat(invoice): Add bankline id to listOfPayments fields --- htdocs/core/class/commoninvoice.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index d1eb324cc7f..dd0ec988062 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -332,6 +332,7 @@ abstract class CommonInvoice extends CommonObject $field = 'fk_facture'; $field2 = 'fk_paiement'; $field3 = ', p.ref_ext'; + $field4 = ', p.fk_bank'; // Bank line id $sharedentity = 'facture'; if ($this->element == 'facture_fourn' || $this->element == 'invoice_supplier') { $table = 'paiementfourn_facturefourn'; @@ -342,7 +343,7 @@ abstract class CommonInvoice extends CommonObject $sharedentity = 'facture_fourn'; } - $sql = "SELECT p.ref, pf.amount, pf.multicurrency_amount, p.fk_paiement, p.datep, p.num_paiement as num, t.code".$field3; + $sql = "SELECT p.ref, pf.amount, pf.multicurrency_amount, p.fk_paiement, p.datep, p.num_paiement as num, t.code".$field3 . $field4; $sql .= " FROM ".$this->db->prefix().$table." as pf, ".$this->db->prefix().$table2." as p, ".$this->db->prefix()."c_paiement as t"; $sql .= " WHERE pf.".$field." = ".((int) $this->id); $sql .= " AND pf.".$field2." = p.rowid"; @@ -363,6 +364,9 @@ abstract class CommonInvoice extends CommonObject if (!empty($field3)) { $tmp['ref_ext'] = $obj->ref_ext; } + if (!empty($field4)) { + $tmp['fk_bank_line'] = $obj->fk_bank; + } $retarray[] = $tmp; $i++; } From b963ddb0bc27daae5e2cb6e1d13c9720a6b83386 Mon Sep 17 00:00:00 2001 From: daraelmin Date: Sun, 29 Jan 2023 14:33:13 +0100 Subject: [PATCH 810/816] Fix PHP8 Warning --- htdocs/core/modules/project/task/mod_task_universal.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/core/modules/project/task/mod_task_universal.php b/htdocs/core/modules/project/task/mod_task_universal.php index 6de02dcaf99..ba61a0363df 100644 --- a/htdocs/core/modules/project/task/mod_task_universal.php +++ b/htdocs/core/modules/project/task/mod_task_universal.php @@ -128,8 +128,7 @@ class mod_task_universal extends ModeleNumRefTask require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; - // On defini critere recherche compteur - $mask = $conf->global->PROJECT_TASK_UNIVERSAL_MASK; + $mask = !empty($conf->global->PROJECT_TASK_UNIVERSAL_MASK) ? $conf->global->PROJECT_TASK_UNIVERSAL_MASK : ''; if (!$mask) { $this->error = 'NotConfigured'; From b0332730a6e9ac64f4757c043fa2baced81278dd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 29 Jan 2023 18:45:09 +0100 Subject: [PATCH 811/816] Fix count --- htdocs/contrat/list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php index 31d489c4b1f..38c37c1389e 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -469,6 +469,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { } else { /* 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('/LEFT JOIN '.MAIN_DB_PREFIX.'contratdet as cd ON c.rowid = cd.fk_contrat /', '', $sqlforcount); $sqlforcount = preg_replace('/GROUP BY.*$/', '', $sqlforcount); $resql = $db->query($sqlforcount); From 22ffef7b4e2b2e1fa40863256167eb35b391b91f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 29 Jan 2023 20:25:42 +0100 Subject: [PATCH 812/816] Update card.php --- htdocs/compta/paiement/card.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/paiement/card.php b/htdocs/compta/paiement/card.php index 14442e6c965..36f14dca2fc 100644 --- a/htdocs/compta/paiement/card.php +++ b/htdocs/compta/paiement/card.php @@ -46,7 +46,8 @@ $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $backtopage = GETPOST('backtopage', 'alpha'); -$socid = GETPOST('socid', 'int'); if ($socid < 0) { +$socid = GETPOST('socid', 'int'); +if ($socid < 0) { $socid = 0; } From 244239d44db2104570f37dcc13016a95d51174e9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 29 Jan 2023 20:52:24 +0100 Subject: [PATCH 813/816] Doc --- dev/dolibarr_changes.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/dolibarr_changes.txt b/dev/dolibarr_changes.txt index 461db52f959..e12c237e28e 100644 --- a/dev/dolibarr_changes.txt +++ b/dev/dolibarr_changes.txt @@ -209,6 +209,11 @@ with with foreach ($value[1] as $k => $v) { +* Fix by replacing + if ($res[0] == PDF_TYPE_OBJECT) +with + if ($res && $res[0] == PDF_TYPE_OBJECT) + JSGANTT: From d03ec374d083c832f8858e515b04c7c098bf09a3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 30 Jan 2023 02:21:54 +0100 Subject: [PATCH 814/816] NEW Can set a checkbox in formconfirm by clicking on the label --- htdocs/accountancy/class/accountancyexport.class.php | 2 +- htdocs/core/class/html.form.class.php | 2 +- htdocs/core/modules/modAccounting.class.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 4c6e2d09838..cec3cc5be73 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -203,7 +203,7 @@ class AccountancyExport 'ACCOUNTING_EXPORT_FORMAT' => empty($conf->global->ACCOUNTING_EXPORT_FORMAT) ? 'txt' : $conf->global->ACCOUNTING_EXPORT_FORMAT, 'ACCOUNTING_EXPORT_SEPARATORCSV' => empty($conf->global->ACCOUNTING_EXPORT_SEPARATORCSV) ? ',' : $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV, 'ACCOUNTING_EXPORT_ENDLINE' => empty($conf->global->ACCOUNTING_EXPORT_ENDLINE) ? 1 : $conf->global->ACCOUNTING_EXPORT_ENDLINE, - 'ACCOUNTING_EXPORT_DATE' => empty($conf->global->ACCOUNTING_EXPORT_DATE) ? '%d%m%Y' : $conf->global->ACCOUNTING_EXPORT_DATE, + 'ACCOUNTING_EXPORT_DATE' => getDolGlobalString('ACCOUNTING_EXPORT_DATE', '%Y-%m-%d'), ), self::$EXPORT_TYPE_CEGID => array( 'label' => $langs->trans('Modelcsv_CEGID'), diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 7ed3f76c4bf..a9e69ed9b2b 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5109,7 +5109,7 @@ class Form $more .= ''."\n"; } elseif ($input['type'] == 'checkbox') { $more .= '
    '; - $more .= '
    '.$input['label'].'
    '; + $more .= '
    '; $more .= 'const[11] = array( "ACCOUNTING_EXPORT_DATE", "chaine", - "%d%m%Y", + "%Y-%m-%d", "", 0, 'current', 0 ); $this->const[12] = array( @@ -338,7 +338,7 @@ class modAccounting extends DolibarrModules 'b.sens'=>'C' // This field is still used by accounting export. We can remove it once it has been replace into accountancyexport.class.php by a detection using ->debit and ->credit ); - // General ledger - Fichier FEC + // General ledger - File FEC $r++; $this->import_code[$r] = $this->rights_class.'_'.$r; $this->import_label[$r] = 'ImportAccountingEntriesFECFormat'; From 3fdc32337871ce06dda75eda1b251cc452fbfe7d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 30 Jan 2023 02:41:13 +0100 Subject: [PATCH 815/816] Fix menu --- htdocs/core/menus/standard/eldy.lib.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index bf75035f333..d04cf9edc1a 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1726,7 +1726,10 @@ function get_left_menu_accountancy($mainmenu, &$newmenu, $usemenuhider = 1, $lef if ($nature) { $langs->load('accountancy'); - $journallabel = $langs->transnoentities($objp->label); // Label of bank account in llx_accounting_journal + $journallabel = ''; + if ($objp->label) { + $journallabel = '('.$langs->transnoentities($objp->label).')'; // Label of bank account in llx_accounting_journal + } $key = $langs->trans("AccountingJournalType".strtoupper($objp->nature)); $transferlabel = ($objp->nature && $key != "AccountingJournalType".strtoupper($langs->trans($objp->nature)) ? $key.($journallabel != $key ? ' '.$journallabel : ''): $journallabel); From 1fe08ad3b84beb95fece41902c98a936c6729b13 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 30 Jan 2023 02:56:29 +0100 Subject: [PATCH 816/816] Fix missing hook --- htdocs/core/lib/payments.lib.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 44691f7c2c4..29947dda57c 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -146,7 +146,7 @@ function payment_supplier_prepare_head(Paiement $object) */ function getValidOnlinePaymentMethods($paymentmethod = '') { - global $conf, $langs; + global $conf, $langs, $hookmanager, $action; $validpaymentmethod = array(); @@ -162,8 +162,24 @@ function getValidOnlinePaymentMethods($paymentmethod = '') $langs->load("stripe"); $validpaymentmethod['stripe'] = 'valid'; } - // TODO Add trigger + // This hook is used to complete the $validpaymentmethod array so an external payment modules + // can add its own key (ie 'payzen' for Payzen, ...) + $parameters = [ + 'paymentmethod' => $paymentmethod, + 'validpaymentmethod' => &$validpaymentmethod + ]; + $tmpobject = new stdClass(); + $reshook = $hookmanager->executeHooks('getValidPayment', $parameters, $tmpobject, $action); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } elseif (!empty($hookmanager->resArray['validpaymentmethod'])) { + if ($reshook == 0) { + $validpaymentmethod = array_merge($validpaymentmethod, $hookmanager->resArray['validpaymentmethod']); + } else { + $validpaymentmethod = $hookmanager->resArray['validpaymentmethod']; + } + } return $validpaymentmethod; }