From d46feda3e5fb5358487bc4af2de53c15f1e1f138 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 27 Oct 2020 16:13:07 +0100 Subject: [PATCH 01/46] NEW: Accountancy - Add export for Gestinum (v3 & v5) --- .../class/accountancyexport.class.php | 152 +++++++++++++++++- htdocs/langs/en_US/accountancy.lang | 2 + 2 files changed, 152 insertions(+), 2 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 0204602438f..9d59b20f680 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -57,6 +57,8 @@ class AccountancyExport public static $EXPORT_TYPE_OPENCONCERTO = 100; public static $EXPORT_TYPE_LDCOMPTA = 110; public static $EXPORT_TYPE_LDCOMPTA10 = 120; + public static $EXPORT_TYPE_GESTINUMV3 = 130; + public static $EXPORT_TYPE_GESTINUMV5 = 135; public static $EXPORT_TYPE_FEC = 1000; @@ -113,10 +115,12 @@ class AccountancyExport self::$EXPORT_TYPE_AGIRIS => $langs->trans('Modelcsv_agiris'), self::$EXPORT_TYPE_OPENCONCERTO => $langs->trans('Modelcsv_openconcerto'), self::$EXPORT_TYPE_SAGE50_SWISS => $langs->trans('Modelcsv_Sage50_Swiss'), + self::$EXPORT_TYPE_CHARLEMAGNE => $langs->trans('Modelcsv_charlemagne'), self::$EXPORT_TYPE_LDCOMPTA => $langs->trans('Modelcsv_LDCompta'), self::$EXPORT_TYPE_LDCOMPTA10 => $langs->trans('Modelcsv_LDCompta10'), + self::$EXPORT_TYPE_GESTINUMV3 => $langs->trans('Modelcsv_Gestinum_v3'), + self::$EXPORT_TYPE_GESTINUMV5 => $langs->trans('Modelcsv_Gestinum_v5'), self::$EXPORT_TYPE_FEC => $langs->trans('Modelcsv_FEC'), - self::$EXPORT_TYPE_CHARLEMAGNE => $langs->trans('Modelcsv_charlemagne'), ); ksort($listofexporttypes, SORT_NUMERIC); @@ -147,6 +151,8 @@ class AccountancyExport self::$EXPORT_TYPE_SAGE50_SWISS => 'sage50ch', self::$EXPORT_TYPE_LDCOMPTA => 'ldcompta', self::$EXPORT_TYPE_LDCOMPTA10 => 'ldcompta10', + self::$EXPORT_TYPE_GESTINUMV3 => 'gestinumv3', + self::$EXPORT_TYPE_GESTINUMV5 => 'gestinumv5', self::$EXPORT_TYPE_FEC => 'fec', ); @@ -215,7 +221,12 @@ class AccountancyExport ), self::$EXPORT_TYPE_LDCOMPTA10 => array( 'label' => $langs->trans('Modelcsv_LDCompta10'), - 'ACCOUNTING_EXPORT_FORMAT' => 'csv', + ), + self::$EXPORT_TYPE_GESTINUMV3 => array( + 'label' => $langs->trans('Modelcsv_Gestinumv3'), + ), + self::$EXPORT_TYPE_GESTINUMV5 => array( + 'label' => $langs->trans('Modelcsv_Gestinumv5'), ), self::$EXPORT_TYPE_FEC => array( 'label' => $langs->trans('Modelcsv_FEC'), @@ -301,6 +312,12 @@ class AccountancyExport case self::$EXPORT_TYPE_LDCOMPTA10 : $this->exportLDCompta10($TData); break; + case self::$EXPORT_TYPE_GESTINUMV3 : + $this->exportGestimumV3($TData); + break; + case self::$EXPORT_TYPE_GESTINUMV5 : + $this->exportGestimumV5($TData); + break; case self::$EXPORT_TYPE_FEC : $this->exportFEC($TData); break; @@ -1468,6 +1485,137 @@ class AccountancyExport } } + /** + * Export format : Gestimum V3 + * + * @param array $objectLines data + * + * @return void + */ + public function exportGestimumV3($objectLines) { + global $langs; + + $this->separator = ','; + + $invoices_infos = array(); + $supplier_invoices_infos = array(); + foreach ( $objectLines as $line ) { + + $date = dol_print_date($line->doc_date, '%d/%m/%Y'); + + $invoice_ref = $line->doc_ref; + $company_name = ""; + + if (($line->doc_type == 'customer_invoice' || $line->doc_type == 'supplier_invoice') && $line->fk_doc > 0) { + if (($line->doc_type == 'customer_invoice' && !isset($invoices_infos[$line->fk_doc])) || + ($line->doc_type == 'supplier_invoice' && !isset($supplier_invoices_infos[$line->fk_doc]))) { + if ($line->doc_type == 'customer_invoice') { + // Get new customer invoice ref and company name + $sql = "SELECT f.facnumber, s.nom FROM " . MAIN_DB_PREFIX . "facture as f". + " LEFT JOIN " . MAIN_DB_PREFIX . "societe AS s ON f.fk_soc = s.rowid" . + " WHERE f.rowid = " . $line->fk_doc; + $resql = $this->db->query($sql); + if ($resql) { + if ($obj = $this->db->fetch_object($resql)) { + // Save invoice infos + $invoices_infos[$line->fk_doc] = array('ref' => $obj->facnumber, 'company_name' => $obj->nom); + $invoice_ref = $obj->facnumber; + $company_name = $obj->nom; + } + } + } else { + // Get new supplier invoice ref and company name + $sql = "SELECT ff.ref, s.nom FROM " . MAIN_DB_PREFIX . "facture_fourn as ff". + " LEFT JOIN " . MAIN_DB_PREFIX . "societe AS s ON ff.fk_soc = s.rowid" . + " WHERE ff.rowid = " . $line->fk_doc; + $resql = $this->db->query($sql); + if ($resql) { + if ($obj = $this->db->fetch_object($resql)) { + // Save invoice infos + $supplier_invoices_infos[$line->fk_doc] = array('ref' => $obj->ref, 'company_name' => $obj->nom); + $invoice_ref = $obj->ref; + $company_name = $obj->nom; + } + } + } + } elseif ($line->doc_type == 'customer_invoice') { + // Retrieve invoice infos + $invoice_ref = $invoices_infos[$line->fk_doc]['ref']; + $company_name = $invoices_infos[$line->fk_doc]['company_name']; + } else { + // Retrieve invoice infos + $invoice_ref = $supplier_invoices_infos[$line->fk_doc]['ref']; + $company_name = $supplier_invoices_infos[$line->fk_doc]['company_name']; + } + } + + print $line->id . $this->separator; + print $date . $this->separator; + print substr($line->code_journal, 0, 4) . $this->separator; + + if ((substr($line->numero_compte, 0, 3) == '411') || (substr($line->numero_compte, 0, 3) == '401')) { + print length_accountg($line->subledger_account) . $this->separator; + + } else { + print substr(length_accountg($line->numero_compte), 0, 15) . $this->separator; + } + //Libellé Auto + print $this->separator; + //print '"'.dol_trunc(str_replace('"', '', $line->label_operation),40,'right','UTF-8',1).'"' . $this->separator; + //Libellé manuel + print dol_trunc(str_replace('"', '', $invoice_ref . (!empty($company_name) ? ' - ' : '') . $company_name), 40, 'right', 'UTF-8', 1) . $this->separator; + //Numéro de pièce + print dol_trunc(str_replace('"', '', $line->piece_num), 10, 'right', 'UTF-8', 1) . $this->separator; + //Devise + print 'EUR' . $this->separator; + //Montant + print price2num(abs($line->montant)) . $this->separator; + //Sens + print $line->sens . $this->separator; + //Code lettrage + print $this->separator; + //Date Echéance + print $date; + print $this->end_line; + } + } + + /** + * Export format : Gestimum V5 + * + * @param array $objectLines data + * + * @return void + */ + public function exportGestimumV5($objectLines) { + + $this->separator = ','; + + foreach ( $objectLines as $line ) { + + $date = dol_print_date($line->doc_date, '%d%m%Y'); + + print $line->id . $this->separator; + print $date . $this->separator; + print substr($line->code_journal,0, 4) . $this->separator; + if ((substr($line->numero_compte, 0, 3) == '411') || (substr($line->numero_compte, 0, 3) == '401')) { + print length_accountg($line->subledger_account) . $this->separator; + } else { + print substr(length_accountg($line->numero_compte),0,15) . $this->separator; + } + print $this->separator; + //print '"'.dol_trunc(str_replace('"', '', $line->label_operation),40,'right','UTF-8',1).'"' . $this->separator; + print '"'.dol_trunc(str_replace('"', '', $line->doc_ref),40,'right','UTF-8',1).'"' . $this->separator; + print '"'.dol_trunc(str_replace('"', '', $line->piece_num),10,'right','UTF-8',1).'"'.$this->separator; + print price2num($line->montant).$this->separator; + print $line->sens.$this->separator; + print $date . $this->separator; + print $this->separator; + print $this->separator; + print 'EUR'; + print $this->end_line; + } + } /** * trunc diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 24255577b11..82119366b2b 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -338,6 +338,8 @@ Modelcsv_configurable=Export CSV Configurable Modelcsv_FEC=Export FEC Modelcsv_Sage50_Swiss=Export for Sage 50 Switzerland Modelcsv_winfic=Export Winfic - eWinfic - WinSis Compta +Modelcsv_Gestinumv3=Export for Gestinum (v3) +Modelcsv_Gestinumv5Export for Gestinum (v5) ChartofaccountsId=Chart of accounts Id ## Tools - Init accounting account on product / service From 1b8f9e6a6782cdf8f91e46a216dcf8f07158d6a3 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 27 Oct 2020 16:14:52 +0100 Subject: [PATCH 02/46] Useless to specify css format export, csv is format by default --- htdocs/accountancy/class/accountancyexport.class.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 9d59b20f680..1e818916655 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -209,15 +209,12 @@ class AccountancyExport ), self::$EXPORT_TYPE_OPENCONCERTO => array( 'label' => $langs->trans('Modelcsv_openconcerto'), - 'ACCOUNTING_EXPORT_FORMAT' => 'csv', ), self::$EXPORT_TYPE_SAGE50_SWISS => array( 'label' => $langs->trans('Modelcsv_Sage50_Swiss'), - 'ACCOUNTING_EXPORT_FORMAT' => 'csv', ), self::$EXPORT_TYPE_LDCOMPTA => array( 'label' => $langs->trans('Modelcsv_LDCompta'), - 'ACCOUNTING_EXPORT_FORMAT' => 'csv', ), self::$EXPORT_TYPE_LDCOMPTA10 => array( 'label' => $langs->trans('Modelcsv_LDCompta10'), From 0931a42dc23af634a214a92b39b9521d5c5a3485 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 27 Oct 2020 16:17:52 +0100 Subject: [PATCH 03/46] Move format Charlemagne --- .../accountancy/class/accountancyexport.class.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 1e818916655..1caa17f3836 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -149,6 +149,7 @@ class AccountancyExport self::$EXPORT_TYPE_AGIRIS => 'agiris', self::$EXPORT_TYPE_OPENCONCERTO => 'openconcerto', self::$EXPORT_TYPE_SAGE50_SWISS => 'sage50ch', + self::$EXPORT_TYPE_CHARLEMAGNE => 'charlemagne', self::$EXPORT_TYPE_LDCOMPTA => 'ldcompta', self::$EXPORT_TYPE_LDCOMPTA10 => 'ldcompta10', self::$EXPORT_TYPE_GESTINUMV3 => 'gestinumv3', @@ -213,6 +214,10 @@ class AccountancyExport self::$EXPORT_TYPE_SAGE50_SWISS => array( 'label' => $langs->trans('Modelcsv_Sage50_Swiss'), ), + self::$EXPORT_TYPE_CHARLEMAGNE => array( + 'label' => $langs->trans('Modelcsv_charlemagne'), + 'ACCOUNTING_EXPORT_FORMAT' => 'txt', + ), self::$EXPORT_TYPE_LDCOMPTA => array( 'label' => $langs->trans('Modelcsv_LDCompta'), ), @@ -229,10 +234,6 @@ class AccountancyExport 'label' => $langs->trans('Modelcsv_FEC'), 'ACCOUNTING_EXPORT_FORMAT' => 'txt', ), - self::$EXPORT_TYPE_CHARLEMAGNE => array( - 'label' => $langs->trans('Modelcsv_charlemagne'), - 'ACCOUNTING_EXPORT_FORMAT' => 'txt', - ), ), 'cr'=> array( '1' => $langs->trans("Unix"), @@ -303,6 +304,9 @@ class AccountancyExport case self::$EXPORT_TYPE_SAGE50_SWISS : $this->exportSAGE50SWISS($TData); break; + case self::$EXPORT_TYPE_CHARLEMAGNE : + $this->exportCharlemagne($TData); + break; case self::$EXPORT_TYPE_LDCOMPTA : $this->exportLDCompta($TData); break; @@ -318,9 +322,6 @@ class AccountancyExport case self::$EXPORT_TYPE_FEC : $this->exportFEC($TData); break; - case self::$EXPORT_TYPE_CHARLEMAGNE : - $this->exportCharlemagne($TData); - break; default: $this->errors[] = $langs->trans('accountancy_error_modelnotfound'); break; From 967eb5fa8e0a2f6bb5fe0be937174053d8e509bc Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 27 Oct 2020 15:20:34 +0000 Subject: [PATCH 04/46] Fixing style errors. --- .../class/accountancyexport.class.php | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 1caa17f3836..02143ad16c9 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -1490,15 +1490,15 @@ class AccountancyExport * * @return void */ - public function exportGestimumV3($objectLines) { + public function exportGestimumV3($objectLines) + { global $langs; $this->separator = ','; $invoices_infos = array(); $supplier_invoices_infos = array(); - foreach ( $objectLines as $line ) { - + foreach ($objectLines as $line) { $date = dol_print_date($line->doc_date, '%d/%m/%Y'); $invoice_ref = $line->doc_ref; @@ -1553,7 +1553,6 @@ class AccountancyExport if ((substr($line->numero_compte, 0, 3) == '411') || (substr($line->numero_compte, 0, 3) == '401')) { print length_accountg($line->subledger_account) . $this->separator; - } else { print substr(length_accountg($line->numero_compte), 0, 15) . $this->separator; } @@ -1585,26 +1584,26 @@ class AccountancyExport * * @return void */ - public function exportGestimumV5($objectLines) { + public function exportGestimumV5($objectLines) + { $this->separator = ','; - foreach ( $objectLines as $line ) { - + foreach ($objectLines as $line) { $date = dol_print_date($line->doc_date, '%d%m%Y'); print $line->id . $this->separator; print $date . $this->separator; - print substr($line->code_journal,0, 4) . $this->separator; + print substr($line->code_journal, 0, 4) . $this->separator; if ((substr($line->numero_compte, 0, 3) == '411') || (substr($line->numero_compte, 0, 3) == '401')) { print length_accountg($line->subledger_account) . $this->separator; } else { - print substr(length_accountg($line->numero_compte),0,15) . $this->separator; + print substr(length_accountg($line->numero_compte), 0, 15) . $this->separator; } print $this->separator; //print '"'.dol_trunc(str_replace('"', '', $line->label_operation),40,'right','UTF-8',1).'"' . $this->separator; - print '"'.dol_trunc(str_replace('"', '', $line->doc_ref),40,'right','UTF-8',1).'"' . $this->separator; - print '"'.dol_trunc(str_replace('"', '', $line->piece_num),10,'right','UTF-8',1).'"'.$this->separator; + print '"'.dol_trunc(str_replace('"', '', $line->doc_ref), 40, 'right', 'UTF-8', 1).'"' . $this->separator; + print '"'.dol_trunc(str_replace('"', '', $line->piece_num), 10, 'right', 'UTF-8', 1).'"'.$this->separator; print price2num($line->montant).$this->separator; print $line->sens.$this->separator; print $date . $this->separator; From 7a7f51cd00e1b579959c7a8ce503c0c4acd83bb2 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 27 Oct 2020 16:29:10 +0100 Subject: [PATCH 05/46] Fix stickler --- htdocs/accountancy/class/accountancyexport.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 1caa17f3836..5d700e54660 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -1509,9 +1509,9 @@ class AccountancyExport ($line->doc_type == 'supplier_invoice' && !isset($supplier_invoices_infos[$line->fk_doc]))) { if ($line->doc_type == 'customer_invoice') { // Get new customer invoice ref and company name - $sql = "SELECT f.facnumber, s.nom FROM " . MAIN_DB_PREFIX . "facture as f". - " LEFT JOIN " . MAIN_DB_PREFIX . "societe AS s ON f.fk_soc = s.rowid" . - " WHERE f.rowid = " . $line->fk_doc; + $sql = 'SELECT f.facnumber, s.nom FROM ' . MAIN_DB_PREFIX . 'facture as f'. + ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON f.fk_soc = s.rowid' . + ' WHERE f.rowid = ' . $line->fk_doc; $resql = $this->db->query($sql); if ($resql) { if ($obj = $this->db->fetch_object($resql)) { @@ -1523,9 +1523,9 @@ class AccountancyExport } } else { // Get new supplier invoice ref and company name - $sql = "SELECT ff.ref, s.nom FROM " . MAIN_DB_PREFIX . "facture_fourn as ff". - " LEFT JOIN " . MAIN_DB_PREFIX . "societe AS s ON ff.fk_soc = s.rowid" . - " WHERE ff.rowid = " . $line->fk_doc; + $sql = 'SELECT ff.ref, s.nom FROM ' . MAIN_DB_PREFIX . 'facture_fourn as ff'. + ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON ff.fk_soc = s.rowid' . + ' WHERE ff.rowid = ' . $line->fk_doc; $resql = $this->db->query($sql); if ($resql) { if ($obj = $this->db->fetch_object($resql)) { From 53009e41fed51f485e3bcc1e3ba4ea472bb5024e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 27 Oct 2020 18:10:38 +0100 Subject: [PATCH 06/46] Update accountancyexport.class.php --- htdocs/accountancy/class/accountancyexport.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index e2e876bb079..aa806cb084a 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -1509,9 +1509,9 @@ class AccountancyExport ($line->doc_type == 'supplier_invoice' && !isset($supplier_invoices_infos[$line->fk_doc]))) { if ($line->doc_type == 'customer_invoice') { // Get new customer invoice ref and company name - $sql = 'SELECT f.facnumber, s.nom FROM ' . MAIN_DB_PREFIX . 'facture as f'. - ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON f.fk_soc = s.rowid' . - ' WHERE f.rowid = ' . $line->fk_doc; + $sql = 'SELECT f.facnumber, s.nom FROM ' . MAIN_DB_PREFIX . 'facture as f'; + $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON f.fk_soc = s.rowid'; + $sql .= ' WHERE f.rowid = ' . $line->fk_doc; $resql = $this->db->query($sql); if ($resql) { if ($obj = $this->db->fetch_object($resql)) { @@ -1523,9 +1523,9 @@ class AccountancyExport } } else { // Get new supplier invoice ref and company name - $sql = 'SELECT ff.ref, s.nom FROM ' . MAIN_DB_PREFIX . 'facture_fourn as ff'. - ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON ff.fk_soc = s.rowid' . - ' WHERE ff.rowid = ' . $line->fk_doc; + $sql = 'SELECT ff.ref, s.nom FROM ' . MAIN_DB_PREFIX . 'facture_fourn as ff'; + $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON ff.fk_soc = s.rowid'; + $sql .= ' WHERE ff.rowid = ' . $line->fk_doc; $resql = $this->db->query($sql); if ($resql) { if ($obj = $this->db->fetch_object($resql)) { From 28e4be3b0ecbe937ac8710bace428c44b4e6bb6a Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 22 Nov 2020 16:25:38 +0100 Subject: [PATCH 07/46] Fix contact API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get roles by API (without GET this data, we can't add this to POST, so data was deleted 👎 ) --- htdocs/societe/class/api_contacts.class.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index bc456dd7185..a32619855fd 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -78,6 +78,7 @@ class Contacts extends DolibarrApi $result = $this->contact->initAsSpecimen(); } else { $result = $this->contact->fetch($id); + $this->contact->fetchRoles(); } if (!$result) @@ -120,6 +121,7 @@ class Contacts extends DolibarrApi $result = $this->contact->initAsSpecimen(); } else { $result = $this->contact->fetch('', '', '', $email); + $this->contact->fetchRoles(); } if (!$result) @@ -241,6 +243,7 @@ class Contacts extends DolibarrApi $contact_static = new Contact($this->db); if ($contact_static->fetch($obj->rowid)) { + $contact_static->fetchRoles(); if ($includecount) { $contact_static->load_ref_elements(); From fbc911aea1e82dfa711d9bc7b41c0c458dc1e417 Mon Sep 17 00:00:00 2001 From: ATM john Date: Mon, 23 Nov 2020 16:40:31 +0100 Subject: [PATCH 08/46] Fix conf usage thirdparty propagate extrafields to --- htdocs/commande/card.php | 2 +- htdocs/compta/facture/card.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index ed1f27e3c82..4175509eb28 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1772,7 +1772,7 @@ if ($action == 'create' && $usercancreate) $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); print $hookmanager->resPrint; if (empty($reshook)) { - if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER)) { + if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER) && !empty($soc->id)) { // copy from thirdparty $tpExtrafields = new Extrafields($db); $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element); diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 9118944d9f9..3362d23e532 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3571,7 +3571,7 @@ if ($action == 'create') $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print $hookmanager->resPrint; if (empty($reshook)) { - if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_INVOICE)) { + if (!empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_INVOICE) && !empty($soc->id)) { // copy from thirdparty $tpExtrafields = new Extrafields($db); $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element); From 5822fcfbedf3dd62398ed1785d70a815bdb7e8cb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Nov 2020 21:38:45 +0100 Subject: [PATCH 09/46] FIX several warning with the barcode use in ODT templates --- htdocs/comm/propal/class/propal.class.php | 20 ++++++++++++++++--- htdocs/commande/class/commande.class.php | 7 +++++-- .../core/class/commondocgenerator.class.php | 11 ++++++---- htdocs/core/class/commonorder.class.php | 12 +++++++++++ 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index c6d6f18e109..144374ab47c 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -1344,7 +1344,6 @@ class Propal extends CommonObject // Load source object $object->fetch($this->id); - $object->fetch_lines(); $objsoc = new Societe($this->db); @@ -1738,7 +1737,7 @@ class Propal extends CommonObject $sql = 'SELECT d.rowid, d.fk_propal, d.fk_parent_line, d.label as custom_label, d.description, d.price, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.qty, d.fk_remise_except, d.remise_percent, d.subprice, d.fk_product,'; $sql .= ' d.info_bits, d.total_ht, d.total_tva, d.total_localtax1, d.total_localtax2, d.total_ttc, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht, d.special_code, d.rang, d.product_type,'; $sql .= ' d.fk_unit,'; - $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tobatch as product_batch,'; + $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tobatch as product_tobatch, p.barcode as product_barcode,'; $sql .= ' p.weight, p.weight_units, p.volume, p.volume_units,'; $sql .= ' d.date_start, d.date_end,'; $sql .= ' d.fk_multicurrency, d.multicurrency_code, d.multicurrency_subprice, d.multicurrency_total_ht, d.multicurrency_total_tva, d.multicurrency_total_ttc'; @@ -1800,11 +1799,14 @@ class Propal extends CommonObject $line->fk_product = $objp->fk_product; $line->ref = $objp->product_ref; // deprecated - $line->product_ref = $objp->product_ref; $line->libelle = $objp->product_label; // deprecated + + $line->product_ref = $objp->product_ref; $line->product_label = $objp->product_label; $line->product_desc = $objp->product_desc; // Description produit $line->product_tobatch = $objp->product_tobatch; + $line->product_barcode = $objp->product_barcode; + $line->fk_product_type = $objp->fk_product_type; // deprecated $line->fk_unit = $objp->fk_unit; $line->weight = $objp->weight; @@ -3924,6 +3926,18 @@ class PropaleLigne extends CommonObjectLine */ public $product_desc; + /** + * Product use lot + * @var string + */ + public $product_tobatch; + + /** + * Product barcode + * @var string + */ + public $product_barcode; + public $localtax1_tx; // Local tax 1 public $localtax2_tx; // Local tax 2 public $localtax1_type; // Local tax 1 type diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 07f483da931..fbbd40265a1 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -2033,7 +2033,7 @@ class Commande extends CommonOrder $sql .= ' l.total_ht, l.total_ttc, l.total_tva, l.total_localtax1, l.total_localtax2, l.date_start, l.date_end,'; $sql .= ' l.fk_unit,'; $sql .= ' l.fk_multicurrency, l.multicurrency_code, l.multicurrency_subprice, l.multicurrency_total_ht, l.multicurrency_total_tva, l.multicurrency_total_ttc,'; - $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tobatch as product_tobatch,'; + $sql .= ' p.ref as product_ref, p.description as product_desc, p.fk_product_type, p.label as product_label, p.tobatch as product_tobatch, p.barcode as product_barcode,'; $sql .= ' p.weight, p.weight_units, p.volume, p.volume_units'; $sql .= ' FROM '.MAIN_DB_PREFIX.'commandedet as l'; $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON (p.rowid = l.fk_product)'; @@ -2091,11 +2091,14 @@ class Commande extends CommonOrder $line->fk_parent_line = $objp->fk_parent_line; $line->ref = $objp->product_ref; - $line->product_ref = $objp->product_ref; $line->libelle = $objp->product_label; + + $line->product_ref = $objp->product_ref; $line->product_label = $objp->product_label; $line->product_desc = $objp->product_desc; $line->product_tobatch = $objp->product_tobatch; + $line->product_barcode = $objp->product_barcode; + $line->fk_product_type = $objp->fk_product_type; // Produit ou service $line->fk_unit = $objp->fk_unit; diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 544cc105416..2900a4cd173 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -529,10 +529,13 @@ abstract class CommonDocGenerator $resarray = array( 'line_pos' => $linenumber, 'line_fulldesc'=>doc_getlinedesc($line, $outputlangs), - 'line_product_ref'=>$line->product_ref, - 'line_product_ref_fourn'=>$line->ref_fourn, // for supplier doc lines - 'line_product_label'=>$line->product_label, - 'line_product_type'=>$line->product_type, + + 'line_product_ref'=>(empty($line->product_ref) ? '' : $line->product_ref), + 'line_product_ref_fourn'=>(empty($line->ref_fourn) ? '' : $line->ref_fourn), // for supplier doc lines + 'line_product_label'=>(empty($line->product_label) ? '' :$line->product_label), + 'line_product_type'=>(empty($line->product_type) ? '' : $line->product_type), + 'line_product_barcode'=>(empty($line->product_barcode) ? '' : $line->product_barcode), + 'line_desc'=>$line->desc, 'line_vatrate'=>vatrate($line->tva_tx, true, $line->info_bits), 'line_localtax1_rate'=>vatrate($line->localtax1_tx), diff --git a/htdocs/core/class/commonorder.class.php b/htdocs/core/class/commonorder.class.php index e45d08a9396..7f2c9fef684 100644 --- a/htdocs/core/class/commonorder.class.php +++ b/htdocs/core/class/commonorder.class.php @@ -71,6 +71,18 @@ abstract class CommonOrderLine extends CommonObjectLine */ public $product_desc; + /** + * Product use lot + * @var string + */ + public $product_tobatch; + + /** + * Product barcode + * @var string + */ + public $product_barcode; + /** * Quantity * @var float From f227d5e72ae654cb2b6b3d7f268662026082456f Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Mon, 23 Nov 2020 22:53:56 +0100 Subject: [PATCH 10/46] Update api_contacts.class.php --- htdocs/societe/class/api_contacts.class.php | 26 +++++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index a32619855fd..9b1f0cc084d 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -63,12 +63,13 @@ class Contacts extends DolibarrApi * Return an array with contact informations * * @param int $id ID of contact + * @param int $includeroles Includes roles of the contact * @param int $includecount Count and return also number of elements the contact is used as a link for * @return array|mixed data without useless information * * @throws RestException */ - public function get($id, $includecount = 0) + public function get($id, $includeroles = 0, $includecount = 0) { if (!DolibarrApiAccess::$user->rights->societe->contact->lire) { @@ -78,7 +79,6 @@ class Contacts extends DolibarrApi $result = $this->contact->initAsSpecimen(); } else { $result = $this->contact->fetch($id); - $this->contact->fetchRoles(); } if (!$result) @@ -90,6 +90,11 @@ class Contacts extends DolibarrApi { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } + + if ($includeroles) + { + $this->contact->fetchRoles(); + } if ($includecount) { @@ -103,6 +108,7 @@ class Contacts extends DolibarrApi * Get properties of a contact object by Email * * @param string $email Email of contact + * @param int $includeroles Includes roles of the contact * @param int $includecount Count and return also number of elements the contact is used as a link for * @return array|mixed data without useless information * @@ -111,7 +117,7 @@ class Contacts extends DolibarrApi * @throws RestException 401 Insufficient rights * @throws RestException 404 User or group not found */ - public function getByEmail($email, $includecount = 0) + public function getByEmail($email, $includeroles = 0, $includecount = 0) { if (!DolibarrApiAccess::$user->rights->societe->contact->lire) { @@ -133,6 +139,11 @@ class Contacts extends DolibarrApi { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } + + if ($includeroles) + { + $this->contact->fetchRoles(); + } if ($includecount) { @@ -152,14 +163,15 @@ class Contacts extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @param string $thirdparty_ids Thirdparty ids to filter contacts of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i} - * @param int $category Use this param to filter list by category + * @param int $category Use this param to filter list by category * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @param int $includeroles Includes roles of the contact * @param int $includecount Count and return also number of elements the contact is used as a link for * @return array Array of contact objects * * @throws RestException */ - public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $category = 0, $sqlfilters = '', $includecount = 0) + public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $category = 0, $sqlfilters = '', $includeroles = 0, $includecount = 0) { global $db, $conf; @@ -244,6 +256,10 @@ class Contacts extends DolibarrApi if ($contact_static->fetch($obj->rowid)) { $contact_static->fetchRoles(); + if ($includeroles) + { + $contact_static->fetchRoles(); + } if ($includecount) { $contact_static->load_ref_elements(); From c1ba61e54853350df7a7a109b26947284ba9bf02 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 23 Nov 2020 21:55:36 +0000 Subject: [PATCH 11/46] Fixing style errors. --- htdocs/societe/class/api_contacts.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index 9b1f0cc084d..1ebcf3fecb8 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -90,7 +90,7 @@ class Contacts extends DolibarrApi { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - + if ($includeroles) { $this->contact->fetchRoles(); @@ -139,7 +139,7 @@ class Contacts extends DolibarrApi { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - + if ($includeroles) { $this->contact->fetchRoles(); From 0d50402803850e0f52dee278062efe461694be68 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Mon, 23 Nov 2020 23:31:46 +0100 Subject: [PATCH 12/46] Update api_contacts.class.php --- htdocs/societe/class/api_contacts.class.php | 41 +++++++++++---------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index 1ebcf3fecb8..ee131a5c40f 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -63,13 +63,13 @@ class Contacts extends DolibarrApi * Return an array with contact informations * * @param int $id ID of contact - * @param int $includeroles Includes roles of the contact * @param int $includecount Count and return also number of elements the contact is used as a link for + * @param int $includeroles Includes roles of the contact * @return array|mixed data without useless information * * @throws RestException */ - public function get($id, $includeroles = 0, $includecount = 0) + public function get($id, $includecount = 0, $includeroles = 0) { if (!DolibarrApiAccess::$user->rights->societe->contact->lire) { @@ -91,15 +91,15 @@ class Contacts extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - if ($includeroles) - { - $this->contact->fetchRoles(); - } - if ($includecount) { $this->contact->load_ref_elements(); } + + if ($includeroles) + { + $this->contact->fetchRoles(); + } return $this->_cleanObjectDatas($this->contact); } @@ -108,8 +108,8 @@ class Contacts extends DolibarrApi * Get properties of a contact object by Email * * @param string $email Email of contact - * @param int $includeroles Includes roles of the contact * @param int $includecount Count and return also number of elements the contact is used as a link for + * @param int $includeroles Includes roles of the contact * @return array|mixed data without useless information * * @url GET email/{email} @@ -117,7 +117,7 @@ class Contacts extends DolibarrApi * @throws RestException 401 Insufficient rights * @throws RestException 404 User or group not found */ - public function getByEmail($email, $includeroles = 0, $includecount = 0) + public function getByEmail($email, $includecount = 0, $includeroles = 0) { if (!DolibarrApiAccess::$user->rights->societe->contact->lire) { @@ -140,16 +140,16 @@ class Contacts extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - if ($includeroles) - { - $this->contact->fetchRoles(); - } - if ($includecount) { $this->contact->load_ref_elements(); } + if ($includeroles) + { + $this->contact->fetchRoles(); + } + return $this->_cleanObjectDatas($this->contact); } @@ -165,13 +165,13 @@ class Contacts extends DolibarrApi * @param string $thirdparty_ids Thirdparty ids to filter contacts of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i} * @param int $category Use this param to filter list by category * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" - * @param int $includeroles Includes roles of the contact * @param int $includecount Count and return also number of elements the contact is used as a link for + * @param int $includeroles Includes roles of the contact * @return array Array of contact objects * * @throws RestException */ - public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $category = 0, $sqlfilters = '', $includeroles = 0, $includecount = 0) + public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $category = 0, $sqlfilters = '', $includecount = 0, $includeroles = 0) { global $db, $conf; @@ -256,14 +256,15 @@ class Contacts extends DolibarrApi if ($contact_static->fetch($obj->rowid)) { $contact_static->fetchRoles(); + if ($includecount) + { + $contact_static->load_ref_elements(); + } if ($includeroles) { $contact_static->fetchRoles(); } - if ($includecount) - { - $contact_static->load_ref_elements(); - } + $obj_ret[] = $this->_cleanObjectDatas($contact_static); } From 11704ea6fb4153724fc9cd94f22f3ef8e4108216 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 23 Nov 2020 22:33:45 +0000 Subject: [PATCH 13/46] Fixing style errors. --- htdocs/societe/class/api_contacts.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index ee131a5c40f..9463aba5277 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -95,7 +95,7 @@ class Contacts extends DolibarrApi { $this->contact->load_ref_elements(); } - + if ($includeroles) { $this->contact->fetchRoles(); @@ -259,7 +259,7 @@ class Contacts extends DolibarrApi if ($includecount) { $contact_static->load_ref_elements(); - } + } if ($includeroles) { $contact_static->fetchRoles(); From 46fba9d192bbee60745492960b1b227443e49e13 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 09:11:46 +0100 Subject: [PATCH 14/46] Changelog --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index bef57215417..16811fd8f8b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ NEW: Accountancy - add options to disable binding on sales, purchases & expense NEW: Accountancy balance - add a menu entry to show subtotal by group NEW: Accountancy - move to real ledger, real journals, menu disposition NEW: Accountancy - on transfers, select the periodicity by default +NEW: Accountancy - Add export for Gestinum (v3 & v5) NEW: new currency rate editor NEW: add 2 rules for emailcollector: Message send/not sent from Dolibarr NEW: add a counter of number of words for pages in website module From 53208e620e81f135c50f4b0308ac4a3a9661009a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 10:56:05 +0100 Subject: [PATCH 15/46] Use of . as thousand separator. Can use it for decimal if not 3 digits. --- htdocs/core/lib/functions.lib.php | 38 +++++++++++++++---------------- test/phpunit/FunctionsLibTest.php | 16 +++++++++++-- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index efeed543865..ef0703d635a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4691,19 +4691,19 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $ * Function to use on each input amount before any numeric test or database insert. A better name for this function * should be roundtext2num(). * - * @param float $amount Amount to convert/clean or round - * @param string $rounding ''=No rounding - * 'MU'=Round to Max unit price (MAIN_MAX_DECIMALS_UNIT) - * 'MT'=Round to Max for totals with Tax (MAIN_MAX_DECIMALS_TOT) - * 'MS'=Round to Max for stock quantity (MAIN_MAX_DECIMALS_STOCK) - * 'CR'=Currency rate - * Numeric = Nb of digits for rounding - * @param int $alreadysqlnb Put 1 if you know that content is already universal format number - * @return string Amount with universal numeric format (Example: '99.99999'). - * If conversion fails, it return text unchanged if $rounding = '' or '0' if $rounding is defined. - * If amount is null or '', it returns '' if $rounding = '' or '0' if $rounding is defined.. + * @param string|float $amount Amount to convert/clean or round + * @param string $rounding ''=No rounding + * 'MU'=Round to Max unit price (MAIN_MAX_DECIMALS_UNIT) + * 'MT'=Round to Max for totals with Tax (MAIN_MAX_DECIMALS_TOT) + * 'MS'=Round to Max for stock quantity (MAIN_MAX_DECIMALS_STOCK) + * 'CR'=Currency rate + * Numeric = Nb of digits for rounding + * @param int $alreadysqlnb Put 1 if you know that content is already universal format number + * @return string Amount with universal numeric format (Example: '99.99999'). + * If conversion fails, it return text unchanged if $rounding = '' or '0' if $rounding is defined. + * If amount is null or '', it returns '' if $rounding = '' or '0' if $rounding is defined.. * - * @see price() Opposite function of price2num + * @see price() Opposite function of price2num */ function price2num($amount, $rounding = '', $alreadysqlnb = 0) { @@ -4720,15 +4720,15 @@ function price2num($amount, $rounding = '', $alreadysqlnb = 0) //print "amount=".$amount." html=".$form." trunc=".$trunc." nbdecimal=".$nbdecimal." dec='".$dec."' thousand='".$thousand."'
"; // Convert value to universal number format (no thousand separator, '.' as decimal separator) - if ($alreadysqlnb != 1) // If not a PHP number or unknown, we change format - { - //print 'PP'.$amount.' - '.$dec.' - '.$thousand.' - '.intval($amount).'
'; + if ($alreadysqlnb != 1) { // If not a PHP number or unknown, we change or clean format + print 'PP'.$amount.' - '.$dec.' - '.$thousand.' - '.intval($amount).'
'; + if ($thousand == '.' && preg_match('/\.(\d\d\d)$/', (string) $amount)) { // It means the . is used as a thousand separator, not as a decimal separator + $amount = str_replace($thousand, '', $amount); // Replace of thousand before test of is_numeric to avoid pb if thousand is . and there is 3 numbers after + print 'TTTT'.$amount; + } // Convert amount to format with dolibarr dec and thousand (this is because PHP convert a number // to format defined by LC_NUMERIC after a calculation and we want source format to be like defined by Dolibarr setup. - if ($thousand == '.') { - $amount = str_replace($thousand, '', $amount); // Replace of thousand before test of is_numeric to avoid pb if thousand is . - } if (is_numeric($amount)) { // We put in temps value of decimal ("0.00001"). Works with 0 and 2.0E-5 and 9999.10 @@ -4738,7 +4738,7 @@ function price2num($amount, $rounding = '', $alreadysqlnb = 0) $amount = number_format($amount, $nbofdec, $dec, $thousand); } //print "QQ".$amount.'
'; - + // Now make replace (the main goal of function) if ($thousand != ',' && $thousand != '.') { $amount = str_replace(',', '.', $amount); // To accept 2 notations for french users diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 0fc2583178c..85937147cff 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -1260,10 +1260,18 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase $newlangs2->load("main"); $langs = $newlangs2; - $this->assertEquals(1000, price2num('1.000'), 'Test 1.000 give 1000 with spanish language'); - $this->assertEquals(1000, price2num('1 000'), 'Test 1 000 give 1000 with spanish language'); + // Test with 3 chars after . or , + // If a . is used and there is 3 digits after, it is a thousand separator + $this->assertEquals(1234, price2num('1.234'), 'Test 1.234 give 1234 with spanish language'); + $this->assertEquals(1234, price2num('1 234'), 'Test 1 234 give 1234 with spanish language'); $this->assertEquals(1234, price2num('1.234'), 'Test 1.234 give 1234 with spanish language'); $this->assertEquals(1.234, price2num('1,234'), 'Test 1,234 give 1.234 with spanish language'); + $this->assertEquals(21500123, price2num('21.500.123'), 'Test 21.500.123 give 21500123 with spanish language'); + $this->assertEquals(21500123, price2num('21500.123'), 'Test 21500.123 give 21500123 with spanish language'); + $this->assertEquals(21500.123, price2num('21500,123'), 'Test 21500,123 give 21500.123 with spanish language'); + // Test with 2 digits + $this->assertEquals(21500.12, price2num('21500.12'), 'Test 21500.12 give 21500.12 with spanish language'); + $this->assertEquals(21500.12, price2num('21500,12'), 'Test 21500,12 give 21500.12 with spanish language'); // For french language $newlangs3 = new Translate('', $conf); @@ -1275,6 +1283,10 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase $this->assertEquals(1000, price2num('1 000'), 'Test 1.000 give 1 with french language'); $this->assertEquals(1.234, price2num('1.234'), 'Test 1.234 give 1.234 with french language'); $this->assertEquals(1.234, price2num('1,234'), 'Test 1,234 give 1.234 with french language'); + $this->assertEquals(21500000, price2num('21500 000'), 'Test 21500 000 give 21500000 with french language'); + $this->assertEquals(21500000, price2num('21 500 000'), 'Test 21 500 000 give 21500000 with french language'); + $this->assertEquals(21500, price2num('21500.00'), 'Test 21500.00 give 21500 with french language'); + $this->assertEquals(21500, price2num('21500,00'), 'Test 21500,00 give 21500 with french language'); $langs = $oldlangs; From 47cfdb4ef2dd65da9141a52d0d161283c3a0d376 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 11:36:54 +0100 Subject: [PATCH 16/46] Prepare database to be ready for a future fix on sessions --- .../install/mysql/migration/12.0.0-13.0.0.sql | 10 +++++++ htdocs/install/mysql/tables/llx_session.sql | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 htdocs/install/mysql/tables/llx_session.sql diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql index d4cfaddb4eb..2ad8fb32896 100644 --- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql +++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql @@ -528,3 +528,13 @@ CREATE TABLE llx_zapier_hook( import_key varchar(14) ) ENGINE=innodb; + +CREATE TABLE llx_session( + session_id varchar(50) PRIMARY KEY, + session_variable text, + last_accessed datetime NOT NULL, + fk_user integer NOT NULL, + remote_ip varchar(64) NULL, + user_agent varchar(128) NULL +)ENGINE=innodb; + diff --git a/htdocs/install/mysql/tables/llx_session.sql b/htdocs/install/mysql/tables/llx_session.sql new file mode 100644 index 00000000000..5be31733c22 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_session.sql @@ -0,0 +1,28 @@ +-- ======================================================================== +-- Copyright (C) 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 +-- 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 . +-- +-- This table can be used for user defined session management +-- ======================================================================== + +create table llx_session +( + session_id varchar(50) PRIMARY KEY, + session_variable text, + last_accessed datetime NOT NULL, + fk_user integer NOT NULL, + remote_ip varchar(64) NULL, + user_agent varchar(128) NULL +)ENGINE=innodb; From 51eed3efe5ad10f2830691af9b09884ad29ac186 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Tue, 24 Nov 2020 12:03:31 +0100 Subject: [PATCH 17/46] Fix api contact --- htdocs/societe/class/api_contacts.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index 9463aba5277..82984409325 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -127,7 +127,6 @@ class Contacts extends DolibarrApi $result = $this->contact->initAsSpecimen(); } else { $result = $this->contact->fetch('', '', '', $email); - $this->contact->fetchRoles(); } if (!$result) From 817de18a5d9ad9f6d3c9fa3f7ae87f7a0e899e2e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 12:25:32 +0100 Subject: [PATCH 18/46] Fix remove log --- htdocs/core/lib/functions.lib.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index ef0703d635a..155b1d74a5f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4721,11 +4721,10 @@ function price2num($amount, $rounding = '', $alreadysqlnb = 0) // Convert value to universal number format (no thousand separator, '.' as decimal separator) if ($alreadysqlnb != 1) { // If not a PHP number or unknown, we change or clean format - print 'PP'.$amount.' - '.$dec.' - '.$thousand.' - '.intval($amount).'
'; + //print 'PP'.$amount.' - '.$dec.' - '.$thousand.' - '.intval($amount).'
'; if ($thousand == '.' && preg_match('/\.(\d\d\d)$/', (string) $amount)) { // It means the . is used as a thousand separator, not as a decimal separator $amount = str_replace($thousand, '', $amount); // Replace of thousand before test of is_numeric to avoid pb if thousand is . and there is 3 numbers after - print 'TTTT'.$amount; } // Convert amount to format with dolibarr dec and thousand (this is because PHP convert a number // to format defined by LC_NUMERIC after a calculation and we want source format to be like defined by Dolibarr setup. From d2f8b65dbf845c35c806d0b1c7c4d6a3dd1f2ba9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 12:26:32 +0100 Subject: [PATCH 19/46] Prepare use of session in db --- htdocs/core/lib/phpsessionindb.lib.php | 166 +++++++++++++++++++++++++ htdocs/main.inc.php | 5 + 2 files changed, 171 insertions(+) create mode 100644 htdocs/core/lib/phpsessionindb.lib.php diff --git a/htdocs/core/lib/phpsessionindb.lib.php b/htdocs/core/lib/phpsessionindb.lib.php new file mode 100644 index 00000000000..585967965dc --- /dev/null +++ b/htdocs/core/lib/phpsessionindb.lib.php @@ -0,0 +1,166 @@ + + * + * 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 . + * or see https://www.gnu.org/ + */ + +/** + * \file htdocs/core/lib/phpsessionindb.lib.php + * \ingroup core + * \brief Set function handlers for PHP session management in DB + */ + +// The session handler file must be included just after the call of the master.inc.php into main.inc.php +// The $conf is already defined from conf.php file. +// To use it set in your PHP.ini: session.save_handler = user + +/** + * The session open handler called by PHP whenever a session is initialized. + * + * @param string $database_name Database NamedConstraint + * @param string $table_name Table name + * @return boolean Always true + */ +function dolSessionOpen($database_name, $table_name) +{ + global $conf, $dbsession; + + $dbsession = getDoliDBInstance($conf->db->type, $conf->db->host, $conf->db->user, $conf->db->pass, $conf->db->name, $conf->db->port); + + return true; +} + +/** + * This function is called whenever a session_start() call is made and reads the session variables. + * + * @param string $sess_id Session ID + * @return string Returns "" when a session is not found or (serialized)string if session exists + */ +function dolSessionRead($sess_id) +{ + global $dbsession; + + $sql = "SELECT session_variable FROM ".MAIN_DB_PREFIX."session"; + $sql .= " WHERE session_id = '".$dbsession->escape($sess_id)."'"; + + // Execute the query + $resql = $dbsession->query($sql); + $num_rows = $dbsession->num_rows($resql); + if ($num_rows == 0) { + // No session found - return an empty string + return ''; + } else { + // Found a session - return the serialized string + $obj = $dbsession->fetch_object($resql); + return $obj->session_variable; + } +} + +/** + * This function is called when a session is initialized with a session_start( ) call, when variables are registered or unregistered, + * and when session variables are modified. Returns true on success. + * + * @param string $sess_id Session iDecodeStream + * @param string $val Content of session + * @return boolean Always true + */ +function dolSessionWrite($sess_id, $val) +{ + global $dbsession; + + $time_stamp = dol_now(); + + $sql = "SELECT session_id FROM ".MAIN_DB_PREFIX."session"; + $sql .= " WHERE session_id = '".$dbsession->escape($sess_id)."'"; + + // Execute the query + $resql = $dbsession->query($sql); + $num_rows = $dbsession->num_rows($resql); + if ($num_rows == 0) { + // No session found, insert a new one + $insert_query = "INSERT INTO ".MAIN_DB_PREFIX."session"; + $insert_query .= "(session_id, session_variable, last_accessed)"; + $insert_query .= " VALUES ('".$dbsession->escape($sess_id)."', '".$dbsession->escape($val)."', '".$dbsession->idate($time_stamp)."')"; + $dbsession->query($insert_query); + } else { + // Existing session found - Update the session variables + $update_query = "UPDATE ".MAIN_DB_PREFIX."session"; + $update_query .= "SET session_variable = '".$dbsession->escape($val)."',"; + $update_query .= " last_accessed = '".$dbsession->idate($time_stamp)."'"; + $update_query .= " WHERE session_id = '".$dbsession->escape($sess_id)."'"; + $dbsession->query($update_query); + } + return true; +} + +/** + * This function is executed on shutdown of the session. + * + * @param string $sess_id Session ID + * @return boolean Always returns true. + */ +function dolSessionClose($sess_id) +{ + global $dbsession; + + $dbsession->close(); + + return true; +} + +/** + * This is called whenever the session_destroy() function call is made. Returns true if the session has successfully been deleted. + * + * @param string $sess_id Session iDecodeStream + * @return boolean Always true + */ +function dolSessionDestroy($sess_id) +{ + global $dbsession; + + $delete_query = "DELETE FROM ".MAIN_DB_PREFIX."session"; + $delete_query .= " WHERE session_id = '".$dbsession->escape($sess_id)."'"; + $dbsession->query($delete_query); + + return true; +} + +/** + * This function is called on a session's start up with the probability specified in session.gc_probability. + * Performs garbage collection by removing all sessions that haven't been updated in the last $max_lifetime seconds as set in session.gc_maxlifetime. + * + * @param int $max_lifetime Max lifetime + * @return boolean true if the DELETE query succeeded. + */ +function dolSessionGC($max_lifetime) +{ + global $dbsession; + + $time_stamp = dol_now(); + + $delete_query = "DELETE FROM ".MAIN_DB_PREFIX."session"; + $delete_query .= " WHERE last_accessed < '".$dbsession->idate($time_stamp - $max_lifetime)."'"; + + $resql = $dbsession->query($delete_query); + if ($resql) { + return true; + } else { + return false; + } +} + +// Call to register user call back functions. +session_set_save_handler("dolSessionOpen", "dolSessionClose", "dolSessionRead", "dolSessionWrite", "dolSessionDestroy", "dolSessionGC"); + diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index d6999dba6e7..c7468e4c7c6 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -229,6 +229,11 @@ if (!empty($_POST["DOL_AUTOSET_COOKIE"])) // Init the 5 global objects, this include will make the 'new Xxx()' and set properties for: $conf, $db, $langs, $user, $mysoc require_once 'master.inc.php'; +// Set the handler of session +if (ini_get('session.save_handler') == 'user') { + require_once 'core/lib/phpsessionindb.lib.php'; +} + // Init session. Name of session is specific to Dolibarr instance. // Must be done after the include of master.inc.php so $conf file is loaded and vars like $dolibarr_main_force_https are set. // Note: the function dol_getprefix may have been redefined to return a different key to manage another area to protect. From faa33f2d3c71526fc5e6fb8c27754c0340cb6b91 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 12:52:39 +0100 Subject: [PATCH 20/46] FIX #15501 --- htdocs/product/list.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index efe63001349..d2f212df8da 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -57,7 +57,6 @@ $search_ref = GETPOST("search_ref", 'alpha'); $search_barcode = GETPOST("search_barcode", 'alpha'); $search_label = GETPOST("search_label", 'alpha'); $search_type = GETPOST("search_type", 'int'); -$search_sale = GETPOST("search_sale", 'int'); $search_vatrate = GETPOST("search_vatrate", 'alpha'); $searchCategoryProductOperator = (GETPOST('search_category_product_operator', 'int') ? GETPOST('search_category_product_operator', 'int') : 0); $searchCategoryProductList = GETPOST('search_category_product_list', 'array'); @@ -257,8 +256,8 @@ if (empty($reshook)) $searchCategoryProductList = array(); $search_tosell = ""; $search_tobuy = ""; - $search_vatrate = ""; $search_tobatch = ''; + $search_vatrate = ""; //$search_type=''; // There is 2 types of list: a list of product and a list of services. No list with both. So when we clear search criteria, we must keep the filter on type. $show_childproducts = ''; @@ -355,8 +354,9 @@ if (!empty($conf->variants->enabled) && (!empty($conf->global->PRODUIT_ATTRIBUTE if ($search_ref) $sql .= natural_search('p.ref', $search_ref); if ($search_label) $sql .= natural_search('p.label', $search_label); if ($search_barcode) $sql .= natural_search('p.barcode', $search_barcode); -if (isset($search_tosell) && dol_strlen($search_tosell) > 0 && $search_tosell != -1) $sql .= " AND p.tosell = ".$db->escape($search_tosell); -if (isset($search_tobuy) && dol_strlen($search_tobuy) > 0 && $search_tobuy != -1) $sql .= " AND p.tobuy = ".$db->escape($search_tobuy); +if (isset($search_tosell) && dol_strlen($search_tosell) > 0 && $search_tosell != -1) $sql .= " AND p.tosell = ".((int) $search_tosell); +if (isset($search_tobuy) && dol_strlen($search_tobuy) > 0 && $search_tobuy != -1) $sql .= " AND p.tobuy = ".((int) $search_tobuy); +if (isset($search_tobatch) && dol_strlen($search_tobatch) > 0 && $search_tobatch != -1) $sql .= " AND p.tobatch = ".((int) $search_tobatch); if ($search_vatrate) $sql .= natural_search('p.tva_tx', $search_vatrate); if (dol_strlen($canvas) > 0) $sql .= " AND p.canvas = '".$db->escape($canvas)."'"; if ($catid > 0) $sql .= " AND cp.fk_categorie = ".$catid; @@ -385,8 +385,7 @@ if ($searchCategoryProductOperator == 1) { $sql .= " AND (".implode(' AND ', $searchCategoryProductSqlList).")"; } } -if ($fourn_id > 0) $sql .= " AND pfp.fk_soc = ".$fourn_id; -if ($search_tobatch != '' && $search_tobatch >= 0) $sql .= " AND p.tobatch = ".$db->escape($search_tobatch); +if ($fourn_id > 0) $sql .= " AND pfp.fk_soc = ".((int) $fourn_id); if ($search_accountancy_code_sell) $sql .= natural_search('p.accountancy_code_sell', $search_accountancy_code_sell); if ($search_accountancy_code_sell_intra) $sql .= natural_search('p.accountancy_code_sell_intra', $search_accountancy_code_sell_intra); if ($search_accountancy_code_sell_export) $sql .= natural_search('p.accountancy_code_sell_export', $search_accountancy_code_sell_export); @@ -485,14 +484,14 @@ if ($resql) if ($search_label) $param .= "&search_label=".urlencode($search_label); if ($search_tosell != '') $param .= "&search_tosell=".urlencode($search_tosell); if ($search_tobuy != '') $param .= "&search_tobuy=".urlencode($search_tobuy); - if ($search_vatrate) $sql .= natural_search('p.tva_tx', $search_vatrate); + if ($search_tobatch) $param = "&search_tobatch=".urlencode($search_tobatch); + if ($search_vatrate) $param = "&search_vatrate=".urlencode($search_vatrate); if ($fourn_id > 0) $param .= ($fourn_id ? "&fourn_id=".$fourn_id : ""); //if ($seach_categ) $param.=($search_categ?"&search_categ=".urlencode($search_categ):""); if ($show_childproducts) $param .= ($show_childproducts ? "&search_show_childproducts=".urlencode($show_childproducts) : ""); if ($type != '') $param .= '&type='.urlencode($type); if ($search_type != '') $param .= '&search_type='.urlencode($search_type); if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); - if ($search_tobatch) $param = "&search_ref_supplier=".urlencode($search_ref_supplier); if ($search_accountancy_code_sell) $param = "&search_accountancy_code_sell=".urlencode($search_accountancy_code_sell); if ($search_accountancy_code_sell_intra) $param = "&search_accountancy_code_sell_intra=".urlencode($search_accountancy_code_sell_intra); if ($search_accountancy_code_sell_export) $param = "&search_accountancy_code_sell_export=".urlencode($search_accountancy_code_sell_export); @@ -785,7 +784,7 @@ if ($resql) // Stock if (!empty($arrayfields['stock_virtual']['checked'])) print ' '; // To batch - if (!empty($arrayfields['p.tobatch']['checked'])) print ''.$form->selectyesno($search_tobatch, '', '', '', 1).''; + if (!empty($arrayfields['p.tobatch']['checked'])) print ''.$form->selectyesno('search_tobatch', $search_tobatch, 1, false, 1).''; // Accountancy code sell if (!empty($arrayfields['p.accountancy_code_sell']['checked'])) print ''; if (!empty($arrayfields['p.accountancy_code_sell_intra']['checked'])) print ''; From cf82581a2a0d3e56198424dc386daf7b5814e106 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 14:06:02 +0100 Subject: [PATCH 21/46] Move module to experimental --- htdocs/core/modules/modHRM.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modHRM.class.php b/htdocs/core/modules/modHRM.class.php index 484564b7066..ad36253fe22 100644 --- a/htdocs/core/modules/modHRM.class.php +++ b/htdocs/core/modules/modHRM.class.php @@ -49,7 +49,7 @@ class modHRM extends DolibarrModules $this->description = "Management of employees carrier and feelings (department, employment contract)"; // Possible values for version are: 'development', 'experimental', 'dolibarr' or version - $this->version = 'development'; + $this->version = 'experimental'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); // Name of image file used for this module. From 551f82ef6a4bb8cdf6302f902de6eda64495f462 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 14:15:43 +0100 Subject: [PATCH 22/46] Fix label --- htdocs/langs/en_US/hrm.lang | 1 + htdocs/user/list.php | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/hrm.lang b/htdocs/langs/en_US/hrm.lang index 6cc7f6bef24..3b8f137e103 100644 --- a/htdocs/langs/en_US/hrm.lang +++ b/htdocs/langs/en_US/hrm.lang @@ -16,3 +16,4 @@ DictionaryFunction=HRM - Job positions Employees=Employees Employee=Employee NewEmployee=New employee +ListOfEmployees=List of employees diff --git a/htdocs/user/list.php b/htdocs/user/list.php index a6237f47052..257bcd4c6be 100644 --- a/htdocs/user/list.php +++ b/htdocs/user/list.php @@ -299,7 +299,11 @@ $formother = new FormOther($db); //$help_url="EN:Module_MyObject|FR:Module_MyObject_FR|ES:Módulo_MyObject"; $help_url = ''; -$text = $langs->trans("ListOfUsers"); +if ($contextpage == 'employeelist' && $search_employee == 1) { + $text = $langs->trans("ListOfEmployees"); +} else { + $text = $langs->trans("ListOfUsers"); +} $user2 = new User($db); From d50212597525c4b3a3c7f3e065b2f3477343ca7b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 14:32:19 +0100 Subject: [PATCH 23/46] 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 b355e8b5492..a1500d84186 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -2595,7 +2595,7 @@ input.vmenusearchselectcombo[type=text] { a.vmenu:link, a.vmenu:visited, a.vmenu:hover, a.vmenu:active, span.vmenu, span.vsmenu { white-space: nowrap; font-family: ; text-align: ; } a.vmenu:link, a.vmenu:visited, a.vmenu:hover, a.vmenu:active, span.vmenu, span.vmenu:link, span.vmenu:visited, span.vmenu:hover, span.vmenu:active { font-weight: bold; } /* bold = 600, 500 is ko with Edge on 1200x960 */ -font.vmenudisabled { font-family: ; text-align: ; font-weight: bold; color: #aaa; margin-left: 4px; } /* bold = 600, 500 is ko with Edge on 1200x960 */ +font.vmenudisabled { font-family: ; text-align: ; font-weight: bold; color: #aaa; margin-left: 4px; white-space: nowrap; } /* bold = 600, 500 is ko with Edge on 1200x960 */ a.vmenu:link, a.vmenu:visited { color: var(--colortextbackvmenu); } a.vsmenu:link, a.vsmenu:visited, a.vsmenu:hover, a.vsmenu:active, span.vsmenu { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index e119c5348a1..0dd6acab9f7 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -2578,7 +2578,7 @@ div.vmenu, td.vmenu { .searchform { padding-top: 10px; } a.vmenu:link, a.vmenu:visited, a.vmenu:hover, a.vmenu:active, span.vmenu, span.vsmenu { white-space: nowrap; font-size:px; font-family: ; text-align: ; font-weight: bold; } -font.vmenudisabled { font-size:px; font-family: ; text-align: ; font-weight: bold; color: #aaa; margin-left: 4px; } +font.vmenudisabled { font-size:px; font-family: ; text-align: ; font-weight: bold; color: #aaa; margin-left: 4px; white-space: nowrap; } a.vmenu:link, a.vmenu:visited { color: #; } a.vsmenu:link, a.vsmenu:visited, a.vsmenu:hover, a.vsmenu:active, span.vsmenu { font-size:px; font-family: ; text-align: ; font-weight: normal; color: #202020; margin: 1px 1px 1px 8px; } From 1be9789c339c3bb0fcbe48c8a5f7b9be6072db1a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 14:54:26 +0100 Subject: [PATCH 24/46] Fix unalterable logs --- htdocs/blockedlog/admin/blockedlog.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/htdocs/blockedlog/admin/blockedlog.php b/htdocs/blockedlog/admin/blockedlog.php index b6ce9cda1bc..39725eae3b7 100644 --- a/htdocs/blockedlog/admin/blockedlog.php +++ b/htdocs/blockedlog/admin/blockedlog.php @@ -35,6 +35,8 @@ if (!$user->admin || empty($conf->blockedlog->enabled)) accessforbidden(); $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); +$withtab = GETPOST('withtab', 'int'); + /* * Actions @@ -49,7 +51,7 @@ if (preg_match('/set_(.*)/', $action, $reg)) if (dolibarr_set_const($db, $code, $values, 'chaine', 0, '', $conf->entity) > 0) { - header("Location: ".$_SERVER["PHP_SELF"]); + header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : '')); exit; } else { dol_print_error($db); @@ -61,7 +63,7 @@ if (preg_match('/del_(.*)/', $action, $reg)) $code = $reg[1]; if (dolibarr_del_const($db, $code, 0) > 0) { - Header("Location: ".$_SERVER["PHP_SELF"]); + Header("Location: ".$_SERVER["PHP_SELF"].($withtab ? '?withtab='.$withtab : '')); exit; } else { dol_print_error($db); @@ -79,15 +81,13 @@ $block_static = new BlockedLog($db); llxHeader('', $langs->trans("BlockedLogSetup")); $linkback = ''; -if (GETPOST('withtab', 'alpha')) -{ +if ($withtab) { $linkback = ''.$langs->trans("BackToModuleList").''; } print load_fiche_titre($langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog'), $linkback); -if (GETPOST('withtab', 'alpha')) -{ +if ($withtab) { $head = blockedlogadmin_prepare_head(); print dol_get_fiche_head($head, 'blockedlog', '', -1); } @@ -114,21 +114,26 @@ if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY)) { print ''; print ''.$langs->trans("BlockedLogAuthorityUrl").img_info($langs->trans('BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote')).''; print ''; + print '
'; print ''; print ''; + print ''; print ''; print ''; print '
'; + print ''; } print ''; print ''.$langs->trans("BlockedLogDisableNotAllowedForCountry").''; print ''; + print '
'; print ''; print ''; +print ''; $sql = "SELECT rowid, code as code_iso, code_iso as code_iso3, label, favorite"; $sql .= " FROM ".MAIN_DB_PREFIX."c_country"; @@ -168,7 +173,7 @@ print ''; print ''; -if (GETPOST('withtab', 'alpha')) +if ($withtab) { print dol_get_fiche_end(); } From 148f8222516378eaac17fb86ef712a0c1a81ed47 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 14:59:37 +0100 Subject: [PATCH 25/46] Trans --- htdocs/langs/en_US/languages.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/languages.lang b/htdocs/langs/en_US/languages.lang index 574ac2146dd..015e6dcfa25 100644 --- a/htdocs/langs/en_US/languages.lang +++ b/htdocs/langs/en_US/languages.lang @@ -40,6 +40,7 @@ Language_es_PA=Spanish (Panama) Language_es_PY=Spanish (Paraguay) Language_es_PE=Spanish (Peru) Language_es_PR=Spanish (Puerto Rico) +Language_es_US=Spanish (USA) Language_es_UY=Spanish (Uruguay) Language_es_GT=Spanish (USA) Language_es_VE=Spanish (Venezuela) From a7347b89d1ad7c946a217d3bf9d52809b1c687e0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 16:54:13 +0100 Subject: [PATCH 26/46] Look and feel v13 --- htdocs/user/card.php | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 52b94cbc2f9..ba7cd546d54 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1018,50 +1018,54 @@ if ($action == 'create' || $action == 'adduserldap') } // Tel - print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePro").''; + print ''.$langs->trans("PhonePro").''; print ''; + print img_picto('', 'object_phoning'); if (!empty($ldap_phone)) { print ''; print $ldap_phone; } else { - print ''; + print ''; } print ''; // Tel portable - print ''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").''; + print ''.$langs->trans("PhoneMobile").''; print ''; + print img_picto('', 'object_phoning_mobile'); if (!empty($ldap_mobile)) { print ''; print $ldap_mobile; } else { - print ''; + print ''; } print ''; // Fax - print ''.img_picto('', 'object_phoning_fax').' '.$langs->trans("Fax").''; + print ''.$langs->trans("Fax").''; print ''; + print img_picto('', 'object_phoning_fax'); if (!empty($ldap_fax)) { print ''; print $ldap_fax; } else { - print ''; + print ''; } print ''; // EMail - print 'global->USER_MAIL_REQUIRED) ? ' class="fieldrequired"' : '').'>'.img_picto('', 'object_email').' '.$langs->trans("EMail").''; + print 'global->USER_MAIL_REQUIRED) ? ' class="fieldrequired"' : '').'>'.$langs->trans("EMail").''; print ''; + print img_picto('', 'object_email'); if (!empty($ldap_mail)) { print ''; print $ldap_mail; } else { - print ''; + print ''; } print ''; @@ -1093,7 +1097,7 @@ if ($action == 'create' || $action == 'adduserldap') { print ''.$langs->trans("AccountancyCode").''; print ''; - print ''; + print ''; print ''; } @@ -2357,11 +2361,12 @@ if ($action == 'create' || $action == 'adduserldap') } // Tel pro - print "".''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePro").''; + print "".''.$langs->trans("PhonePro").''; print ''; + print img_picto('', 'object_phoning'); if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { print ''; print $object->office_phone; @@ -2369,11 +2374,12 @@ if ($action == 'create' || $action == 'adduserldap') print ''; // Tel mobile - print "".''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").''; + print "".''.$langs->trans("PhoneMobile").''; print ''; + print img_picto('', 'object_phoning_mobile'); if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { print ''; print $object->user_mobile; @@ -2381,11 +2387,12 @@ if ($action == 'create' || $action == 'adduserldap') print ''; // Fax - print "".''.img_picto('', 'object_phoning_fax').' '.$langs->trans("Fax").''; + print "".''.$langs->trans("Fax").''; print ''; + print img_picto('', 'object_phoning_fax'); if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { print ''; print $object->office_fax; @@ -2393,11 +2400,12 @@ if ($action == 'create' || $action == 'adduserldap') print ''; // EMail - print "".'global->USER_MAIL_REQUIRED) ? ' class="fieldrequired"' : '').'>'.img_picto('', 'object_email').' '.$langs->trans("EMail").''; + print "".'global->USER_MAIL_REQUIRED) ? ' class="fieldrequired"' : '').'>'.$langs->trans("EMail").''; print ''; + print img_picto('', 'object_email'); if ($caneditfield && empty($object->ldap_sid)) { - print ''; + print ''; } else { print ''; print $object->email; From 57d34bc543088b056763f004ae64ee8c1970c6de Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 17:03:02 +0100 Subject: [PATCH 27/46] Fix link --- htdocs/user/hierarchy.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/user/hierarchy.php b/htdocs/user/hierarchy.php index a27946e7474..1a6a630d27c 100644 --- a/htdocs/user/hierarchy.php +++ b/htdocs/user/hierarchy.php @@ -43,6 +43,9 @@ if ($user->socid > 0) $sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $search_user = GETPOST('search_user', 'alpha'); +// Load mode employee +$mode = GETPOST("mode", 'alpha'); + $userstatic = new User($db); $search_statut = GETPOST('search_statut', 'int'); @@ -143,10 +146,7 @@ if (!is_array($user_arbo) && $user_arbo < 0) $param = "search_statut=".urlencode($search_statut); $newcardbutton = ''; - if ($canadduser) - { - $newcardbutton .= dolGetButtonTitle($langs->trans('NewUser'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/user/card.php?action=create'.($mode == 'employee' ? '&employee=1' : '').'&leftmenu='); - } + $newcardbutton .= dolGetButtonTitle($langs->trans('NewUser'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/user/card.php?action=create'.($mode == 'employee' ? '&employee=1' : '').'&leftmenu=', '', $canadduser); $morehtmlright .= dolGetButtonTitle($langs->trans("List"), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/user/list.php'.(($search_statut != '' && $search_statut >= 0) ? '?search_statut='.$search_statut : '')); $param = array('morecss'=>'marginleftonly btnTitleSelected'); From b0cf81a58ca594dfa900bde1d37643f27e1f0d51 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 24 Nov 2020 17:42:36 +0100 Subject: [PATCH 28/46] Update README-FR --- doc/install/README-FR | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/install/README-FR b/doc/install/README-FR index 2cee29cf2df..5872ec0e3d1 100644 --- a/doc/install/README-FR +++ b/doc/install/README-FR @@ -6,13 +6,14 @@ README (french) Téléchargement -------------------------------- -* Dolibarr ERP/CRM can be downloaded at sourceforge: -http://sourceforge.net/projects/dolibarr/files -or from Dolibarr official web site: +* Dolibarr ERP/CRM peut être téléchargé sur sourceforge: +https://sourceforge.net/projects/dolibarr/files + +ou sur le site officiel de Dolibarr: https://www.dolibarr.org -* Most external modules are only available on DoliStore: -https://www.dolistore.org +* La plupart des modules externes ne sont disponibles que sur le DoliStore officiel: +https://www.dolistore.com -------------------------------- @@ -24,4 +25,4 @@ README-FR à la racine. * Une documentation utilisateur francophone plus consistante est disponible en ligne sur le wiki de Dolibarr à l'adresse: -https://wiki.dolibarr.org +https://wiki.dolibarr.org/index.php/Accueil From a5af9996badd8a10886c6dd24aead2ed6532b814 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 24 Nov 2020 18:17:15 +0100 Subject: [PATCH 29/46] Update copyright --- build/debian/copyright | 61 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/build/debian/copyright b/build/debian/copyright index 7b199adf693..d5fdf416a65 100644 --- a/build/debian/copyright +++ b/build/debian/copyright @@ -1,4 +1,4 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Dolibarr Upstream-Contact: Laurent Destailleur Source: https://www.dolibarr.org/files/stable/standard/ @@ -38,6 +38,7 @@ Copyright: 2002-2009, Rodolphe Quiedeville 2011, Herve Prot 2011, Remy Younes 2012-2013, Christophe Battarel + License: GPL-3+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -56,7 +57,9 @@ License: GPL-3+ . On Debian systems, the full text of the GNU General Public License version 3 can be found in the file - `/usr/share/common-licenses/GPL-3'. + '/usr/share/common-licenses/GPL-3'. + +------------------------------------------------------------ Files: htdocs/includes/adodbtime/* Copyright: 2003-2005, John Lim @@ -80,6 +83,9 @@ Comment: Those files are not shipped in the binary package since we use the library as packaged in "libphp-adodb". + +------------------------------------------------------------ + Files: htdocs/includes/ckeditor/* Copyright: 2003-2012 CKSource - Frederico Knabben License: GPL-2+ @@ -109,6 +115,9 @@ Comment: Those files are not shipped in the binary package since we use the library as packaged in "ckeditor". + +------------------------------------------------------------ + Files: htdocs/includes/fonts/* Copyright: 2003, Bitstream Inc unknown, Gavin Graham @@ -158,7 +167,10 @@ License: other Comments: Those files are not shipped in the binary package as we configure Dolibarr to use Dejavu fonts from "fonts-dejavu-core". - + + +------------------------------------------------------------ + Files: doc/images/* Copyright: Laurent Destailleur License: CC-BY-SA-3.0 @@ -174,7 +186,10 @@ License: CC-BY-SA-3.0 distribute the resulting work only under the same, similar or a compatible license. . - For more information, see http://creativecommons.org/licenses/by-sa/3.0/ + For more information, see https://creativecommons.org/licenses/by-sa/3.0/ + + +------------------------------------------------------------ Files: htdocs/includes/fpdfi/* Copyright: 2004-2011 Setasign - Jan Slabon @@ -196,7 +211,10 @@ License: GPL-2+ . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + '/usr/share/common-licenses/GPL-2'. + + +------------------------------------------------------------ Files: htdocs/includes/geoip/* Copyright: 2007 MaxMind LLC @@ -216,10 +234,14 @@ License: LGPL-2.1+ . On Debian systems, the full text of the GNU Lesser General Public License version 2.1 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. + '/usr/share/common-licenses/LGPL-2.1'. + + +------------------------------------------------------------ Files: htdocs/includes/jquery/* Copyright: JQuery team +https://www.jquery.com License: GPL-2+ or MIT === GPL-2+ LICENSE NOTICE === . @@ -240,7 +262,7 @@ License: GPL-2+ or MIT . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + '/usr/share/common-licenses/GPL-2'. . === MIT LICENSE === . @@ -267,6 +289,8 @@ Comment: "libjs-jquery-ui". Most of the plugins are shipped though. +------------------------------------------------------------ + Files: htdocs/includes/jquery/plugins/flot/* Copyright: Flot team License: Public-Domain @@ -275,6 +299,9 @@ Comment: Those files are not shipped in the binary package because we configure Dolibarr to use the files provided by "libjs-flot". + +------------------------------------------------------------ + Files: htdocs/includes/jsgantt/* Copyright: JSGantt team License: GPL-2+ @@ -295,7 +322,10 @@ License: GPL-2+ . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + '/usr/share/common-licenses/GPL-2'. + + +------------------------------------------------------------ Files: htdocs/includes/nusoap/* Copyright: 2002-2010 NuSphere Corporation @@ -315,11 +345,14 @@ License: LGPL-2.1+ . On Debian systems, the full text of the GNU Lesser General Public License version 2.1 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. + '/usr/share/common-licenses/LGPL-2.1'. Comment: Those files are not shipped in the binary package since we configure Dolibarr to use the library provided in "libnusoap-php". + +------------------------------------------------------------ + Files: htdocs/includes/odtphp/* Copyright: 2008, Julien Pauli 2008, Cyril PIERRE de GEYER @@ -342,7 +375,10 @@ License: GPL-2+ . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file - `/usr/share/common-licenses/GPL-2'. + '/usr/share/common-licenses/GPL-2'. + + +------------------------------------------------------------ Files: htdocs/includes/phpexcel/* Copyright: 2006-2011 PHPExcel (http://www.codeplex.com/PHPExcel) @@ -362,7 +398,10 @@ License: LGPL-2.1+ . On Debian systems, the full text of the GNU Lesser General Public License version 2.1 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. + '/usr/share/common-licenses/LGPL-2.1'. + + +------------------------------------------------------------ Files: htdocs/includes/tcpdf/* Copyright: 2002-2013 Nicola Asuni - Tecnick.com LTD From 1b6bc2a86d7e7bc8902db9106d2766bb24ebc131 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 24 Nov 2020 18:46:37 +0100 Subject: [PATCH 30/46] Update README --- dev/translation/README | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dev/translation/README b/dev/translation/README index 9727f91e2e6..8d6954878b5 100644 --- a/dev/translation/README +++ b/dev/translation/README @@ -2,13 +2,18 @@ README (English) -------------------------------- This directory contains tools to generate translation files for a new languages or to update translation files for existing languages. + See Dolibarr Wiki page: https://wiki.dolibarr.org/index.php/Translator_documentation For more information on how to use them. -for Linux OS: -To install transifex client: +Translation of Dolibarr Project at Transifex: +https://www.transifex.com/dolibarr-association/dolibarr/dashboard/ + + +Installation of Transifex Client: +--------------------------------- +for Linux OS +to install or to update transifex client: sudo pip install --upgrade transifex-client -To update transifex client: -sudo pip install --upgrade transifex-client From bd0236edebfaf1a11ce3839d17087adb61ef20e2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 20:53:42 +0100 Subject: [PATCH 31/46] Fix #15438 --- .../commande/doc/pdf_eratosthene.modules.php | 12 ++- .../facture/doc/pdf_sponge.modules.php | 35 ++++--- .../modules/propale/doc/pdf_cyan.modules.php | 97 ++++++++++++------- 3 files changed, 96 insertions(+), 48 deletions(-) diff --git a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php index 46409b362af..36374ce66b7 100644 --- a/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_eratosthene.modules.php @@ -1756,7 +1756,6 @@ class pdf_eratosthene extends ModelePDFCommandes $this->cols['photo']['status'] = true; } - $rank = $rank + 10; $this->cols['vat'] = array( 'rank' => $rank, @@ -1784,6 +1783,17 @@ class pdf_eratosthene extends ModelePDFCommandes 'border-left' => true, // add left line separator ); + // Adapt dynamically the width of subprice, if text is too long. + $tmpwidth = 0; + $nblines = count($object->lines); + for ($i = 0; $i < $nblines; $i++) { + $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails))); + $tmpwidth = max($tmpwidth, $tmpwidth2); + } + if ($tmpwidth > 10) { + $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10)); + } + $rank = $rank + 10; $this->cols['qty'] = array( 'rank' => $rank, diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 4107e25ca03..646b4831697 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -304,7 +304,7 @@ class pdf_sponge extends ModelePDFFactures $file = $dir."/SPECIMEN.pdf"; } else { $objectref = dol_sanitizeFileName($object->ref); - $dir = $conf->facture->multidir_output[$conf->entity]."/".$objectref; + $dir = $conf->facture->multidir_output[$object->entity]."/".$objectref; $file = $dir."/".$objectref.".pdf"; } if (!file_exists($dir)) @@ -443,7 +443,7 @@ class pdf_sponge extends ModelePDFFactures } } - // Display notes + // Displays notes $notetoshow = empty($object->note_public) ? '' : $object->note_public; if (!empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) { @@ -608,6 +608,7 @@ class pdf_sponge extends ModelePDFFactures $showpricebeforepagebreak = 1; $posYAfterImage = 0; + $posYAfterDescription = 0; if ($this->getColumnStatus('photo')) { @@ -671,6 +672,7 @@ class pdf_sponge extends ModelePDFFactures { $pdf->commitTransaction(); } + $posYAfterDescription = $pdf->GetY(); } $nexY = $pdf->GetY(); @@ -684,7 +686,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->setPage($pageposafter); $curY = $tab_top_newpage; } - $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par defaut + $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font // VAT Rate if ($this->getColumnStatus('vat')) @@ -1233,7 +1235,7 @@ class pdf_sponge extends ModelePDFFactures /** * Show total to pay * - * @param TCPDI $pdf Object PDF + * @param TCPDF $pdf Object PDF * @param Facture $object Object invoice * @param int $deja_regle Amount already paid (in the currency of invoice) * @param int $posy Position depart @@ -1658,8 +1660,6 @@ class pdf_sponge extends ModelePDFFactures $pdf->MultiCell($largcol2, $tab2_hl, price($sign * $total_ttc, 0, $outputlangs), $useborder, 'R', 1); - - // Retained warranty if ($object->displayRetainedWarranty()) { @@ -1720,7 +1720,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->MultiCell($largcol2, $tab2_hl, price($creditnoteamount, 0, $outputlangs), 0, 'R', 0); } - // Escompte + /* if ($object->close_code == Facture::CLOSECODE_DISCOUNTVAT) { $index++; @@ -1733,6 +1733,7 @@ class pdf_sponge extends ModelePDFFactures $resteapayer = 0; } + */ $index++; $pdf->SetTextColor(0, 0, 60); @@ -1847,7 +1848,7 @@ class pdf_sponge extends ModelePDFFactures pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); // Show Draft Watermark - if ($object->statut == Facture::STATUS_DRAFT && (!empty($conf->global->FACTURE_DRAFT_WATERMARK))) + if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->FACTURE_DRAFT_WATERMARK))) { pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->FACTURE_DRAFT_WATERMARK); } @@ -1875,8 +1876,7 @@ class pdf_sponge extends ModelePDFFactures } else { $logo = $logodir.'/logos/'.$this->emetteur->logo; } - if (is_readable($logo)) - { + if (is_readable($logo)) { $height = pdf_getHeightForLogo($logo); $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) } else { @@ -1918,7 +1918,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref); - if ($object->statut == Facture::STATUS_DRAFT) + if ($object->statut == $object::STATUS_DRAFT) { $pdf->SetTextColor(128, 0, 0); $textref .= ' - '.$outputlangs->transnoentities("NotValidated"); @@ -2092,7 +2092,7 @@ class pdf_sponge extends ModelePDFFactures $pdf->SetFont('', '', $default_font_size - 1); $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L'); - // If BILLING contact defined on invoice, we use it + // If BILLING contact defined, we use it $usecontact = false; $arrayidcontact = $object->getIdContact('external', 'BILLING'); if (count($arrayidcontact) > 0) @@ -2273,6 +2273,17 @@ class pdf_sponge extends ModelePDFFactures 'border-left' => true, // add left line separator ); + // Adapt dynamically the width of subprice, if text is too long. + $tmpwidth = 0; + $nblines = count($object->lines); + for ($i = 0; $i < $nblines; $i++) { + $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails))); + $tmpwidth = max($tmpwidth, $tmpwidth2); + } + if ($tmpwidth > 10) { + $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10)); + } + $rank = $rank + 10; $this->cols['qty'] = array( 'rank' => $rank, diff --git a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php index ac83d194749..91aaa9de4a4 100644 --- a/htdocs/core/modules/propale/doc/pdf_cyan.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_cyan.modules.php @@ -200,6 +200,8 @@ class pdf_cyan extends ModelePDFPropales // phpcs:enable global $user, $langs, $conf, $mysoc, $db, $hookmanager, $nblines; + dol_syslog("write_file outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null')); + if (!is_object($outputlangs)) $outputlangs = $langs; // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO if (!empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output = 'ISO-8859-1'; @@ -320,6 +322,10 @@ class pdf_cyan extends ModelePDFPropales global $action; $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + // Set nblines with the new facture lines content after hook + $nblines = count($object->lines); + //$nbpayments = count($object->getListOfPayments()); + // Create pdf instance $pdf = pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance @@ -393,7 +399,7 @@ class pdf_cyan extends ModelePDFPropales $pdf->SetFont('', '', $default_font_size - 1); $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1); - $nexY = $pdf->GetY(); + $nexY = max($pdf->GetY(), $nexY); $height_incoterms = $nexY - $tab_top; // Rect takes a length in 3rd parameter @@ -420,8 +426,7 @@ class pdf_cyan extends ModelePDFPropales // Extrafields in note $extranote = $this->getExtrafieldsInHtml($object, $outputlangs); - if (!empty($extranote)) - { + if (!empty($extranote)) { $notetoshow = dol_concatdesc($notetoshow, $extranote); } @@ -554,7 +559,7 @@ class pdf_cyan extends ModelePDFPropales // Use new auto column system $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref); - // tab simulation to know line height + // Table simulation to know the height of the title line $pdf->startTransaction(); $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop); $pdf->rollbackTransaction(true); @@ -633,7 +638,6 @@ class pdf_cyan extends ModelePDFPropales { $pdf->AddPage('', '', true); if (!empty($tplidx)) $pdf->useTemplate($tplidx); - //if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); $pdf->setPage($pageposafter + 1); } } else { @@ -773,20 +777,21 @@ class pdf_cyan extends ModelePDFPropales } // retrieve global local tax - if ($localtax1_type && $localtax1ligne != 0) + if ($localtax1_type && $localtax1ligne != 0) { $this->localtax1[$localtax1_type][$localtax1_rate] += $localtax1ligne; - if ($localtax2_type && $localtax2ligne != 0) + } + if ($localtax2_type && $localtax2ligne != 0) { $this->localtax2[$localtax2_type][$localtax2_rate] += $localtax2ligne; + } if (($object->lines[$i]->info_bits & 0x01) == 0x01) $vatrate .= '*'; if (!isset($this->tva[$vatrate])) $this->tva[$vatrate] = 0; $this->tva[$vatrate] += $tvaligne; - if ($posYAfterImage > $posYAfterDescription) $nexY = $posYAfterImage; + if ($posYAfterImage > $posYAfterDescription) $nexY = max($nexY, $posYAfterImage); // Add line - if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) - { + if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) { $pdf->setPage($pageposafter); $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80))); //$pdf->SetDrawColor(190,190,200); @@ -797,14 +802,12 @@ class pdf_cyan extends ModelePDFPropales // Detect if some page were added automatically and output _tableau for past pages - while ($pagenb < $pageposafter) - { + while ($pagenb < $pageposafter) { $pdf->setPage($pagenb); - if ($pagenb == $pageposbeforeprintlines) - { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code); + if ($pagenb == $pageposbeforeprintlines) { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code, $outputlangsbis); } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code, $outputlangsbis); } $this->_pagefoot($pdf, $object, $outputlangs, 1); $pagenb++; @@ -812,13 +815,12 @@ class pdf_cyan extends ModelePDFPropales $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); } - if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) - { - if ($pagenb == $pageposafter) - { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code); + + if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { + if ($pagenb == $pageposafter) { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, $hidetop, 1, $object->multicurrency_code, $outputlangsbis); } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code); + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1, $object->multicurrency_code, $outputlangsbis); } $this->_pagefoot($pdf, $object, $outputlangs, 1); // New page @@ -832,10 +834,10 @@ class pdf_cyan extends ModelePDFPropales // Show square if ($pagenb == $pageposbeforeprintlines) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code); + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code, $outputlangsbis); $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1; } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code); + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code, $outputlangsbis); $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforsignature - $heightforfooter + 1; } @@ -859,7 +861,7 @@ class pdf_cyan extends ModelePDFPropales $posy = $this->drawSignatureArea($pdf, $object, $posy, $outputlangs); } - // Pied de page + // Pagefoot $this->_pagefoot($pdf, $object, $outputlangs); if (method_exists($pdf, 'AliasNbPages')) $pdf->AliasNbPages(); @@ -1160,7 +1162,7 @@ class pdf_cyan extends ModelePDFPropales * * @param TCPDF $pdf Object PDF * @param Propal $object Object proposal - * @param int $deja_regle Montant deja regle + * @param int $deja_regle Amount already paid (in the currency of invoice) * @param int $posy Position depart * @param Translate $outputlangs Objet langs * @return int Position pour suite @@ -1417,7 +1419,7 @@ class pdf_cyan extends ModelePDFPropales $pdf->SetFillColor(255,255,255); $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1); + $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort"), $useborder, 'L', 1); $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); $pdf->MultiCell($largcol2, $tab2_hl, price($object->total_ttc - $deja_regle, 0, $outputlangs), $useborder, 'R', 1); @@ -1525,7 +1527,7 @@ class pdf_cyan extends ModelePDFPropales pdf_pagehead($pdf, $outputlangs, $this->page_hauteur); // Show Draft Watermark - if ($object->statut == 0 && (!empty($conf->global->PROPALE_DRAFT_WATERMARK))) + if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->PROPALE_DRAFT_WATERMARK))) { pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->PROPALE_DRAFT_WATERMARK); } @@ -1579,7 +1581,13 @@ class pdf_cyan extends ModelePDFPropales $posy += 5; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R'); + $textref = $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref); + if ($object->statut == $object::STATUS_DRAFT) + { + $pdf->SetTextColor(128, 0, 0); + $textref .= ' - '.$outputlangs->transnoentities("NotValidated"); + } + $pdf->MultiCell($w, 4, $textref, '', 'R'); $posy += 1; $pdf->SetFont('', '', $default_font_size - 2); @@ -1624,7 +1632,12 @@ class pdf_cyan extends ModelePDFPropales $posy += 4; $pdf->SetXY($posx, $posy); $pdf->SetTextColor(0, 0, 60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DateEndPropal")." : ".dol_print_date($object->fin_validite, "day", false, $outputlangs, true), '', 'R'); + + $title = $outputlangs->transnoentities("DateEndPropal"); + if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && is_object($outputlangsbis)) { + $title .= ' - '.$outputlangsbis->transnoentities("DateEndPropal"); + } + $pdf->MultiCell($w, 3, $title." : ".dol_print_date($object->fin_validite, "day", false, $outputlangs, true), '', 'R'); if ($object->thirdparty->code_client) { @@ -1676,10 +1689,13 @@ class pdf_cyan extends ModelePDFPropales $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object); // Show sender - $posy = 42 + $top_shift; + $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42; + $posy += $top_shift; $posx = $this->marge_gauche; if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx = $this->page_largeur - $this->marge_droite - 80; - $hautcadre = 40; + + $hautcadre = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 38 : 40; + $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 82; // Show sender frame $pdf->SetTextColor(0, 0, 0); @@ -1688,19 +1704,19 @@ class pdf_cyan extends ModelePDFPropales $pdf->MultiCell(66, 5, $outputlangs->transnoentities("BillFrom").":", 0, 'L'); $pdf->SetXY($posx, $posy); $pdf->SetFillColor(230, 230, 230); - $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); + $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1); $pdf->SetTextColor(0, 0, 60); // Show sender name $pdf->SetXY($posx + 2, $posy + 3); $pdf->SetFont('', 'B', $default_font_size); - $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); $posy = $pdf->getY(); // Show sender information $pdf->SetXY($posx + 2, $posy); $pdf->SetFont('', '', $default_font_size - 1); - $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); + $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L'); // If CUSTOMER contact defined, we use it @@ -1920,6 +1936,17 @@ class pdf_cyan extends ModelePDFPropales 'border-left' => true, // add left line separator ); + // Adapt dynamically the width of subprice, if text is too long. + $tmpwidth = 0; + $nblines = count($object->lines); + for ($i = 0; $i < $nblines; $i++) { + $tmpwidth2 = dol_strlen(dol_string_nohtmltag(pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails))); + $tmpwidth = max($tmpwidth, $tmpwidth2); + } + if ($tmpwidth > 10) { + $this->cols['subprice']['width'] += (2 * ($tmpwidth - 10)); + } + $rank = $rank + 10; $this->cols['qty'] = array( 'rank' => $rank, From bac24485c2f211864ee4490395f860a64b96b4a6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 24 Nov 2020 21:12:44 +0100 Subject: [PATCH 32/46] Fix label of project. Must use ProjectLabel instead of Label --- htdocs/projet/card.php | 9 ++++----- htdocs/projet/class/project.class.php | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 94a7b772fac..771998fbb6c 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -126,7 +126,7 @@ if (empty($reshook)) } if (!GETPOST('title')) { - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors'); $error++; } @@ -236,7 +236,7 @@ if (empty($reshook)) { $error++; //$_GET["id"]=$_POST["id"]; // We return on the project card - setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ProjectLabel")), null, 'errors'); } $db->begin(); @@ -529,7 +529,7 @@ if ($action == 'create' && $user->rights->projet->creer) print ''; // Label - print ''.$langs->trans("Label").''; + print ''.$langs->trans("ProjectLabel").''; // Usage (opp, task, bill time, ...) print ''; @@ -804,10 +804,9 @@ if ($action == 'create' && $user->rights->projet->creer) print ''; // Label - print ''.$langs->trans("Label").''; + print ''.$langs->trans("ProjectLabel").''; print ''; - // Status print ''.$langs->trans("Status").''; print '