From 7cdd334995a855982c936f7e0ead519f8afa7573 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Tue, 28 Jan 2020 11:37:23 +0100 Subject: [PATCH 01/14] FIX require category class in extrafield --- htdocs/core/class/extrafields.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index c2c7752e994..9400c64de85 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1321,6 +1321,7 @@ class ExtraFields print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.
'; } } else { + require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php'; $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1); $out .= ''; foreach ($data as $data_key => $data_value) { @@ -1548,6 +1549,7 @@ class ExtraFields print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.
'; } } else { + require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php'; $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1); $out = $form->multiselectarray($keyprefix . $key . $keysuffix, $data, $value_arr, '', 0, '', 0, '100%'); } @@ -1628,7 +1630,7 @@ class ExtraFields if ($hidden) return ''; // This is a protection. If field is hidden, we should just not call this method. //if ($computed) $value = // $value is already calculated into $value before calling this method - + $showsize=0; if ($type == 'date') { From e770b503e5a03002f04e95b5c475a8add24b55f5 Mon Sep 17 00:00:00 2001 From: gti-eu <60189441+gti-eu@users.noreply.github.com> Date: Tue, 28 Jan 2020 13:23:26 +0100 Subject: [PATCH 02/14] Fix mailcollector text format --- .../class/emailcollector.class.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 0844cff2057..5b7d394dce0 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2013,6 +2013,9 @@ class EmailCollector extends CommonObject // TEXT if ($p->type == 0 && $data) { + if(!empty($params['charset'])) { + $data = $this->convertStringEncoding($data, $params['charset']); + } // Messages may be split in different parts because of inline attachments, // so append parts together with blank row. if (strtolower($p->subtype) == 'plain') @@ -2028,6 +2031,9 @@ class EmailCollector extends CommonObject // There are no PHP functions to parse embedded messages, // so this just appends the raw source to the main message. elseif ($p->type == 2 && $data) { + if(!empty($params['charset'])) { + $data = $this->convertStringEncoding($data, $params['charset']); + } $plainmsg .= $data."\n\n"; } @@ -2039,4 +2045,18 @@ class EmailCollector extends CommonObject } } } + + protected function convertStringEncoding($string, $fromEncoding, $toEncoding='UTF-8') { + if(!$string || $fromEncoding == $toEncoding) { + return $string; + } + $convertedString = function_exists('iconv') ? @iconv($fromEncoding, $toEncoding . '//IGNORE', $string) : null; + if(!$convertedString && extension_loaded('mbstring')) { + $convertedString = @mb_convert_encoding($string, $toEncoding, $fromEncoding); + } + if(!$convertedString) { + throw new Exception('Mime string encoding conversion failed'); + } + return $convertedString; + } } From 8a9ca97b45fa25d0a6ebb36423f41f0ea491a8d5 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 28 Jan 2020 12:26:59 +0000 Subject: [PATCH 03/14] Fixing style errors. --- htdocs/emailcollector/class/emailcollector.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 5b7d394dce0..69e3c83fc66 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2045,8 +2045,9 @@ class EmailCollector extends CommonObject } } } - - protected function convertStringEncoding($string, $fromEncoding, $toEncoding='UTF-8') { + + protected function convertStringEncoding($string, $fromEncoding, $toEncoding = 'UTF-8') + { if(!$string || $fromEncoding == $toEncoding) { return $string; } From c169632f7b267b03905e715bd9f269ddfcd04f6f Mon Sep 17 00:00:00 2001 From: gti-eu <60189441+gti-eu@users.noreply.github.com> Date: Tue, 28 Jan 2020 14:24:42 +0100 Subject: [PATCH 04/14] Add missing doc --- htdocs/emailcollector/class/emailcollector.class.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 69e3c83fc66..514612c4b2b 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2046,6 +2046,14 @@ class EmailCollector extends CommonObject } } + /** + * Converts a string from one encoding to another. + * @param string $string + * @param string $fromEncoding + * @param string $toEncoding + * @return string Converted string if conversion was successful, or the original string if not + * @throws Exception + */ protected function convertStringEncoding($string, $fromEncoding, $toEncoding = 'UTF-8') { if(!$string || $fromEncoding == $toEncoding) { From 8af5d87e80e1bfda9acf71f44ac7433da55b59e6 Mon Sep 17 00:00:00 2001 From: VESSILLER Date: Tue, 28 Jan 2020 17:13:09 +0100 Subject: [PATCH 05/14] FIX regex for include or exclude categories in full arbo --- htdocs/categories/class/categorie.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index f31e8f9b048..6edb069ef6e 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -1080,7 +1080,7 @@ class Categorie extends CommonObject // Include or exclude leaf including $markafterid from tree if (count($markafterid) > 0) { - $keyfiltercatid = implode('|', $markafterid); + $keyfiltercatid = '(' . implode('|', $markafterid) . ')'; //print "Look to discard category ".$markafterid."\n"; $keyfilter1 = '^' . $keyfiltercatid . '$'; From 5783f9b7c2f7a83e6e04bfb5178174957b9b4790 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Tue, 28 Jan 2020 17:33:50 +0100 Subject: [PATCH 06/14] fix lang for other payment mode available --- htdocs/stripe/charge.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/stripe/charge.php b/htdocs/stripe/charge.php index 77bd1d918bf..d198555e421 100644 --- a/htdocs/stripe/charge.php +++ b/htdocs/stripe/charge.php @@ -139,6 +139,10 @@ if (!$rowid) $type = $langs->trans("card"); } elseif ($charge->payment_method_details->type=='three_d_secure'){ $type = $langs->trans("card3DS"); + } elseif ($charge->payment_method_details->type=='sepa_debit'){ + $type = $langs->trans("sepadebit"); + } elseif ($charge->payment_method_details->type=='ideal'){ + $type = $langs->trans("iDEAL"); } if (! empty($charge->payment_intent)) { From 9ae174d8b4fb16ffa4492b8718ebc556e2e79ec3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 28 Jan 2020 19:47:21 +0100 Subject: [PATCH 07/14] Clean code --- htdocs/api/class/api.class.php | 6 ++++++ htdocs/expensereport/class/api_expensereports.class.php | 3 +++ 2 files changed, 9 insertions(+) diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index f4c9076fbd9..26f83f36fd6 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -150,6 +150,12 @@ class DolibarrApi unset($object->context); unset($object->next_prev_filter); + unset($object->region); + unset($object->region_code); + + unset($object->libelle_statut); + unset($object->libelle_paiement); + if ($object->table_element != 'ticket') { unset($object->comments); } diff --git a/htdocs/expensereport/class/api_expensereports.class.php b/htdocs/expensereport/class/api_expensereports.class.php index 0e673ffdf30..60e5eafcb48 100644 --- a/htdocs/expensereport/class/api_expensereports.class.php +++ b/htdocs/expensereport/class/api_expensereports.class.php @@ -501,6 +501,9 @@ class ExpenseReports extends DolibarrApi // phpcs:enable $object = parent::_cleanObjectDatas($object); + unset($object->cond_reglement); + unset($object->shipping_method_id); + unset($object->barcode_type); unset($object->barcode_type_code); unset($object->barcode_type_label); From b2256620c40d4310c93ed3aec876c27fa1b74960 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 28 Jan 2020 20:36:28 +0100 Subject: [PATCH 08/14] Update emailcollector.class.php --- htdocs/emailcollector/class/emailcollector.class.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 514612c4b2b..e6968109bf7 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -2048,10 +2048,11 @@ class EmailCollector extends CommonObject /** * Converts a string from one encoding to another. - * @param string $string - * @param string $fromEncoding - * @param string $toEncoding - * @return string Converted string if conversion was successful, or the original string if not + * + * @param string $string String to convert + * @param string $fromEncoding String encoding + * @param string $toEncoding String return encoding + * @return string Converted string if conversion was successful, or the original string if not * @throws Exception */ protected function convertStringEncoding($string, $fromEncoding, $toEncoding = 'UTF-8') From d224c711cf3b9015af4131968e6be5bc00fa1ff1 Mon Sep 17 00:00:00 2001 From: oscim Date: Wed, 29 Jan 2020 08:08:15 +0100 Subject: [PATCH 09/14] Update result.php fix error for display detail of account 6xxx. this account is < 0, but is not null --- htdocs/compta/resultat/result.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/resultat/result.php b/htdocs/compta/resultat/result.php index 6e91ef53e2b..97b04158e34 100644 --- a/htdocs/compta/resultat/result.php +++ b/htdocs/compta/resultat/result.php @@ -505,7 +505,7 @@ elseif ($modecompta=="BOOKKEEPING") $resultNP = $totPerAccount[$cpt['account_number']]['NP']; $resultN = $totPerAccount[$cpt['account_number']]['N']; - if ($showaccountdetail == 'all' || $resultN > 0) { + if ($showaccountdetail == 'all' || $resultN != 0) { print ''; print ''; print ''; From 5d2130a5aec3ae306d3f323c977b656fa20c18ca Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 29 Jan 2020 11:38:06 +0100 Subject: [PATCH 10/14] Fix SQL injection --- htdocs/resource/class/dolresource.class.php | 6 +++--- htdocs/resource/list.php | 14 ++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/htdocs/resource/class/dolresource.class.php b/htdocs/resource/class/dolresource.class.php index 13cbf37c34a..9abbf297370 100644 --- a/htdocs/resource/class/dolresource.class.php +++ b/htdocs/resource/class/dolresource.class.php @@ -533,7 +533,7 @@ class Dolresource extends CommonObject $sql.= $value; } else { - $sql.= ' AND '.$key.' LIKE \'%'.$value.'%\''; + $sql.= ' AND '.$key.' LIKE \'%'.$this->db->escape($value).'%\''; } } } @@ -617,7 +617,7 @@ class Dolresource extends CommonObject $sql.= ' AND '.$key.' = \''.$this->db->idate($value).'\''; } else { - $sql.= ' AND '.$key.' LIKE \'%'.$value.'%\''; + $sql.= ' AND '.$key.' LIKE \'%'.$this->db->escape($value).'%\''; } } } @@ -699,7 +699,7 @@ class Dolresource extends CommonObject $sql.= ' AND '.$key.' = \''.$this->db->idate($value).'\''; } else { - $sql.= ' AND '.$key.' LIKE \'%'.$value.'%\''; + $sql.= ' AND '.$key.' LIKE \'%'.$this->db->escape($value).'%\''; } } } diff --git a/htdocs/resource/list.php b/htdocs/resource/list.php index d9547ad441b..7490bd42a51 100644 --- a/htdocs/resource/list.php +++ b/htdocs/resource/list.php @@ -18,7 +18,7 @@ */ /** - * \file resource/index.php + * \file resource/list.php * \ingroup resource * \brief Page to manage resource objects */ @@ -52,20 +52,19 @@ $extrafields = new ExtraFields($db); $extralabels=$extrafields->fetch_name_optionals_label($object->table_element); $search_array_options=$extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); if (! is_array($search_array_options)) $search_array_options = array(); -$search_ref=GETPOST("search_ref"); -$search_type=GETPOST("search_type"); +$search_ref = GETPOST("search_ref", 'alpha'); +$search_type = GETPOST("search_type", 'alpha'); $filter=array(); if ($search_ref != ''){ - $param.='&search_ref='.$search_ref; + $param.='&search_ref='.urlencode($search_ref); $filter['t.ref']=$search_ref; } if ($search_type != ''){ - $param.='&search_type='.$search_type; + $param.='&search_type='.urlencode($search_type); $filter['ty.label']=$search_type; } -if ($search_label != '') $param.='&search_label='.$search_label; // Add $param from extra fields foreach ($search_array_options as $key => $val) { @@ -83,7 +82,7 @@ foreach ($search_array_options as $key => $val) $filter['ef.'.$tmpkey] = natural_search('ef.'.$tmpkey, $crit, $mode_search); } } -if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; +if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage); $hookmanager->initHooks(array('resourcelist')); @@ -133,7 +132,6 @@ include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // Both test are required to be compatible with all browsers { $search_ref=""; - $search_label=""; $search_type=""; $search_array_options=array(); $filter=array(); From 7c34d97e2d2461c5e438782ac8436a6a5f03c5f0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 29 Jan 2020 13:10:16 +0100 Subject: [PATCH 11/14] Fix messages for SPF --- htdocs/admin/mails.php | 26 ++++++++++++++++++++++---- htdocs/langs/en_US/admin.lang | 1 + 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 2e03eed937c..82da31bdeca 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -758,13 +758,31 @@ else $text = ''; if ($conf->global->MAIN_MAIL_SENDMODE == 'mail') { - $text .= $langs->trans("WarningPHPMail"); + $text .= $langs->trans("WarningPHPMail"); // To encourage to use SMTPS } - //$conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS='1.2.3.4'; - if (!empty($conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS)) + + if ($conf->global->MAIN_MAIL_SENDMODE == 'mail') { - $text .= ($text ? '
' : '').$langs->trans("WarningPHPMail2", $conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS); + // MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS is list of IPs where email is sent from. Example: '1.2.3.4, [aaaa:bbbb:cccc:dddd]'. + if (!empty($conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS)) + { + // List of IP show as record to add in SPF if we use the mail method + $text .= ($text ? '

' : '').$langs->trans("WarningPHPMailSPF", $conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS); + } + } else { + if (!empty($conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS)) + { + // List of IP show as record to add as allowed IP if we use the smtp method + $text .= ($text ? '

' : '').$langs->trans("WarningPHPMail2", $conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS); + } + if (!empty($conf->global->MAIN_EXTERNAL_SMTP_SPF_STRING_TO_ADD)) + { + // List of string to add in SPF if we use the smtp method + $text .= ($text ? '

' : '').$langs->trans("WarningPHPMailSPF", $conf->global->MAIN_EXTERNAL_SMTP_SPF_STRING_TO_ADD); + } } + + if ($text) print info_admin($text); } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 3c351467284..7bea668e091 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -472,6 +472,7 @@ Use3StepsApproval=By default, Purchase Orders need to be created and approved by UseDoubleApproval=Use a 3 steps approval when amount (without tax) is higher than... WarningPHPMail=WARNING: It is often better to setup outgoing emails to use the email server of your provider instead of the default setup. Some email providers (like Yahoo) do not allow you to send an email from another server than their own server. Your current setup uses the server of the application to send email and not the server of your email provider, so some recipients (the one compatible with the restrictive DMARC protocol), will ask your email provider if they can accept your email and some email providers (like Yahoo) may respond "no" because the server is not theirs, so few of your sent Emails may not be accepted (be careful also of your email provider's sending quota).
If your Email provider (like Yahoo) has this restriction, you must change Email setup to choose the other method "SMTP server" and enter the SMTP server and credentials provided by your Email provider. WarningPHPMail2=If your email SMTP provider need to restrict email client to some IP addresses (very rare), this is the IP address of the mail user agent (MUA) for your ERP CRM application: %s. +WarningPHPMailSPF=If the domain name in your sender email address is protected by SPF (ask you email provider), you must include the following IPs in the SPF record of the DNS of your domain: %s. ClickToShowDescription=Click to show description DependsOn=This module needs the module(s) RequiredBy=This module is required by module(s) From 65e8113373231788d4df0e954d33d988a049357a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 29 Jan 2020 14:23:44 +0100 Subject: [PATCH 12/14] Look and feel v11 --- htdocs/admin/notification.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/admin/notification.php b/htdocs/admin/notification.php index 1eddaef9903..fb5ff1df202 100644 --- a/htdocs/admin/notification.php +++ b/htdocs/admin/notification.php @@ -113,10 +113,12 @@ llxHeader('', $langs->trans("NotificationSetup")); $linkback = ''.$langs->trans("BackToModuleList").''; print load_fiche_titre($langs->trans("NotificationSetup"), $linkback, 'title_setup'); +print ''; print $langs->trans("NotificationsDesc").'
'; print $langs->trans("NotificationsDescUser").'
'; if (!empty($conf->societe->enabled)) print $langs->trans("NotificationsDescContact").'
'; print $langs->trans("NotificationsDescGlobal").'
'; +print '
'; print '
'; print '
'; From 60f772d28562f73d55d4ccba6f38d65fa0d9ccd6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 29 Jan 2020 17:27:31 +0100 Subject: [PATCH 13/14] FIX Pending amount to pay must be zero if invoice close for anticipated payment. --- htdocs/compta/facture/list.php | 16 ++++++++++++---- htdocs/core/class/commoninvoice.class.php | 7 ++++++- htdocs/core/modules/modFacture.class.php | 21 +++++++++++++-------- htdocs/exports/class/export.class.php | 1 + htdocs/exports/export.php | 2 +- htdocs/langs/en_US/bills.lang | 2 ++ 6 files changed, 35 insertions(+), 14 deletions(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 00aa9deb4df..db1ba28c14e 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -387,7 +387,7 @@ if ($sall || $search_product_category > 0) $sql = 'SELECT DISTINCT'; $sql .= ' f.rowid as id, f.ref, f.ref_client, f.type, f.note_private, f.note_public, f.increment, f.fk_mode_reglement, f.fk_cond_reglement, f.total as total_ht, f.tva as total_vat, f.total_ttc,'; $sql .= ' f.localtax1 as total_localtax1, f.localtax2 as total_localtax2,'; $sql .= ' f.datef as df, f.date_lim_reglement as datelimite, f.module_source, f.pos_source,'; -$sql .= ' f.paye as paye, f.fk_statut,'; +$sql .= ' f.paye as paye, f.fk_statut, f.close_code,'; $sql .= ' f.datec as date_creation, f.tms as date_update, f.date_closing as date_closing,'; $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; $sql .= ' s.rowid as socid, s.nom as name, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,'; @@ -502,7 +502,7 @@ if (!$sall) $sql .= ' GROUP BY f.rowid, f.ref, ref_client, f.type, f.note_private, f.note_public, f.increment, f.fk_mode_reglement, f.fk_cond_reglement, f.total, f.tva, f.total_ttc,'; $sql .= ' f.localtax1, f.localtax2,'; $sql .= ' f.datef, f.date_lim_reglement, f.module_source, f.pos_source,'; - $sql .= ' f.paye, f.fk_statut,'; + $sql .= ' f.paye, f.fk_statut, f.close_code,'; $sql .= ' f.datec, f.tms, f.date_closing,'; $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; $sql .= ' s.rowid, s.nom, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; @@ -987,6 +987,7 @@ if ($resql) $facturestatic->total_tva = $obj->total_vat; $facturestatic->total_ttc = $obj->total_ttc; $facturestatic->statut = $obj->fk_statut; + $facturestatic->close_code = $obj->close_code; $facturestatic->total_ttc = $obj->total_ttc; $facturestatic->paye = $obj->paye; $facturestatic->fk_soc = $obj->fk_soc; @@ -1022,7 +1023,11 @@ if ($resql) $totaldeposits = $facturestatic->getSumDepositsUsed(); $totalpay = $paiement + $totalcreditnotes + $totaldeposits; $remaintopay = price2num($facturestatic->total_ttc - $totalpay); - if ($facturestatic->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1) { + + if ($facturestatic->statut == Facture::STATUS_CLOSED && $facturestatic->close_code == 'discount_vat') { // If invoice closed with discount for anticipated payment + $remaintopay = 0; + } + if ($facturestatic->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1) { // If credit note closed, we take into account the amount not yet consummed $remaincreditnote = $discount->getAvailableDiscounts($obj->fk_soc, '', 'rc.fk_facture_source='.$facturestatic->id); $remaintopay = -$remaincreditnote; $totalpay = price2num($facturestatic->total_ttc - $remaintopay); @@ -1281,9 +1286,12 @@ if ($resql) $totalarray['val']['totalam'] += $totalpay; } + // Pending amount if (!empty($arrayfields['rtp']['checked'])) { - print ''.(!empty($remaintopay) ?price($remaintopay, 0, $langs) : ' ').''; // TODO Use a denormalized field + print ''; + print (!empty($remaintopay) ? price($remaintopay, 0, $langs) : ' '); + print ''; // TODO Use a denormalized field if (!$i) $totalarray['nbfield']++; if (!$i) $totalarray['pos'][$totalarray['nbfield']] = 'rtp'; $totalarray['val']['rtp'] += $remaintopay; diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index eb2e55d6279..80afcfacecc 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -103,7 +103,12 @@ abstract class CommonInvoice extends CommonObject $alreadypaid+=$this->getSommePaiement($multicurrency); $alreadypaid+=$this->getSumDepositsUsed($multicurrency); $alreadypaid+=$this->getSumCreditNotesUsed($multicurrency); - return $this->total_ttc - $alreadypaid; + + $remaintopay = ($this->total_ttc - $alreadypaid); + if ($this->statut == self::STATUS_CLOSED && $this->close_code == 'discount_vat') { // If invoice closed with discount for anticipated payment + $remaintopay = 0; + } + return $remaintopay; } /** diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index b0f7dd94ae8..984e28f4e31 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -216,7 +216,8 @@ class modFacture extends DolibarrModules 's.code_compta_fournisseur'=>'SupplierAccountancyCode', 's.tva_intra'=>'VATIntra', 'f.rowid'=>"InvoiceId", 'f.ref'=>"InvoiceRef", 'f.ref_client'=>'RefCustomer', 'f.type'=>"Type", 'f.datec'=>"InvoiceDateCreation", 'f.datef'=>"DateInvoice", 'f.date_lim_reglement'=>"DateDue", 'f.total'=>"TotalHT", - 'f.total_ttc'=>"TotalTTC", 'f.tva'=>"TotalVAT", 'f.localtax1'=>'LocalTax1', 'f.localtax2'=>'LocalTax2', 'none.rest'=>'Rest', 'f.paye'=>"InvoicePaidCompletely", 'f.fk_statut'=>'InvoiceStatus', + 'f.total_ttc'=>"TotalTTC", 'f.tva'=>"TotalVAT", 'f.localtax1'=>'LocalTax1', 'f.localtax2'=>'LocalTax2', 'f.paye'=>"InvoicePaidCompletely", 'f.fk_statut'=>'InvoiceStatus', 'f.close_code'=>'EarlyClosingReason', 'f.close_note'=>'EarlyClosingComment', + 'none.rest'=>'Rest', 'f.note_private'=>"NotePrivate", 'f.note_public'=>"NotePublic", 'f.fk_user_author'=>'CreatedById', 'uc.login'=>'CreatedByLogin', 'f.fk_user_valid'=>'ValidatedById', 'uv.login'=>'ValidatedByLogin', 'pj.ref'=>'ProjectRef', 'pj.title'=>'ProjectLabel', 'fd.rowid'=>'LineId', 'fd.description'=>"LineDescription", 'fd.subprice'=>"LineUnitPrice", 'fd.tva_tx'=>"LineVATRate", 'fd.qty'=>"LineQty", 'fd.total_ht'=>"LineTotalHT", 'fd.total_tva'=>"LineTotalVAT", @@ -241,7 +242,8 @@ class modFacture extends DolibarrModules 's.rowid'=>'Numeric', 's.nom'=>'Text', 's.code_client'=>'Text', 's.address'=>'Text', 's.zip'=>'Text', 's.town'=>'Text', 'c.code'=>'Text', 'cd.nom'=>'Text', 's.phone'=>'Text', 's.siren'=>'Text', 's.siret'=>'Text', 's.ape'=>'Text', 's.idprof4'=>'Text', 's.code_compta'=>'Text', 's.code_compta_fournisseur'=>'Text', 's.tva_intra'=>'Text', 'f.rowid'=>'Numeric', 'f.ref'=>"Text", 'f.ref_client'=>'Text', 'f.type'=>"Numeric", 'f.datec'=>"Date", 'f.datef'=>"Date", 'f.date_lim_reglement'=>"Date", - 'f.total'=>"Numeric", 'f.total_ttc'=>"Numeric", 'f.tva'=>"Numeric", 'f.localtax1'=>'Numeric', 'f.localtax2'=>'Numeric', 'none.rest'=>"NumericCompute", 'f.paye'=>"Boolean", 'f.fk_statut'=>'Numeric', + 'f.total'=>"Numeric", 'f.total_ttc'=>"Numeric", 'f.tva'=>"Numeric", 'f.localtax1'=>'Numeric', 'f.localtax2'=>'Numeric', 'f.paye'=>"Boolean", 'f.fk_statut'=>'Numeric', 'f.close_code'=>'Text', 'f.close_note'=>'Text', + 'none.rest'=>"NumericCompute", 'f.note_private'=>"Text", 'f.note_public'=>"Text", 'f.fk_user_author'=>'Numeric', 'uc.login'=>'Text', 'f.fk_user_valid'=>'Numeric', 'uv.login'=>'Text', 'pj.ref'=>'Text', 'pj.title'=>'Text', 'fd.rowid'=>'Numeric', 'fd.label'=>'Text', 'fd.description'=>"Text", 'fd.subprice'=>"Numeric", 'fd.tva_tx'=>"Numeric", 'fd.qty'=>"Numeric", 'fd.total_ht'=>"Numeric", 'fd.total_tva'=>"Numeric", 'fd.total_ttc'=>"Numeric", 'fd.date_start'=>"Date", 'fd.date_end'=>"Date", @@ -263,7 +265,7 @@ class modFacture extends DolibarrModules 'f.fk_user_author'=>'user', 'uc.login'=>'user', 'f.fk_user_valid'=>'user', 'uv.login'=>'user' ); $this->export_special_array[$r] = array('none.rest'=>'getRemainToPay'); - $this->export_dependencies_array[$r] = array('invoice_line'=>'fd.rowid', 'product'=>'fd.rowid', 'none.rest'=>array('f.rowid', 'f.total_ttc')); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them + $this->export_dependencies_array[$r] = array('invoice_line'=>'fd.rowid', 'product'=>'fd.rowid', 'none.rest'=>array('f.rowid', 'f.total_ttc', 'f.close_code')); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them $keyforselect = 'facture'; $keyforelement = 'invoice'; $keyforaliasextra = 'extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; $keyforselect = 'facturedet'; $keyforelement = 'invoice_line'; $keyforaliasextra = 'extra2'; @@ -289,6 +291,7 @@ class modFacture extends DolibarrModules if (isset($user) && empty($user->rights->societe->client->voir)) $this->export_sql_end[$r] .= ' AND sc.fk_user = '.$user->id; $r++; + $this->export_code[$r] = $this->rights_class.'_'.$r; $this->export_label[$r] = 'CustomersInvoicesAndPayments'; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_icon[$r] = 'invoice'; @@ -300,7 +303,8 @@ class modFacture extends DolibarrModules 's.code_compta_fournisseur'=>'SupplierAccountancyCode', 's.tva_intra'=>'VATIntra', 'f.rowid'=>"InvoiceId", 'f.ref'=>"InvoiceRef", 'f.ref_client'=>'RefCustomer', 'f.type'=>"Type", 'f.datec'=>"InvoiceDateCreation", 'f.datef'=>"DateInvoice", 'f.date_lim_reglement'=>"DateDue", 'f.total'=>"TotalHT", - 'f.total_ttc'=>"TotalTTC", 'f.tva'=>"TotalVAT", 'f.localtax1'=>'LocalTax1', 'f.localtax2'=>'LocalTax2', 'none.rest'=>'Rest', 'f.paye'=>"InvoicePaidCompletely", 'f.fk_statut'=>'InvoiceStatus', + 'f.total_ttc'=>"TotalTTC", 'f.tva'=>"TotalVAT", 'f.localtax1'=>'LocalTax1', 'f.localtax2'=>'LocalTax2', 'f.paye'=>"InvoicePaidCompletely", 'f.fk_statut'=>'InvoiceStatus', 'f.close_code'=>'EarlyClosingReason', 'f.close_note'=>'EarlyClosingComment', + 'none.rest'=>'Rest', 'f.note_private'=>"NotePrivate", 'f.note_public'=>"NotePublic", 'f.fk_user_author'=>'CreatedById', 'uc.login'=>'CreatedByLogin', 'f.fk_user_valid'=>'ValidatedById', 'uv.login'=>'ValidatedByLogin', 'pj.ref'=>'ProjectRef', 'pj.title'=>'ProjectLabel', 'p.rowid'=>'PaymentId', 'p.ref'=>'PaymentRef', 'p.amount'=>'AmountPayment', 'pf.amount'=>'AmountPaymentDistributedOnInvoice', 'p.datep'=>'DatePayment', 'p.num_paiement'=>'PaymentNumber', @@ -325,9 +329,10 @@ class modFacture extends DolibarrModules 's.rowid'=>'Numeric', 's.nom'=>'Text', 's.code_client'=>'Text', 's.address'=>'Text', 's.zip'=>'Text', 's.town'=>'Text', 'c.code'=>'Text', 'cd.nom'=>'Text', 's.phone'=>'Text', 's.siren'=>'Text', 's.siret'=>'Text', 's.ape'=>'Text', 's.idprof4'=>'Text', 's.code_compta'=>'Text', 's.code_compta_fournisseur'=>'Text', 's.tva_intra'=>'Text', 'f.rowid'=>"Numeric", 'f.ref'=>"Text", 'f.ref_client'=>'Text', 'f.type'=>"Numeric", 'f.datec'=>"Date", 'f.datef'=>"Date", 'f.date_lim_reglement'=>"Date", - 'f.total'=>"Numeric", 'f.total_ttc'=>"Numeric", 'f.tva'=>"Numeric", 'f.localtax1'=>'Numeric', 'f.localtax2'=>'Numeric', 'none.rest'=>'NumericCompute', 'f.paye'=>"Boolean", 'f.fk_statut'=>'Status', + 'f.total'=>"Numeric", 'f.total_ttc'=>"Numeric", 'f.tva'=>"Numeric", 'f.localtax1'=>'Numeric', 'f.localtax2'=>'Numeric', 'f.paye'=>"Boolean", 'f.fk_statut'=>'Status', 'f.close_code'=>'Text', 'f.close_note'=>'Text', + 'none.rest'=>'NumericCompute', 'f.note_private'=>"Text", 'f.note_public'=>"Text", 'f.fk_user_author'=>'Numeric', 'uc.login'=>'Text', 'f.fk_user_valid'=>'Numeric', 'uv.login'=>'Text', - 'pj.ref'=>'Text', 'p.amount'=>'Numeric', 'pf.amount'=>'Numeric', 'p.rowid'=>'Numeric', 'p.ref'=>'Text', 'p.title'=>'Text', 'p.datep'=>'Date', 'p.num_paiement'=>'Numeric', + 'pj.ref'=>'Text', 'pj.title'=>'Text', 'p.amount'=>'Numeric', 'pf.amount'=>'Numeric', 'p.rowid'=>'Numeric', 'p.ref'=>'Text', 'p.title'=>'Text', 'p.datep'=>'Date', 'p.num_paiement'=>'Numeric', 'p.fk_bank'=>'Numeric', 'p.note'=>'Text', 'pt.code'=>'Text', 'pt.libelle'=>'text', 'ba.ref'=>'Text' ); if (! empty($conf->cashdesk->enabled) || ! empty($conf->takepos->enabled) || ! empty($conf->global->INVOICE_SHOW_POS)) @@ -338,12 +343,12 @@ class modFacture extends DolibarrModules $this->export_entities_array[$r] = array( 's.rowid'=>"company", 's.nom'=>'company', 's.code_client'=>'company', 's.address'=>'company', 's.zip'=>'company', 's.town'=>'company', 'c.code'=>'company', 'cd.nom'=>'company', 's.phone'=>'company', 's.siren'=>'company', 's.siret'=>'company', 's.ape'=>'company', 's.idprof4'=>'company', 's.code_compta'=>'company', 's.code_compta_fournisseur'=>'company', - 's.tva_intra'=>'company', 'pj.ref'=>'project', 'p.title'=>'project', 'p.rowid'=>'payment', 'p.ref'=>'payment', 'p.amount'=>'payment', 'pf.amount'=>'payment', 'p.datep'=>'payment', + 's.tva_intra'=>'company', 'pj.ref'=>'project', 'pj.title'=>'project', 'p.rowid'=>'payment', 'p.ref'=>'payment', 'p.amount'=>'payment', 'pf.amount'=>'payment', 'p.datep'=>'payment', 'p.num_paiement'=>'payment', 'pt.code'=>'payment', 'pt.libelle'=>'payment', 'p.note'=>'payment', 'f.fk_user_author'=>'user', 'uc.login'=>'user', 'f.fk_user_valid'=>'user', 'uv.login'=>'user', 'p.fk_bank'=>'account', 'ba.ref'=>'account' ); $this->export_special_array[$r] = array('none.rest'=>'getRemainToPay'); - $this->export_dependencies_array[$r] = array('payment'=>'p.rowid', 'none.rest'=>array('f.rowid', 'f.total_ttc')); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them + $this->export_dependencies_array[$r] = array('payment'=>'p.rowid', 'none.rest'=>array('f.rowid', 'f.total_ttc', 'f.close_code')); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them, or just to have field we need $keyforselect = 'facture'; $keyforelement = 'invoice'; $keyforaliasextra = 'extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; $this->export_sql_start[$r]='SELECT DISTINCT '; diff --git a/htdocs/exports/class/export.class.php b/htdocs/exports/class/export.class.php index 06813b03ae5..b43fddad60d 100644 --- a/htdocs/exports/class/export.class.php +++ b/htdocs/exports/class/export.class.php @@ -660,6 +660,7 @@ class Export } $tmpobjforcomputecall->id = $obj->f_rowid; $tmpobjforcomputecall->total_ttc = $obj->f_total_ttc; + $tmpobjforcomputecall->close_code = $obj->f_close_code; $remaintopay=$tmpobjforcomputecall->getRemainToPay(); } $obj->$alias=$remaintopay; diff --git a/htdocs/exports/export.php b/htdocs/exports/export.php index ffbed97a75c..525a5b17c9e 100644 --- a/htdocs/exports/export.php +++ b/htdocs/exports/export.php @@ -1186,7 +1186,7 @@ if ($step == 5 && $datatoexport) print $objexport->array_export_module[0]->getName(); print ''; - // Lot de donnees a exporter + // Dataset to export print ''.$langs->trans("DatasetToExport").''; print ''; $icon = preg_replace('/:.*$/', '', $objexport->array_export_icon[0]); diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 83ebdece24b..6e26ecb6835 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -519,6 +519,8 @@ TerreNumRefModelDesc1=Return number with format %syymm-nnnn for standard invoice MarsNumRefModelDesc1=Return number with format %syymm-nnnn for standard invoices, %syymm-nnnn for replacement invoices, %syymm-nnnn for down payment invoices and %syymm-nnnn for credit notes where yy is year, mm is month and nnnn is a sequence with no break and no return to 0 TerreNumRefModelError=A bill starting with $syymm already exists and is not compatible with this model of sequence. Remove it or rename it to activate this module. CactusNumRefModelDesc1=Return number with format %syymm-nnnn for standard invoices, %syymm-nnnn for credit notes and %syymm-nnnn for down payment invoices where yy is year, mm is month and nnnn is a sequence with no break and no return to 0 +EarlyClosingReason=Early closing reason +EarlyClosingComment=Early closing note ##### Types de contacts ##### TypeContact_facture_internal_SALESREPFOLL=Representative following-up customer invoice TypeContact_facture_external_BILLING=Customer invoice contact From 633ba666aa5e1f9dbde4868bffc4f7c0820624ad Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 29 Jan 2020 19:26:04 +0100 Subject: [PATCH 14/14] Add info of email reference syntax to help debug. --- htdocs/admin/mails.php | 7 +++++++ htdocs/langs/en_US/admin.lang | 1 + 2 files changed, 8 insertions(+) diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index 82da31bdeca..165f5f9c7f1 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -858,6 +858,13 @@ else print $formmail->get_form('addfile', 'removefile'); dol_fiche_end(); + + // References + print ''.$langs->trans("EMailsWillHaveMessageID").': '; + print dol_escape_htmltag(''); + print ''; + + } } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 7bea668e091..5cac95078c0 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1971,3 +1971,4 @@ NotAPublicIp=Not a public IP MakeAnonymousPing=Make an anonymous Ping '+1' to the Dolibarr foundation server (done 1 time only after installation) to allow the foundation to count the number of Dolibarr installation. FeatureNotAvailableWithReceptionModule=Feature not available when module Reception is enabled EmailTemplate=Template for email +EMailsWillHaveMessageID=Emails will have a tag 'References' matching this syntax \ No newline at end of file