diff --git a/COPYRIGHT b/COPYRIGHT index a5e1f4a4005..a2101a1db0a 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -50,8 +50,8 @@ TCPDI 1.0.0 LGPL-3+ / Apache 2.0 Yes JS libraries: Ace 1.4.14 BSD Yes JS library to get code syntaxique coloration in a textarea. ChartJS 3.7.1 MIT License Yes JS library for graph -jQuery 3.5.1 MIT License Yes JS library -jQuery UI 1.12.1 GPL and MIT License Yes JS library plugin UI +jQuery 3.6.0 MIT License Yes JS library +jQuery UI 1.13.1 GPL and MIT License Yes JS library plugin UI jQuery select2 4.0.13 GPL and Apache License Yes JS library plugin for sexier multiselect. Warning: 4.0.6+ create troubles without patching css jQuery blockUI 2.70.0 GPL and MIT License Yes JS library plugin blockUI (to use ajax popups) jQuery Colorpicker 1.1 MIT License Yes JS library for color picker for a defined list of colors diff --git a/ChangeLog b/ChangeLog index 880406bb189..31bfa1c1cff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,7 +9,8 @@ English Dolibarr ChangeLog For users: --------------- -NEW: ... +NEW: PHP 8.0 compatibility + Modules diff --git a/dev/resources/iso-normes/currencies_iso-4217.txt b/dev/resources/iso-normes/currencies_iso-4217.txt index bc392b72e9c..e24faa4283e 100644 --- a/dev/resources/iso-normes/currencies_iso-4217.txt +++ b/dev/resources/iso-normes/currencies_iso-4217.txt @@ -1,8 +1,12 @@ # File of all ISO-4217 currencies codes -# http://en.wikipedia.org/wiki/ISO_4217 -# http://fx.sauder.ubc.ca/currency_table.html for symbols for 2 letter code # -# Code,Name,Nb decimals +# https://en.wikipedia.org/wiki/ISO_4217 +# https://en.wikipedia.org/wiki/Currency_symbol for symbols for 2 letter code +# + + +# Code, Currency Name, Nb decimals + AED,UAE Dirham,2 AFN,Afghanistan Afghani,2 ALL,Albanian Lek,2 diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 996f2d16c8d..e58def3f481 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -505,7 +505,7 @@ if (GETPOSTISSET("search_status")) { if ($search_type > 0) { $membertype = new AdherentType($db); - $result = $membertype->fetch(GETPOST("type", 'int')); + $result = $membertype->fetch($search_type); $titre .= " (".$membertype->label.")"; } @@ -767,7 +767,7 @@ if (!empty($arrayfields['d.email']['checked'])) { } // End of subscription date if (!empty($arrayfields['d.datefin']['checked'])) { - print '
| ' . $langs->trans('ExpenseReportApplyTo') . ' | '; - echo '' . $langs->trans('Type') . ' | '; - echo '' . $langs->trans('ExpenseReportLimitOn') . ' | '; - echo '' . $langs->trans('ExpenseReportDateStart') . ' | '; - echo '' . $langs->trans('ExpenseReportDateEnd') . ' | '; - echo '' . $langs->trans('ExpenseReportLimitAmount') . ' | '; - echo '' . $langs->trans('ExpenseReportRestrictive') . ' | '; + echo '|||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ' . $langs->trans('ExpenseReportApplyTo') . ' | '; + echo '' . $langs->trans('Type') . ' | '; + echo '' . $langs->trans('ExpenseReportLimitOn') . ' | '; + echo '' . $langs->trans('ExpenseReportDateStart') . ' | '; + echo '' . $langs->trans('ExpenseReportDateEnd') . ' | '; + echo '' . $langs->trans('ExpenseReportLimitAmount') . ' | '; + echo '' . $langs->trans('ExpenseReportRestrictive') . ' | '; echo ''; echo ' | ||||||
| ';
- echo ' ' . $form->selectarray('apply_to', $tab_apply, '', 0) . ' ';
- echo '' . $form->select_dolusers('', 'fk_user') . ' ';
- echo '' . $form->select_dolgroups('', 'fk_usergroup') . ' ';
+ echo '' . $form->selectarray('apply_to', $tab_apply, '', 0) . ' ';
+ echo '' . $form->select_dolusers('', 'fk_user') . ' ';
+ echo '' . $form->select_dolgroups('', 'fk_usergroup') . ' ';
echo ' | ';
- echo '' . $form->selectExpense('', 'fk_c_type_fees', 0, 1, 1) . ' | '; - echo '' . $form->selectarray('code_expense_rules_type', $tab_rules_type, '', 0) . ' | '; - echo '' . $form->selectDate(strtotime(date('Y-m-01', dol_now())), 'start', '', '', 0, '', 1, 0) . ' | '; - echo '' . $form->selectDate(strtotime(date('Y-m-t', dol_now())), 'end', '', '', 0, '', 1, 0) . ' | '; - echo '' . $conf->currency . ' | '; - echo '' . $form->selectyesno('restrictive', 0, 1) . ' | '; - echo ''; + echo ' | ' . $form->selectExpense('', 'fk_c_type_fees', 0, 1, 1) . ' | '; + echo '' . $form->selectarray('code_expense_rules_type', $tab_rules_type, '', 0) . ' | '; + echo '' . $form->selectDate(strtotime(date('Y-m-01', dol_now())), 'start', '', '', 0, '', 1, 0) . ' | '; + echo '' . $conf->currency . ' | '; + echo '' . $form->selectyesno('restrictive', 0, 1) . ' | '; + echo ''; echo ' |
| ' . $langs->trans('ExpenseReportApplyTo') . ' | '; - echo '' . $langs->trans('Type') . ' | '; - echo '' . $langs->trans('ExpenseReportLimitOn') . ' | '; - echo '' . $langs->trans('ExpenseReportDateStart') . ' | '; - echo '' . $langs->trans('ExpenseReportDateEnd') . ' | '; - echo '' . $langs->trans('ExpenseReportLimitAmount') . ' | '; - echo '' . $langs->trans('ExpenseReportRestrictive') . ' | '; + echo '|||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ' . $langs->trans('ExpenseReportApplyTo') . ' | '; + echo '' . $langs->trans('Type') . ' | '; + echo '' . $langs->trans('ExpenseReportLimitOn') . ' | '; + echo '' . $langs->trans('ExpenseReportDateStart') . ' | '; + echo '' . $langs->trans('ExpenseReportDateEnd') . ' | '; + echo '' . $langs->trans('ExpenseReportLimitAmount') . ' | '; + echo '' . $langs->trans('ExpenseReportRestrictive') . ' | '; echo ''; echo ' | ||||||
| '; + echo ' | ';
if ($action == 'edit' && $object->id == $rule->id) {
$selected = ($object->is_for_all > 0) ? 'A' : ($object->fk_usergroup > 0 ? 'G' : 'U');
echo ' ' . $form->selectarray('apply_to', $tab_apply, $selected, 0) . ' ';
@@ -259,7 +259,7 @@ foreach ($rules as $rule) {
echo ' | ';
- echo ''; + echo ' | '; if ($action == 'edit' && $object->id == $rule->id) { echo $form->selectExpense($object->fk_c_type_fees, 'fk_c_type_fees', 0, 1, 1); } else { @@ -278,7 +278,7 @@ foreach ($rules as $rule) { echo ' | '; - echo ''; + echo ' | '; if ($action == 'edit' && $object->id == $rule->id) { echo $form->selectarray('code_expense_rules_type', $tab_rules_type, $object->code_expense_rules_type, 0); } else { @@ -287,7 +287,7 @@ foreach ($rules as $rule) { echo ' | '; - echo ''; + echo ' | '; if ($action == 'edit' && $object->id == $rule->id) { print $form->selectDate(strtotime(date('Y-m-d', $object->dates)), 'start', '', '', 0, '', 1, 0); } else { @@ -296,7 +296,7 @@ foreach ($rules as $rule) { echo ' | '; - echo ''; + echo ' | '; if ($action == 'edit' && $object->id == $rule->id) { print $form->selectDate(strtotime(date('Y-m-d', $object->datee)), 'end', '', '', 0, '', 1, 0); } else { @@ -305,7 +305,7 @@ foreach ($rules as $rule) { echo ' | '; - echo ''; + echo ' | '; if ($action == 'edit' && $object->id == $rule->id) { echo '' . $conf->currency; } else { @@ -314,7 +314,7 @@ foreach ($rules as $rule) { echo ' | '; - echo ''; + echo ' | ';
if ($action == 'edit' && $object->id == $rule->id) {
echo $form->selectyesno('restrictive', $object->restrictive, 1);
} else {
diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php
index 40656928824..8a480ea49ca 100644
--- a/htdocs/admin/system/security.php
+++ b/htdocs/admin/system/security.php
@@ -266,10 +266,20 @@ print ' '; print '$dolibarr_main_restrict_ip: '; if (empty($dolibarr_main_restrict_ip)) { - print ''.$langs->trans("None").''; + print $langs->trans("None"); //print ' ('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("IPsOfUsers")).')'; +} else { + print $dolibarr_main_restrict_ip; } +print ' '; +print '$dolibarr_main_restrict_os_commands: '; +if (empty($dolibarr_main_restrict_os_commands)) { + print $langs->trans("None"); +} else { + print $dolibarr_main_restrict_os_commands; +} +print ' ('.$langs->trans("RecommendedValueIs", 'mysqldump, mysql, pg_dump, pgrestore').')'; print ' '; if (empty($conf->global->SECURITY_DISABLE_TEST_ON_OBFUSCATED_CONF)) { diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 09f69993310..86e07ed424d 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1103,6 +1103,23 @@ class BOM extends CommonObject } } + /** + * Function used to replace a product id with another one. + * + * @param DoliDB $db Database handler + * @param int $origin_id Old product id + * @param int $dest_id New product id + * @return bool + */ + public static function replaceProduct(DoliDB $db, $origin_id, $dest_id) + { + $tables = array( + 'bom_bomline' + ); + + return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables); + } + /** * Get Net needs by product * diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index a5b4f1d8ce9..ac26cf0c56a 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -868,6 +868,16 @@ class ActionComm extends CommonObject $this->event_paid = $obj->event_paid; $this->status = $obj->status; + //email information + $this->email_msgid=$obj->email_msgid; + $this->email_from=$obj->email_from; + $this->email_sender=$obj->email_sender; + $this->email_to=$obj->email_to; + $this->email_tocc=$obj->email_tocc; + $this->email_tobcc=$obj->email_tobcc; + $this->email_subject=$obj->email_subject; + $this->errors_to=$obj->errors_to; + $this->fetch_optionals(); if ($loadresources) { @@ -1582,8 +1592,25 @@ class ActionComm extends CommonObject if (isset($this->transparency)) { $tooltip .= ' '.$langs->trans('Busy').': '.yn($this->transparency); } + if (!empty($this->email_msgid)) { + $langs->load("mails"); + $tooltip .= ' '; + //$tooltip .= ' '.img_picto('', 'email').' '.$langs->trans("Email").''; + $tooltip .= ' '.$langs->trans('MailTopic').': '.$this->email_subject; + $tooltip .= ' '.$langs->trans('MailFrom').': '.str_replace(array('<', '>'), array('<', '>'), $this->email_from); + $tooltip .= ' '.$langs->trans('MailTo').':, '.str_replace(array('<', '>'), array('<', '>'), $this->email_to); + if (!empty($this->email_tocc)) { + $tooltip .= ' '.$langs->trans('MailCC').': '.str_replace(array('<', '>'), array('<', '>'), $this->email_tocc); + } + /* Disabled because bcc must remain by defintion not visible + if (!empty($this->email_tobcc)) { + $tooltip .= ' '.$langs->trans('MailCCC').': '.$this->email_tobcc; + } */ + } if (!empty($this->note_private)) { - $tooltip .= ' '.$langs->trans('Note').': '.(dol_textishtml($this->note_private) ? str_replace(array("\r", "\n"), "", $this->note_private) : str_replace(array("\r", "\n"), ' ', $this->note_private)); + $tooltip .= ' '.$langs->trans('Description').': '; + $texttoshow = dolGetFirstLineOfText($this->note_private, 10); + $tooltip .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), ' ', $texttoshow)); } $linkclose = ''; //if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && $this->type_color) @@ -1594,9 +1621,8 @@ class ActionComm extends CommonObject $label = $langs->trans("ShowAction"); $linkclose .= ' alt="'.dol_escape_htmltag($tooltip, 1).'"'; } - $linkclose .= ' title="'.dol_escape_htmltag($tooltip, 1).'"'; + $linkclose .= ' title="'.dol_escape_htmltag($tooltip, 1, 0, 0, '', 1).'"'; $linkclose .= ' class="'.$classname.' classfortooltip"'; - /* $hookmanager->initHooks(array('actiondao')); $parameters=array('id'=>$this->id); @@ -2210,6 +2236,26 @@ class ActionComm extends CommonObject return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + /** + * Function used to replace a product id with another one. + * + * @param DoliDB $dbs Database handler + * @param int $origin_id Old product id + * @param int $dest_id New product id + * @return bool + */ + public static function replaceProduct(DoliDB $dbs, $origin_id, $dest_id) + { + $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'actioncomm SET fk_element = ' . ((int) $dest_id) . ' WHERE elementtype="product" AND fk_element = '.((int) $origin_id); + // using $dbs, not $this->db because function is static + if (!$dbs->query($sql)) { + //$this->errors = $dbs->lasterror(); + return false; + } + + return true; + } + /** * Is the action delayed? * diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 10903ea3556..d73a9769d17 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1892,11 +1892,13 @@ if ($action == 'create') { $title = $langs->trans('ProductsAndServices'); print load_fiche_titre($title); + print ' ';
print ' ';
}
} elseif ($object->id > 0) {
/*
diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php
index a30fc456b18..be10e45383c 100644
--- a/htdocs/comm/propal/class/propal.class.php
+++ b/htdocs/comm/propal/class/propal.class.php
@@ -3821,8 +3821,24 @@ class Propal extends CommonObject
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
-}
+ /**
+ * Function used to replace a product id with another one.
+ *
+ * @param DoliDB $db Database handler
+ * @param int $origin_id Old product id
+ * @param int $dest_id New product id
+ * @return bool
+ */
+ public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
+ {
+ $tables = array(
+ 'propaldet'
+ );
+
+ return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
+ }
+}
/**
* Class to manage commercial proposal lines
diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php
index e8f88800693..b54784a82b2 100644
--- a/htdocs/commande/card.php
+++ b/htdocs/commande/card.php
@@ -1862,11 +1862,13 @@ if ($action == 'create' && $usercancreate) {
$title = $langs->trans('ProductsAndServices');
print load_fiche_titre($title);
+ print '';
print ' ';
}
print '';
diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php
index 4c745948f52..f17006738bf 100644
--- a/htdocs/commande/class/commande.class.php
+++ b/htdocs/commande/class/commande.class.php
@@ -4039,6 +4039,23 @@ class Commande extends CommonOrder
return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
}
+ /**
+ * Function used to replace a product id with another one.
+ *
+ * @param DoliDB $db Database handler
+ * @param int $origin_id Old product id
+ * @param int $dest_id New product id
+ * @return bool
+ */
+ public static function replaceProduct(DoliDB $db, $origin_id, $dest_id)
+ {
+ $tables = array(
+ 'commandedet',
+ );
+
+ return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables);
+ }
+
/**
* Is the customer order delayed?
*
diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php
index b0444b90dcc..8ca3272dd78 100644
--- a/htdocs/compta/bank/card.php
+++ b/htdocs/compta/bank/card.php
@@ -65,7 +65,7 @@ $hookmanager->initHooks(array('bankcard', 'globalcard'));
// Security check
$id = GETPOST("id", 'int') ? GETPOST("id", 'int') : GETPOST('ref', 'alpha');
-$fieldid = GETPOST("id") ? 'rowid' : 'ref';
+$fieldid = GETPOST("id", 'int') ? 'rowid' : 'ref';
$result = restrictedArea($user, 'banque', $id, 'bank_account&bank_account', '', '', $fieldid);
diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php
index 219d8bee154..324800910da 100644
--- a/htdocs/compta/bank/class/account.class.php
+++ b/htdocs/compta/bank/class/account.class.php
@@ -1728,7 +1728,7 @@ class Account extends CommonObject
if ($dbs->query($sql)) {
return true;
} else {
- //if ($ignoreerrors) return true; // TODO Not enough. If there is A-B on kept thirdarty and B-C on old one, we must get A-B-C after merge. Not A-B.
+ //if ($ignoreerrors) return true; // TODO Not enough. If there is A-B on kept thirdparty and B-C on old one, we must get A-B-C after merge. Not A-B.
//$this->errors = $dbs->lasterror();
return false;
}
diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php
index 102e0cf7f4a..2cf5e13ff8b 100644
--- a/htdocs/compta/facture/card.php
+++ b/htdocs/compta/facture/card.php
@@ -2560,9 +2560,10 @@ if (empty($reshook)) {
setEventMessages($mesg, null, 'warnings');
$result = -1;
} else {
- $object->update_percent($line, GETPOST('all_progress'));
+ $object->update_percent($line, GETPOST('all_progress'), false);
}
}
+ $object->update_price(1);
}
} elseif ($action == 'updateline' && $usercancreate && !$cancel) {
header('Location: '.$_SERVER["PHP_SELF"].'?facid='.$id); // To show again edited page
@@ -3522,7 +3523,7 @@ if ($action == 'create') {
if ($socid > 0) {
// Discounts for third party
- print ' |
| '.$langs->trans('Discounts').' | '; + print ' | ||||||||||||
| '.$langs->trans('DiscountStillRemaining').' | ';
$thirdparty = $soc;
$discount_type = 0;
@@ -3815,11 +3816,13 @@ if ($action == 'create') {
$title = $langs->trans('ProductsAndServices');
print load_fiche_titre($title);
+ print ' ';
print ' ';
}
print "\n";
@@ -4353,8 +4356,8 @@ if ($action == 'create') {
// Relative and absolute discounts
print ''."\n";
- print ' | ||||||||||||
| '.$langs->trans('Discounts'); - print ' | '; + print ' | ||||||||||||
| '.$langs->trans('DiscountStillRemaining').' | '; + print '';
$thirdparty = $soc;
$discount_type = 0;
$backtopage = urlencode($_SERVER["PHP_SELF"].'?facid='.$object->id);
@@ -5220,7 +5223,7 @@ if ($action == 'create') {
print '';
print '';
- print ' '; + print ' '; if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { $blocname = 'contacts'; diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 290467a9d54..91d0fd0f20a 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -1759,6 +1759,23 @@ class FactureRec extends CommonInvoice return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + /** + * Function used to replace a product id with another one. + * + * @param DoliDB $db Database handler + * @param int $origin_id Old product id + * @param int $dest_id New product id + * @return bool + */ + public static function replaceProduct(DoliDB $db, $origin_id, $dest_id) + { + $tables = array( + 'facturedet_rec' + ); + + return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables); + } + /** * Update frequency and unit * diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index af029376d53..2b368d7bd75 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3725,11 +3725,12 @@ class Facture extends CommonInvoice /** * Update invoice line with percentage * - * @param FactureLigne $line Invoice line - * @param int $percent Percentage + * @param FactureLigne $line Invoice line + * @param int $percent Percentage + * @param boolean $update_price Update object price * @return void */ - public function update_percent($line, $percent) + public function update_percent($line, $percent, $update_price = true) { // phpcs:enable global $mysoc, $user; @@ -3756,7 +3757,11 @@ class Facture extends CommonInvoice $line->multicurrency_total_tva = $tabprice[17]; $line->multicurrency_total_ttc = $tabprice[18]; $line->update($user); - $this->update_price(1); + + // sometimes it is better to not update price for each line, ie when updating situation on all lines + if ($update_price) { + $this->update_price(1); + } } /** @@ -4818,6 +4823,23 @@ class Facture extends CommonInvoice return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + /** + * Function used to replace a product id with another one. + * + * @param DoliDB $db Database handler + * @param int $origin_id Old product id + * @param int $dest_id New product id + * @return bool + */ + public static function replaceProduct(DoliDB $db, $origin_id, $dest_id) + { + $tables = array( + 'facturedet' + ); + + return CommonObject::commonReplaceProduct($db, $origin_id, $dest_id, $tables); + } + /** * Is the customer invoice delayed? * diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 02c0ec21e7a..eedc3297018 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -598,6 +598,9 @@ if (!empty($search_categ_cus) && $search_categ_cus != '-1') { } $sql .= ', '.MAIN_DB_PREFIX.'facture as f'; +if ($sortfield == "f.datef") { + $sql .= $db->hintindex('idx_facture_datef'); +} if (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 (f.rowid = ef.fk_object)"; } @@ -846,6 +849,37 @@ $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; +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + /* This old and fast method to get and count full list returns all record so use a high amount of memory. + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + */ + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + if ($sall || $search_product_category > 0 || $search_user > 0) { + $sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/', 'SELECT COUNT(DISTINCT f.rowid) as nbtotalofrecords FROM', $sql); + } else { + $sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/', 'SELECT COUNT(f.rowid) as nbtotalofrecords FROM', $sql); + $sqlforcount = preg_replace('/LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON pf.fk_facture = f.rowid/', '', $sqlforcount); + } + $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 of record found is smaller than page * limit, goto and load page 0 + $page = 0; + $offset = 0; + } + $db->free($resql); +} + +// Complete request and execute it with limit $sql .= ' ORDER BY '; $listfield = explode(',', $sortfield); $listorder = explode(',', $sortorder); @@ -853,19 +887,10 @@ foreach ($listfield as $key => $value) { $sql .= $listfield[$key].' '.($listorder[$key] ? $listorder[$key] : 'DESC').','; } $sql .= ' f.rowid DESC '; - -$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; - } +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); } -$sql .= $db->plimit($limit + 1, $offset); - $resql = $db->query($sql); if ($resql) { diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 229bfc0530b..ee1d10181ca 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -624,7 +624,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { */ $object->canvas = $canvas; - $object->state_id = GETPOST("state_id"); + $object->state_id = GETPOST("state_id", "int"); // We set country_id, country_code and label for the selected country $object->country_id = GETPOST("country_id") ? GETPOST("country_id", "int") : (empty($objsoc->country_id) ? $mysoc->country_id : $objsoc->country_id); @@ -697,7 +697,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ' | ||||||||||||
| '; - print img_picto('', 'company').$form->select_company($socid, 'socid', '', 'SelectThirdParty'); + print img_picto('', 'company').$form->select_company($socid, 'socid', '', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300 maxwidth500 widthcentpercentminusxx'); print ' | '.$langs->trans('Unit').' | '; } print ''.$langs->trans('ReductionShort').' | '; + print ''.$langs->trans('TotalHT').' | '; print ''.$form->showCheckAddButtons('checkforselect', 1).' | '; print ''; $i = 0; @@ -5078,6 +5094,7 @@ abstract class CommonObject } $this->tpl['price'] = price($line->subprice); + $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)) { @@ -5602,7 +5619,10 @@ abstract class CommonObject { // phpcs:enable global $langs, $conf; - + if (!empty(self::TRIGGER_PREFIX) && strpos($triggerName, self::TRIGGER_PREFIX . '_') !== 0) { + dol_print_error('', 'The trigger "' . $triggerName . '" does not start with "' . self::TRIGGER_PREFIX . '_" as required.'); + exit; + } if (!is_object($langs)) { // If lang was not defined, we set it. It is required by run_triggers. include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php'; $langs = new Translate('', $conf); @@ -8104,7 +8124,7 @@ abstract class CommonObject /** * Function used to replace a thirdparty id with another one. - * This function is meant to be called from replaceThirdparty with the appropiate tables + * This function is meant to be called from replaceThirdparty with the appropriate tables * Column name fk_soc MUST be used to identify thirdparties * * @param DoliDB $db Database handler @@ -8121,7 +8141,36 @@ abstract class CommonObject if (!$db->query($sql)) { if ($ignoreerrors) { - return true; // TODO Not enough. If there is A-B on kept thirdarty and B-C on old one, we must get A-B-C after merge. Not A-B. + return true; // TODO Not enough. If there is A-B on kept thirdparty and B-C on old one, we must get A-B-C after merge. Not A-B. + } + //$this->errors = $db->lasterror(); + return false; + } + } + + return true; + } + + /** + * Function used to replace a product id with another one. + * This function is meant to be called from replaceProduct with the appropriate tables + * Column name fk_product MUST be used to identify products + * + * @param DoliDB $db Database handler + * @param int $origin_id Old product id (the product to delete) + * @param int $dest_id New product id (the product that will received element of the other) + * @param string[] $tables Tables that need to be changed + * @param int $ignoreerrors Ignore errors. Return true even if errors. We need this when replacement can fails like for categories (categorie of old product may already exists on new one) + * @return bool True if success, False if error + */ + public static function commonReplaceProduct(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors = 0) + { + foreach ($tables as $table) { + $sql = 'UPDATE '.MAIN_DB_PREFIX.$table.' SET fk_product = '.((int) $dest_id).' WHERE fk_product = '.((int) $origin_id); + + if (!$db->query($sql)) { + if ($ignoreerrors) { + return true; // TODO Not enough. If there is A-B on kept product and B-C on old one, we must get A-B-C after merge. Not A-B. } //$this->errors = $db->lasterror(); return false; diff --git a/htdocs/core/class/discount.class.php b/htdocs/core/class/discount.class.php index bdc5e746566..dff1383a629 100644 --- a/htdocs/core/class/discount.class.php +++ b/htdocs/core/class/discount.class.php @@ -562,7 +562,7 @@ class DiscountAbsolute * Should always be empty, except if option FACTURE_DEPOSITS_ARE_JUST_PAYMENTS is on (not recommended). * * @param CommonInvoice $invoice Object invoice (customer of supplier) - * @param int $multicurrency 1=Return multicurrency_amount instead of amount + * @param int $multicurrency 1=Return multicurrency_amount instead of amount. TODO Add a mode multicurrency = -1 to return array with amount + multicurrency amount * @return int <0 if KO, Sum of credit notes and deposits amount otherwise */ public function getSumDepositsUsed($invoice, $multicurrency = 0) @@ -603,7 +603,7 @@ class DiscountAbsolute * Return amount (with tax) of all credit notes invoices + excess received used by invoice as a payment * * @param CommonInvoice $invoice Object invoice - * @param int $multicurrency 1=Return multicurrency_amount instead of amount + * @param int $multicurrency 1=Return multicurrency_amount instead of amount. TODO Add a mode multicurrency = -1 to return array with amount + multicurrency amount * @return int <0 if KO, Sum of credit notes and excess received amount otherwise */ public function getSumCreditNotesUsed($invoice, $multicurrency = 0) @@ -643,7 +643,7 @@ class DiscountAbsolute * Return amount (with tax) of all converted amount for this credit note * * @param CommonInvoice $invoice Object invoice - * @param int $multicurrency Return multicurrency_amount instead of amount + * @param int $multicurrency Return multicurrency_amount instead of amount. TODO Add a mode multicurrency = -1 to return array with amount + multicurrency amount * @return int <0 if KO, Sum of credit notes and deposits amount otherwise */ public function getSumFromThisCreditNotesNotUsed($invoice, $multicurrency = 0) diff --git a/htdocs/core/class/dolgraph.class.php b/htdocs/core/class/dolgraph.class.php index b46ca096547..488becd06b7 100644 --- a/htdocs/core/class/dolgraph.class.php +++ b/htdocs/core/class/dolgraph.class.php @@ -1303,11 +1303,13 @@ class DolGraph $this->stringtoshow .= $xaxis; /* For Chartjs v2.9 */ + /* if (empty($showlegend)) { $this->stringtoshow .= 'legend: { display: false }, '."\n"; } else { $this->stringtoshow .= 'legend: { maxWidth: '.round($this->width / 2).', labels: { boxWidth: 15 }, position: \'' . ($showlegend == 2 ? 'right' : 'top') . '\' }, '."\n"; } + */ /* For Chartjs v3.5 */ $this->stringtoshow .= 'plugins: { '."\n"; @@ -1318,7 +1320,9 @@ class DolGraph } $this->stringtoshow .= "}, \n"; - $this->stringtoshow .= 'scales: { xAxes: [{ '; + /* For Chartjs v2.9 */ + /* + $this->stringtoshow .= 'scales: { xAxis: [{ '; if ($this->hideXValues) { $this->stringtoshow .= ' ticks: { display: false }, display: true,'; } @@ -1328,11 +1332,12 @@ class DolGraph $this->stringtoshow .= ', stacked: true'; } $this->stringtoshow .= ' }]'; - $this->stringtoshow .= ', yAxes: [{ ticks: { beginAtZero: true }'; + $this->stringtoshow .= ', yAxis: [{ ticks: { beginAtZero: true }'; if ($type == 'bar' && count($arrayofgroupslegend) > 0) { $this->stringtoshow .= ', stacked: true'; } $this->stringtoshow .= ' }] }'; + */ // Add a callback to change label to show only positive value if (is_array($this->tooltipsLabels) || is_array($this->tooltipsTitles)) { diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index a40ec3e30c3..5f87d81db9d 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -195,6 +195,7 @@ class HookManager 'getFormatedSupplierRef', 'getIdProfUrl', 'getInputIdProf', + 'menuDropdownQuickaddItems', 'menuLeftMenuItems', 'moveUploadedFile', 'moreHtmlStatus', diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index fbaee3331c5..f976fac978d 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -406,7 +406,7 @@ class FormCompany extends Form // Show break $key = $langs->trans("Country".strtoupper($obj->country_code)); $valuetoshow = ($key != "Country".strtoupper($obj->country_code)) ? $obj->country_code." - ".$key : $obj->country; - print '\n"; + print '\n"; $country = $obj->country; } diff --git a/htdocs/core/db/DoliDB.class.php b/htdocs/core/db/DoliDB.class.php index 66e54a4fc3c..aae315ec992 100644 --- a/htdocs/core/db/DoliDB.class.php +++ b/htdocs/core/db/DoliDB.class.php @@ -96,6 +96,17 @@ abstract class DoliDB implements Database return '(CASE WHEN '.$test.' THEN '.$resok.' ELSE '.$resko.' END)'; } + /** + * Return SQL string to force an index + * + * @param string $nameofindex Name of index + * @return string SQL string + */ + public function hintindex($nameofindex) + { + return ''; + } + /** * Convert (by PHP) a GM Timestamp date into a string date with PHP server TZ to insert into a date field. * Function to use to build INSERT, UPDATE or WHERE predica diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index 81a331add8a..582fd08811f 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -168,6 +168,18 @@ class DoliDBMysqli extends DoliDB } + /** + * Return SQL string to force an index + * + * @param string $nameofindex Name of index + * @return string SQL string + */ + public function hintindex($nameofindex) + { + return " FORCE INDEX(".preg_replace('/[^a-z0-9_]/', '', $nameofindex).")"; + } + + /** * Convert a SQL request in Mysql syntax to native syntax * @@ -180,6 +192,7 @@ class DoliDBMysqli extends DoliDB return $line; } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Select a database diff --git a/htdocs/core/js/lib_head.js.php b/htdocs/core/js/lib_head.js.php index 5d47fa5f605..3fe6dee8820 100644 --- a/htdocs/core/js/lib_head.js.php +++ b/htdocs/core/js/lib_head.js.php @@ -1198,4 +1198,22 @@ $(document).ready(function() { } }); + +/* + * Hacky fix for a bug in select2 with jQuery 3.6.0's new nested-focus "protection" + * see: https://github.com/select2/select2/issues/5993 + * see: https://github.com/jquery/jquery/issues/4382 + * + * TODO: Recheck with the select2 GH issue and remove once this is fixed on their side + */ +$(document).on('select2:open', () => { + console.log("Execute the focus (click on combo or use space when on component"); + let allFound = document.querySelectorAll('.select2-container--open .select2-search__field'); + $(this).one('mouseup keyup',()=>{ + setTimeout(()=>{ + allFound[allFound.length - 1].focus(); + },0); + }); +}); + // End of lib_head.js.php diff --git a/htdocs/core/lib/agenda.lib.php b/htdocs/core/lib/agenda.lib.php index d2528f45dfa..488010609f9 100644 --- a/htdocs/core/lib/agenda.lib.php +++ b/htdocs/core/lib/agenda.lib.php @@ -93,7 +93,7 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh print $form->select_dolgroups($usergroupid, 'usergroup', 1, '', !$canedit, '', '', '0', false, 'minwidth100 maxwidth500 widthcentpercentminusxx'); print ''; - if ($conf->resource->enabled) { + if (!empty($conf->resource->enabled)) { include_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php'; $formresource = new FormResource($db); @@ -105,14 +105,14 @@ function print_actions_filter($form, $canedit, $status, $year, $month, $day, $sh } } - if (!empty($conf->societe->enabled) && $user->rights->societe->lire) { + if (!empty($conf->societe->enabled) && !empty($user->rights->societe->lire)) { print '';
- if ($totalarray['type'][$i] == 'duration') {
+ if (isset($totalarray['type']) && $totalarray['type'][$i] == 'duration') {
print (!empty($totalarray['val'][$totalarray['pos'][$i]])?convertSecondToTime($totalarray['val'][$totalarray['pos'][$i]], 'allhourmin'):0);
} else {
print price(!empty($totalarray['val'][$totalarray['pos'][$i]])?$totalarray['val'][$totalarray['pos'][$i]]:0);
diff --git a/htdocs/core/tpl/originproductline.tpl.php b/htdocs/core/tpl/originproductline.tpl.php
index 7e56611a282..55d385fcd50 100644
--- a/htdocs/core/tpl/originproductline.tpl.php
+++ b/htdocs/core/tpl/originproductline.tpl.php
@@ -1,6 +1,7 @@
* Copyright (C) 2017 Charlie Benke | '.$this->tpl['label'].' | ';
print ''.$this->tpl['description'].' | ';
print ''.$this->tpl['vat_rate'].' | ';
@@ -41,6 +42,7 @@ if (!empty($conf->global->PRODUCT_USE_UNITS)) {
}
print ''.$this->tpl['remise_percent'].' | ';
+print ''.$this->tpl['total_ht'].' | ';
$selected = 1;
if (!empty($selectedLines) && !in_array($this->tpl['id'], $selectedLines)) {
diff --git a/htdocs/core/tpl/resource_add.tpl.php b/htdocs/core/tpl/resource_add.tpl.php
index 64d545ba583..02bc8ce421f 100644
--- a/htdocs/core/tpl/resource_add.tpl.php
+++ b/htdocs/core/tpl/resource_add.tpl.php
@@ -13,9 +13,11 @@ require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php';
$form = new Form($db);
$formresources = new FormResource($db);
-$out = '';
+$out = '';
-$out .= ' | |||