From 7ada0de6549ff6d110c72626da33179c59742961 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Tue, 26 May 2020 21:27:46 +0200 Subject: [PATCH 01/79] FIX : #13968 --- htdocs/societe/class/societe.class.php | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 9cc36dbb7b4..cffae4011c0 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -105,6 +105,13 @@ class Societe extends CommonObject "actioncomm", ); + /** + * Build as [parentChildTable]=>[childTable]=>array(parentChildTable.PrimaryKey,childTable.ForeignKey,WhereClause) + * Define into Contrcutor because of MAIN_DB_PREFIX cannot be use here + * @var array List of Parent's child's child tables. To know object to delete on cascade. + */ + protected $parentchildchildtablesoncascade = array(); + /** * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png */ @@ -653,6 +660,22 @@ class Societe extends CommonObject $this->forme_juridique_code = 0; $this->tva_assuj = 1; $this->status = 1; + + $this->parentchildchildtablesoncascade = array( + 'socpeople'=> + array( + MAIN_DB_PREFIX.'socpeople_extrafields' => + array(MAIN_DB_PREFIX.'socpeople.rowid',MAIN_DB_PREFIX.'socpeople_extrafields.fk_object',''), + MAIN_DB_PREFIX.'element_contact' => + array(MAIN_DB_PREFIX.'socpeople.rowid', + MAIN_DB_PREFIX.'element_contact.fk_socpeople', + MAIN_DB_PREFIX.'element_contact.fk_c_type_contact IN (SELECT ct.rowid FROM '.MAIN_DB_PREFIX.'c_type_contact as ct WHERE ct.source=\'external\')'), + MAIN_DB_PREFIX.'societe_contacts' => + array(MAIN_DB_PREFIX.'socpeople.rowid', + MAIN_DB_PREFIX.'societe_contacts.fk_socpeople', + MAIN_DB_PREFIX.'societe_contacts.fk_c_type_contact IN (SELECT ct.rowid FROM '.MAIN_DB_PREFIX.'c_type_contact as ct WHERE ct.source=\'external\')'), + ) + ); } @@ -1673,6 +1696,22 @@ class Societe extends CommonObject foreach ($this->childtablesoncascade as $tabletodelete) { + if (!$error && array_key_exists($tabletodelete, $this->parentchildchildtablesoncascade)) + { + if (count($this->parentchildchildtablesoncascade[$tabletodelete])>0){ + foreach($this->parentchildchildtablesoncascade[$tabletodelete] as $childtabletodelete=>$dataToDelette) { + $sql = "DELETE FROM ". $childtabletodelete; + $sql .= " WHERE ".$dataToDelette[1]." IN (SELECT ".$dataToDelette[0]." FROM ".MAIN_DB_PREFIX.$tabletodelete." WHERE fk_soc = " . $id.")"; + if (!empty($dataToDelette[3])) { + $sql .= " AND ".$dataToDelette[3]; + } + if (!$this->db->query($sql)) { + $error++; + $this->errors[] = $this->db->lasterror(); + } + } + } + } if (!$error) { $sql = "DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete; @@ -1683,6 +1722,7 @@ class Societe extends CommonObject $this->errors[] = $this->db->lasterror(); } } + } // Removed extrafields From e5edc06f3d3379c90947ff2664e6d90fa5a4fc5d Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Tue, 26 May 2020 21:29:47 +0200 Subject: [PATCH 02/79] spelling --- htdocs/societe/class/societe.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index cffae4011c0..f1a32f1ff2f 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -107,7 +107,7 @@ class Societe extends CommonObject /** * Build as [parentChildTable]=>[childTable]=>array(parentChildTable.PrimaryKey,childTable.ForeignKey,WhereClause) - * Define into Contrcutor because of MAIN_DB_PREFIX cannot be use here + * Define into Contructor because of MAIN_DB_PREFIX cannot be use here * @var array List of Parent's child's child tables. To know object to delete on cascade. */ protected $parentchildchildtablesoncascade = array(); From ceb0a5b0b5910ded71384bc34663a6cc4f256980 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Tue, 26 May 2020 21:32:18 +0200 Subject: [PATCH 03/79] space --- htdocs/societe/class/societe.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index f1a32f1ff2f..abf818f2fe0 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1722,7 +1722,6 @@ class Societe extends CommonObject $this->errors[] = $this->db->lasterror(); } } - } // Removed extrafields From 2337d75d92e60ca74f05e096bffce7295fbd9f4f Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 1 Jun 2020 10:43:57 +0200 Subject: [PATCH 04/79] better fix for #13968 --- htdocs/contact/class/contact.class.php | 63 ++++++++++++++++++-- htdocs/core/class/commonobject.class.php | 35 +++++++++--- htdocs/societe/class/societe.class.php | 73 +++++++++--------------- 3 files changed, 110 insertions(+), 61 deletions(-) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 8a1b26e9d33..e200a309378 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1081,7 +1081,7 @@ class Contact extends CommonObject $sql .= " WHERE ec.fk_socpeople=".$this->id; $sql .= " AND ec.fk_c_type_contact=tc.rowid"; $sql .= " AND tc.source='external'"; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { @@ -1094,7 +1094,7 @@ class Contact extends CommonObject $sqldel = "DELETE FROM ".MAIN_DB_PREFIX."element_contact"; $sqldel .= " WHERE rowid = ".$obj->rowid; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $result = $this->db->query($sqldel); if (!$result) { @@ -1116,7 +1116,7 @@ class Contact extends CommonObject { // Remove Roles $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_contacts WHERE fk_socpeople = ".$this->id; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { @@ -1130,7 +1130,7 @@ class Contact extends CommonObject { // Remove category $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_contact WHERE fk_socpeople = ".$this->id; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { @@ -1144,7 +1144,7 @@ class Contact extends CommonObject { $sql = "DELETE FROM ".MAIN_DB_PREFIX."socpeople"; $sql .= " WHERE rowid=".$this->id; - dol_syslog(get_class($this)."::delete", LOG_DEBUG); + dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); $result = $this->db->query($sql); if (!$result) { @@ -1731,4 +1731,57 @@ class Contact extends CommonObject return $error * -1; } } + + /** + * Delete all contact from a thirdparty + * @param int $socId Thirdparty Id + * @param int $notrigger Disable all trigger + * @return int <0 if KO, >0 if OK + * @throws Exception + */ + public function deleteBySoc($socId = 0, $notrigger = 0) + { + $error = 0; + $deleted = 0; + + if (!empty($socId)) { + $this->db->begin(); + + $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql .= " WHERE fk_soc = " . $socId; + dol_syslog(__METHOD__, LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $this->db->lasterror() . ' sql=' . $sql; + $error++; + } else { + while ($obj = $this->db->fetch_object($resql)) { + $result = $this->fetch($obj->rowid); + if ($result < 0) { + $error++; + $this->errors = $this->error; + } else { + $result = $this->delete($notrigger); + if ($result < 0) { + $error++; + $this->errors = $this->error; + } else { + $deleted++; + } + } + } + } + + if (empty($error)) { + $this->db->commit(); + return $deleted; + } else { + $this->error = implode(' ', $this->errors); + $this->db->rollback(); + return $error * -1; + } + } + + return $deleted; + } } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 10e04896314..7fe7fc41303 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7891,15 +7891,32 @@ abstract class CommonObject if (!empty($this->childtablesoncascade)) { foreach ($this->childtablesoncascade as $table) { - $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$table.' WHERE '.$this->fk_element.' = '.$this->id; - $resql = $this->db->query($sql); - if (!$resql) - { - $this->error = $this->db->lasterror(); - $this->errors[] = $this->error; - $this->db->rollback(); - return -1; - } + $deleteFromObject=explode(':', $table); + if (count($deleteFromObject)>1) { + $className=str_replace('@', '', $deleteFromObject[0]); + $filePath=$deleteFromObject[1]; + $deleteMethod=$deleteFromObject[2]; + if (dol_include_once($filePath)) { + $childObject = new $className($this->db); + $result= $childObject->{$deleteMethod}($this->id); + if ($result<0) { + $this->errors[] = $childObject->error; + return -1; + } + } else { + $this->errors[] = 'Cannot find child class file ' .$filePath; + return -1; + } + } else { + $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $table . ' WHERE ' . $this->fk_element . ' = ' . $this->id; + $resql = $this->db->query($sql); + if (!$resql) { + $this->error = $this->db->lasterror(); + $this->errors[] = $this->error; + $this->db->rollback(); + return -1; + } + } } } diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index e51f8913e48..f5caa59e1f1 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -83,7 +83,8 @@ class Societe extends CommonObject ); /** - * @var array List of child tables. To know object to delete on cascade. + * @var array List of child tables. To know object to delete on cascade. + * if name like with @ClassNAme:FilePathClass:MethodDetele' it will call method to delete object rather tahn SQL delete */ protected $childtablesoncascade = array( "societe_prices", @@ -92,7 +93,7 @@ class Societe extends CommonObject "product_fournisseur_price", "product_customer_price_log", "product_customer_price", - "socpeople", + "@Contact:/contact/class/contact.class.php:deleteBySoc", "adherent", "societe_account", "societe_rib", @@ -105,13 +106,6 @@ class Societe extends CommonObject "actioncomm", ); - /** - * Build as [parentChildTable]=>[childTable]=>array(parentChildTable.PrimaryKey,childTable.ForeignKey,WhereClause) - * Define into Contructor because of MAIN_DB_PREFIX cannot be use here - * @var array List of Parent's child's child tables. To know object to delete on cascade. - */ - protected $parentchildchildtablesoncascade = array(); - /** * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png */ @@ -666,22 +660,6 @@ class Societe extends CommonObject $this->forme_juridique_code = 0; $this->tva_assuj = 1; $this->status = 1; - - $this->parentchildchildtablesoncascade = array( - 'socpeople'=> - array( - MAIN_DB_PREFIX.'socpeople_extrafields' => - array(MAIN_DB_PREFIX.'socpeople.rowid',MAIN_DB_PREFIX.'socpeople_extrafields.fk_object',''), - MAIN_DB_PREFIX.'element_contact' => - array(MAIN_DB_PREFIX.'socpeople.rowid', - MAIN_DB_PREFIX.'element_contact.fk_socpeople', - MAIN_DB_PREFIX.'element_contact.fk_c_type_contact IN (SELECT ct.rowid FROM '.MAIN_DB_PREFIX.'c_type_contact as ct WHERE ct.source=\'external\')'), - MAIN_DB_PREFIX.'societe_contacts' => - array(MAIN_DB_PREFIX.'socpeople.rowid', - MAIN_DB_PREFIX.'societe_contacts.fk_socpeople', - MAIN_DB_PREFIX.'societe_contacts.fk_c_type_contact IN (SELECT ct.rowid FROM '.MAIN_DB_PREFIX.'c_type_contact as ct WHERE ct.source=\'external\')'), - ) - ); } @@ -1702,30 +1680,31 @@ class Societe extends CommonObject foreach ($this->childtablesoncascade as $tabletodelete) { - if (!$error && array_key_exists($tabletodelete, $this->parentchildchildtablesoncascade)) - { - if (count($this->parentchildchildtablesoncascade[$tabletodelete])>0){ - foreach($this->parentchildchildtablesoncascade[$tabletodelete] as $childtabletodelete=>$dataToDelette) { - $sql = "DELETE FROM ". $childtabletodelete; - $sql .= " WHERE ".$dataToDelette[1]." IN (SELECT ".$dataToDelette[0]." FROM ".MAIN_DB_PREFIX.$tabletodelete." WHERE fk_soc = " . $id.")"; - if (!empty($dataToDelette[3])) { - $sql .= " AND ".$dataToDelette[3]; - } - if (!$this->db->query($sql)) { - $error++; - $this->errors[] = $this->db->lasterror(); - } - } - } - } if (!$error) { - $sql = "DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete; - $sql .= " WHERE fk_soc = ".$id; - if (!$this->db->query($sql)) - { - $error++; - $this->errors[] = $this->db->lasterror(); + $delete_from_object=explode(':', $tabletodelete); + if (count($delete_from_object)>1) { + $class_name=str_replace('@', '', $delete_from_object[0]); + $filepath=$delete_from_object[1]; + $delete_method=$delete_from_object[2]; + if (dol_include_once($filepath)) { + $child_object = new $class_name($this->db); + $result= $child_object->{$delete_method}($id); + if ($result<0) { + $error++; + $this->errors[] = $child_object->error; + } + } else { + $error++; + $this->errors[] = 'Cannot find child class file ' .$filepath; + } + } else { + $sql = "DELETE FROM " . MAIN_DB_PREFIX . $tabletodelete; + $sql .= " WHERE fk_soc = " . $id; + if (!$this->db->query($sql)) { + $error++; + $this->errors[] = $this->db->lasterror(); + } } } } From c655720b78d9eaa5b5f4aa1c63b1f03db4215052 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Mon, 1 Jun 2020 10:51:50 +0200 Subject: [PATCH 05/79] fix travis --- htdocs/contact/class/contact.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index e200a309378..71d816c166e 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1081,7 +1081,7 @@ class Contact extends CommonObject $sql .= " WHERE ec.fk_socpeople=".$this->id; $sql .= " AND ec.fk_c_type_contact=tc.rowid"; $sql .= " AND tc.source='external'"; - dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + dol_syslog(__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { @@ -1094,7 +1094,7 @@ class Contact extends CommonObject $sqldel = "DELETE FROM ".MAIN_DB_PREFIX."element_contact"; $sqldel .= " WHERE rowid = ".$obj->rowid; - dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + dol_syslog(__METHOD__, LOG_DEBUG); $result = $this->db->query($sqldel); if (!$result) { @@ -1116,7 +1116,7 @@ class Contact extends CommonObject { // Remove Roles $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_contacts WHERE fk_socpeople = ".$this->id; - dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + dol_syslog(__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { @@ -1130,7 +1130,7 @@ class Contact extends CommonObject { // Remove category $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_contact WHERE fk_socpeople = ".$this->id; - dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + dol_syslog(__METHOD__, LOG_DEBUG); $resql = $this->db->query($sql); if (!$resql) { @@ -1144,7 +1144,7 @@ class Contact extends CommonObject { $sql = "DELETE FROM ".MAIN_DB_PREFIX."socpeople"; $sql .= " WHERE rowid=".$this->id; - dol_syslog(get_class($this)."::".__METHOD__, LOG_DEBUG); + dol_syslog(__METHOD__, LOG_DEBUG); $result = $this->db->query($sql); if (!$result) { From da481049c1b93a05ff73928817206d0e3012db3c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 2 Jun 2020 15:45:40 +0200 Subject: [PATCH 06/79] Update commonobject.class.php --- htdocs/core/class/commonobject.class.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 7fe7fc41303..819b4b20839 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7898,11 +7898,13 @@ abstract class CommonObject $deleteMethod=$deleteFromObject[2]; if (dol_include_once($filePath)) { $childObject = new $className($this->db); - $result= $childObject->{$deleteMethod}($this->id); - if ($result<0) { - $this->errors[] = $childObject->error; - return -1; - } + if (method_exists($childObject, $deleteMethod)) { + $result= $childObject->{$deleteMethod}($this->id); + if ($result<0) { + $this->errors[] = $childObject->error; + return -1; + } + } } else { $this->errors[] = 'Cannot find child class file ' .$filePath; return -1; From 68bb552dcceb7570c9c23d4208c932eb67161970 Mon Sep 17 00:00:00 2001 From: gauthier Date: Tue, 2 Jun 2020 17:06:49 +0200 Subject: [PATCH 07/79] FIX : Tickets mail models doesn't work --- htdocs/admin/mails_templates.php | 1 + htdocs/core/class/html.formticket.class.php | 4 +--- htdocs/langs/en_US/admin.lang | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/mails_templates.php b/htdocs/admin/mails_templates.php index b5f22376c16..85cb5971652 100644 --- a/htdocs/admin/mails_templates.php +++ b/htdocs/admin/mails_templates.php @@ -166,6 +166,7 @@ if ($conf->societe->enabled) $elementList['thirdparty']=$langs->trans( if ($conf->adherent->enabled) $elementList['member']=$langs->trans('MailToMember'); if ($conf->contrat->enabled) $elementList['contract']=$langs->trans('MailToSendContract'); if ($conf->projet->enabled) $elementList['project']=$langs->trans('MailToProject'); +if ($conf->ticket->enabled) $elementList['ticket_send']=$langs->trans('MailToTicket'); $elementList['user']=$langs->trans('MailToUser'); $parameters=array('elementList'=>$elementList); diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 1e51d54f37e..72673abb323 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -991,9 +991,7 @@ class FormTicket // MESSAGE $defaultmessage=""; - if (is_array($arraydefaultmessage) && count($arraydefaultmessage) > 0 && $arraydefaultmessage->content) { - $defaultmessage=$arraydefaultmessage->content; - } + if ($arraydefaultmessage && $arraydefaultmessage->content) $defaultmessage = $arraydefaultmessage->content; $defaultmessage=str_replace('\n', "\n", $defaultmessage); // Deal with format differences between message and signature (text / HTML) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 64dac1f39e5..5378ef5729d 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1792,6 +1792,7 @@ MailToThirdparty=Third parties MailToMember=Members MailToUser=Users MailToProject=Projects page +MailToTicket=Tickets ByDefaultInList=Show by default on list view YouUseLastStableVersion=You use the latest stable version TitleExampleForMajorRelease=Example of message you can use to announce this major release (feel free to use it on your web sites) @@ -1923,4 +1924,4 @@ DeleteEmailCollector=Delete email collector ConfirmDeleteEmailCollector=Are you sure you want to delete this email collector? RecipientEmailsWillBeReplacedWithThisValue=Recipient emails will be always replaced with this value AtLeastOneDefaultBankAccountMandatory=At least 1 default bank account must be defined -FeatureNotAvailableWithReceptionModule=Feature not available when module Reception is enabled \ No newline at end of file +FeatureNotAvailableWithReceptionModule=Feature not available when module Reception is enabled From 9e5c7d0acf2c39788fdd90fd5dc8dce8d87cf12f Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Wed, 3 Jun 2020 23:00:53 +0200 Subject: [PATCH 08/79] FIX: Show ref_customer, amount on contract link object --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index ec7bfeab7c4..e25f3099ad1 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6671,7 +6671,7 @@ class Form 'order'=>array('enabled'=>$conf->commande->enabled, 'perms'=>1, 'label'=>'LinkToOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('commande').')'), 'invoice'=>array('enabled'=>$conf->facture->enabled, 'perms'=>1, 'label'=>'LinkToInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('invoice').')'), 'invoice_template'=>array('enabled'=>$conf->facture->enabled, 'perms'=>1, 'label'=>'LinkToTemplateInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.titre as ref, t.total as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture_rec as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('invoice').')'), - 'contrat'=>array('enabled'=>$conf->contrat->enabled , 'perms'=>1, 'label'=>'LinkToContract', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, '' as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('contract').')'), + 'contrat'=>array('enabled'=>$conf->contrat->enabled , 'perms'=>1, 'label'=>'LinkToContract', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_customer as ref_client, t.ref_supplier, td.total_ht as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as t, ".MAIN_DB_PREFIX."contratdet as td WHERE t.fk_soc = s.rowid AND td.fk_contrat = t.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('contract').')'), 'fichinter'=>array('enabled'=>$conf->ficheinter->enabled, 'perms'=>1, 'label'=>'LinkToIntervention', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."fichinter as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('intervention').')'), 'supplier_proposal'=>array('enabled'=>$conf->supplier_proposal->enabled , 'perms'=>1, 'label'=>'LinkToSupplierProposal', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('supplier_proposal').')'), 'order_supplier'=>array('enabled'=>$conf->supplier_order->enabled , 'perms'=>1, 'label'=>'LinkToSupplierOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('commande_fournisseur').')'), From e19f496d625ec917f9e7be91cce8a7af14f09c60 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Wed, 3 Jun 2020 23:30:06 +0200 Subject: [PATCH 09/79] Fix missing test on module enabled for user validators --- htdocs/user/card.php | 114 ++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/htdocs/user/card.php b/htdocs/user/card.php index 4bedd36fc3c..6e2d9b1cfdb 100644 --- a/htdocs/user/card.php +++ b/htdocs/user/card.php @@ -1631,32 +1631,36 @@ else print "\n"; // Expense report validator - print ''; - $text = $langs->trans("ForceUserExpenseValidator"); - print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); - print ''; - print ''; - if (!empty($object->fk_user_expense_validator)) { - $evuser = new User($db); - $evuser->fetch($object->fk_user_expense_validator); - print $evuser->getNomUrl(1); + if (!empty($conf->expensereport->enabled)) { + print ''; + $text = $langs->trans("ForceUserExpenseValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + print ''; + if (!empty($object->fk_user_expense_validator)) { + $evuser = new User($db); + $evuser->fetch($object->fk_user_expense_validator); + print $evuser->getNomUrl(1); + } + print ''; + print "\n"; } - print ''; - print "\n"; // Holiday request validator - print ''; - $text = $langs->trans("ForceUserHolidayValidator"); - print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); - print ''; - print ''; - if (!empty($object->fk_user_holiday_validator)) { - $hvuser = new User($db); - $hvuser->fetch($object->fk_user_holiday_validator); - print $hvuser->getNomUrl(1); + if (!empty($conf->holiday->enabled)) { + print ''; + $text = $langs->trans("ForceUserHolidayValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + print ''; + if (!empty($object->fk_user_holiday_validator)) { + $hvuser = new User($db); + $hvuser->fetch($object->fk_user_holiday_validator); + print $hvuser->getNomUrl(1); + } + print ''; + print "\n"; } - print ''; - print "\n"; // Default warehouse if (!empty($conf->stock->enabled) && !empty($conf->global->USER_DEFAULT_WAREHOUSE)) // TODO What is goal of this. How it is used ? @@ -2345,44 +2349,42 @@ else print "\n"; // Expense report validator - print ''; - $text = $langs->trans("ForceUserExpenseValidator"); - print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); - print ''; - print ''; - if ($caneditfield) - { - print $form->select_dolusers($object->fk_user_expense_validator, 'fk_user_expense_validator', 1, array($object->id), 0, '', 0, $object->entity, 0, 0, '', 0, '', 'maxwidth300'); + if (!empty($conf->expensereport->enabled)) { + print ''; + $text = $langs->trans("ForceUserExpenseValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + print ''; + if ($caneditfield) { + print $form->select_dolusers($object->fk_user_expense_validator, 'fk_user_expense_validator', 1, array($object->id), 0, '', 0, $object->entity, 0, 0, '', 0, '', 'maxwidth300'); + } else { + print ''; + $evuser = new User($db); + $evuser->fetch($object->fk_user_expense_validator); + print $evuser->getNomUrl(1); + } + print ''; + print "\n"; } - else - { - print ''; - $evuser = new User($db); - $evuser->fetch($object->fk_user_expense_validator); - print $evuser->getNomUrl(1); - } - print ''; - print "\n"; // Holiday request validator - print ''; - $text = $langs->trans("ForceUserHolidayValidator"); - print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); - print ''; - print ''; - if ($caneditfield) - { - print $form->select_dolusers($object->fk_user_holiday_validator, 'fk_user_holiday_validator', 1, array($object->id), 0, '', 0, $object->entity, 0, 0, '', 0, '', 'maxwidth300'); + if (!empty($conf->holiday->enabled)) { + print ''; + $text = $langs->trans("ForceUserHolidayValidator"); + print $form->textwithpicto($text, $langs->trans("ValidatorIsSupervisorByDefault"), 1, 'help'); + print ''; + print ''; + if ($caneditfield) { + print $form->select_dolusers($object->fk_user_holiday_validator, 'fk_user_holiday_validator', 1, array($object->id), 0, '', 0, $object->entity, 0, 0, '', 0, '', 'maxwidth300'); + } else { + print ''; + $hvuser = new User($db); + $hvuser->fetch($object->fk_user_holiday_validator); + print $hvuser->getNomUrl(1); + } + print ''; + print "\n"; } - else - { - print ''; - $hvuser = new User($db); - $hvuser->fetch($object->fk_user_holiday_validator); - print $hvuser->getNomUrl(1); - } - print ''; - print "\n"; print '
'; From f6e0ed08e2bedf6bebdd50f83f0fa63c043a0289 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Thu, 4 Jun 2020 00:30:17 +0200 Subject: [PATCH 10/79] Fix #14027 : emptying social network value on contact wasn't working --- htdocs/contact/card.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index e7fb6469869..f0f65071207 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -403,6 +403,7 @@ if (empty($reshook)) //$object->twitter = GETPOST("twitter", 'alpha'); //$object->facebook = GETPOST("facebook", 'alpha'); //$object->linkedin = GETPOST("linkedin", 'alpha'); + $object->socialnetworks = array(); if (!empty($conf->socialnetworks->enabled)) { foreach ($socialnetworks as $key => $value) { if (GETPOSTISSET($key) && GETPOST($key, 'alphanohtml') != '') { From ede084a1117c0aca753db35da0ec505cc346ba25 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 4 Jun 2020 05:11:00 +0200 Subject: [PATCH 11/79] Fix stickler --- htdocs/core/class/html.form.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index e25f3099ad1..627e5ee8a2b 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6671,7 +6671,8 @@ class Form 'order'=>array('enabled'=>$conf->commande->enabled, 'perms'=>1, 'label'=>'LinkToOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('commande').')'), 'invoice'=>array('enabled'=>$conf->facture->enabled, 'perms'=>1, 'label'=>'LinkToInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('invoice').')'), 'invoice_template'=>array('enabled'=>$conf->facture->enabled, 'perms'=>1, 'label'=>'LinkToTemplateInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.titre as ref, t.total as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture_rec as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('invoice').')'), - 'contrat'=>array('enabled'=>$conf->contrat->enabled , 'perms'=>1, 'label'=>'LinkToContract', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_customer as ref_client, t.ref_supplier, td.total_ht as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as t, ".MAIN_DB_PREFIX."contratdet as td WHERE t.fk_soc = s.rowid AND td.fk_contrat = t.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('contract').')'), + 'contrat'=>array('enabled'=>$conf->contrat->enabled , 'perms'=>1, 'label'=>'LinkToContract', + 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_customer as ref_client, t.ref_supplier, td.total_ht as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as t, ".MAIN_DB_PREFIX."contratdet as td WHERE t.fk_soc = s.rowid AND td.fk_contrat = t.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('contract').')'), 'fichinter'=>array('enabled'=>$conf->ficheinter->enabled, 'perms'=>1, 'label'=>'LinkToIntervention', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."fichinter as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('intervention').')'), 'supplier_proposal'=>array('enabled'=>$conf->supplier_proposal->enabled , 'perms'=>1, 'label'=>'LinkToSupplierProposal', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('supplier_proposal').')'), 'order_supplier'=>array('enabled'=>$conf->supplier_order->enabled , 'perms'=>1, 'label'=>'LinkToSupplierOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('commande_fournisseur').')'), From c393f8149c27a437d7c963d9a5d140a024556a8f Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Thu, 4 Jun 2020 11:29:51 +0200 Subject: [PATCH 12/79] FIX: when creating a VariousPayment, the value date is not copied onto the AccountLine that gets created at the same time, so the bank transaction's value date will be the payment date instead of the payment's value date --- htdocs/compta/bank/class/paymentvarious.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/bank/class/paymentvarious.class.php b/htdocs/compta/bank/class/paymentvarious.class.php index aea51e1a544..9a98ed3fc73 100644 --- a/htdocs/compta/bank/class/paymentvarious.class.php +++ b/htdocs/compta/bank/class/paymentvarious.class.php @@ -422,7 +422,11 @@ class PaymentVarious extends CommonObject $sign * abs($this->amount), $this->num_payment, ($this->category_transaction > 0 ? $this->category_transaction : 0), - $user + $user, + '', + '', + '', + $this->datev ); // Update fk_bank into llx_paiement. From c7a614bd5032034e8b5315af0cf32e033af19389 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 4 Jun 2020 17:07:22 +0200 Subject: [PATCH 13/79] Fix clean data --- htdocs/install/mysql/migration/11.0.0-12.0.0.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/install/mysql/migration/11.0.0-12.0.0.sql b/htdocs/install/mysql/migration/11.0.0-12.0.0.sql index bbf25a40a77..b7ac95b8cea 100644 --- a/htdocs/install/mysql/migration/11.0.0-12.0.0.sql +++ b/htdocs/install/mysql/migration/11.0.0-12.0.0.sql @@ -165,6 +165,8 @@ ALTER TABLE llx_bookmark MODIFY COLUMN url TEXT; ALTER TABLE llx_bookmark ADD UNIQUE uk_bookmark_title (fk_user, entity, title); +ALTER TABLE llx_societe_rib MODIFY COLUMN owner_address varchar(255); +ALTER TABLE llx_societe_rib MODIFY COLUMN default_rib smallint NOT NULL DEFAULT 0; ALTER TABLE llx_societe_rib ADD COLUMN stripe_account varchar(128); From 7115bd7033139aff8bdce5567d8c01ff4b07f933 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Thu, 4 Jun 2020 20:14:19 +0200 Subject: [PATCH 14/79] better fix --- htdocs/contact/class/contact.class.php | 56 --------------- htdocs/core/class/commonobject.class.php | 91 +++++++++++++++++++++--- htdocs/societe/class/societe.class.php | 27 +++---- 3 files changed, 98 insertions(+), 76 deletions(-) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 71d816c166e..dadb41179ca 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1067,9 +1067,6 @@ class Contact extends CommonObject $error = 0; - //$this->old_lastname = $obj->lastname; - //$this->old_firstname = $obj->firstname; - $this->db->begin(); if (!$error) @@ -1731,57 +1728,4 @@ class Contact extends CommonObject return $error * -1; } } - - /** - * Delete all contact from a thirdparty - * @param int $socId Thirdparty Id - * @param int $notrigger Disable all trigger - * @return int <0 if KO, >0 if OK - * @throws Exception - */ - public function deleteBySoc($socId = 0, $notrigger = 0) - { - $error = 0; - $deleted = 0; - - if (!empty($socId)) { - $this->db->begin(); - - $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $this->table_element; - $sql .= " WHERE fk_soc = " . $socId; - dol_syslog(__METHOD__, LOG_DEBUG); - $resql = $this->db->query($sql); - if (!$resql) { - $this->errors[] = $this->db->lasterror() . ' sql=' . $sql; - $error++; - } else { - while ($obj = $this->db->fetch_object($resql)) { - $result = $this->fetch($obj->rowid); - if ($result < 0) { - $error++; - $this->errors = $this->error; - } else { - $result = $this->delete($notrigger); - if ($result < 0) { - $error++; - $this->errors = $this->error; - } else { - $deleted++; - } - } - } - } - - if (empty($error)) { - $this->db->commit(); - return $deleted; - } else { - $this->error = implode(' ', $this->errors); - $this->db->rollback(); - return $error * -1; - } - } - - return $deleted; - } } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 7fe7fc41303..d8ff3cde3c4 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -438,10 +438,14 @@ abstract class CommonObject public $next_prev_filter; - + /** + * @var array List of child tables. To know object to delete on cascade. + * if name like with @ClassNAme:FilePathClass;ParentFkFieldName' it will + * call method deleteByParentField(parentId,ParentFkFieldName) to fetch and delete child object + */ + protected $childtablesoncascade = array(); // No constructor as it is an abstract class - /** * Check an object id/ref exists * If you don't need/want to instantiate object and just need to know if object exists, use this method instead of fetch @@ -7892,16 +7896,18 @@ abstract class CommonObject foreach ($this->childtablesoncascade as $table) { $deleteFromObject=explode(':', $table); - if (count($deleteFromObject)>1) { + if (count($deleteFromObject)>=2) { $className=str_replace('@', '', $deleteFromObject[0]); $filePath=$deleteFromObject[1]; - $deleteMethod=$deleteFromObject[2]; + $columnName=$deleteFromObject[2]; if (dol_include_once($filePath)) { $childObject = new $className($this->db); - $result= $childObject->{$deleteMethod}($this->id); - if ($result<0) { - $this->errors[] = $childObject->error; - return -1; + if (is_callable($childObject, 'deleteByParentField')) { + $result = $childObject->deleteByParentField($this->id, $columnName); + if ($result < 0) { + $this->errors[] = $childObject->error; + return -1; + } } } else { $this->errors[] = 'Cannot find child class file ' .$filePath; @@ -7963,6 +7969,75 @@ abstract class CommonObject } } + /** + * Delete all child object + * @param int $parentId Parent Id + * @param string $parentField Name of parent FIled + * @return int <0 if KO, >0 if OK + * @throws Exception + */ + public function deleteByParentField($parentId = 0, $parentField='') + { + global $user; + + $error = 0; + $deleted = 0; + + if (!empty($parentId) && !empty($parentField)) { + $this->db->begin(); + + $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql .= ' WHERE '.$parentField.' = ' . $parentId; + dol_syslog(__METHOD__, LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->errors[] = $this->db->lasterror(); + $error++; + } else { + while ($obj = $this->db->fetch_object($resql)) { + $result = $this->fetch($obj->rowid); + if ($result < 0) { + $error++; + $this->errors = $this->error; + } else { + $needUserParam = false; + if (class_exists('ReflectionMethod')) { + $method = new ReflectionMethod($this, 'delete'); + $argsMethod=$method->getParameters(); + if (is_array($argsMethod) && count($argsMethod)>0) { + if ($argsMethod[0]->name == 'user') { + $needUserParam = true; + } + } + } + if ($needUserParam) { + $result = $this->delete($user); + } else { + $result = $this->delete(); + } + if ($result < 0) { + $error++; + $this->errors = $this->error; + } else { + $deleted++; + } + } + } + } + + if (empty($error)) { + $this->db->commit(); + return $deleted; + } else { + $this->error = implode(' ', $this->errors); + $this->db->rollback(); + return $error * -1; + } + } + + return $deleted; + } + /** * Delete a line of object in database * diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index f5caa59e1f1..242b3c3efd4 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -84,7 +84,7 @@ class Societe extends CommonObject /** * @var array List of child tables. To know object to delete on cascade. - * if name like with @ClassNAme:FilePathClass:MethodDetele' it will call method to delete object rather tahn SQL delete + * if name like with @ClassNAme:FilePathClass;ParentFkFieldName' it will call method deleteByParentField (with parentId as parameters) and FieldName to fetch and delete child object */ protected $childtablesoncascade = array( "societe_prices", @@ -93,7 +93,7 @@ class Societe extends CommonObject "product_fournisseur_price", "product_customer_price_log", "product_customer_price", - "@Contact:/contact/class/contact.class.php:deleteBySoc", + "@Contact:/contact/class/contact.class.php:fk_soc", "adherent", "societe_account", "societe_rib", @@ -1682,17 +1682,19 @@ class Societe extends CommonObject { if (!$error) { - $delete_from_object=explode(':', $tabletodelete); - if (count($delete_from_object)>1) { - $class_name=str_replace('@', '', $delete_from_object[0]); - $filepath=$delete_from_object[1]; - $delete_method=$delete_from_object[2]; + $deleteFromObject=explode(':', $tabletodelete); + if (count($deleteFromObject)>=2) { + $className=str_replace('@', '', $deleteFromObject[0]); + $filepath=$deleteFromObject[1]; + $columnName=$deleteFromObject[2]; if (dol_include_once($filepath)) { - $child_object = new $class_name($this->db); - $result= $child_object->{$delete_method}($id); - if ($result<0) { - $error++; - $this->errors[] = $child_object->error; + if (class_exists($className)) { + $child_object = new $className($this->db); + $result = $child_object->deleteByParentField($id, $columnName); + if ($result < 0) { + $error++; + $this->errors[] = $child_object->error; + } } } else { $error++; @@ -1706,6 +1708,7 @@ class Societe extends CommonObject $this->errors[] = $this->db->lasterror(); } } + } } From b47761e05cd71d5c1ba945f2470fb5c7adbff450 Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Thu, 4 Jun 2020 20:20:43 +0200 Subject: [PATCH 15/79] fix comment --- htdocs/core/class/commonobject.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index d8ff3cde3c4..798783c951c 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7972,7 +7972,7 @@ abstract class CommonObject /** * Delete all child object * @param int $parentId Parent Id - * @param string $parentField Name of parent FIled + * @param string $parentField Name of Foreign key parent column * @return int <0 if KO, >0 if OK * @throws Exception */ From e9b17aac8db567d39b9bde6921f4b781f031fff7 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 4 Jun 2020 18:20:48 +0000 Subject: [PATCH 16/79] Fixing style errors. --- htdocs/core/class/commonobject.class.php | 2 +- htdocs/societe/class/societe.class.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index d8ff3cde3c4..190720a3f73 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7976,7 +7976,7 @@ abstract class CommonObject * @return int <0 if KO, >0 if OK * @throws Exception */ - public function deleteByParentField($parentId = 0, $parentField='') + public function deleteByParentField($parentId = 0, $parentField = '') { global $user; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 242b3c3efd4..12280843b2a 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1708,7 +1708,6 @@ class Societe extends CommonObject $this->errors[] = $this->db->lasterror(); } } - } } From afafe1a7377f4e6da3ec3a5efee83716a79c9afd Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Thu, 4 Jun 2020 21:38:44 +0200 Subject: [PATCH 17/79] forget[] --- htdocs/core/class/commonobject.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 1645ca2f982..922d7d3f3af 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -8017,7 +8017,7 @@ abstract class CommonObject } if ($result < 0) { $error++; - $this->errors = $this->error; + $this->errors[] = $this->error; } else { $deleted++; } From 699557adbe40e9aa86d7904d4c841876d1a2ac2c Mon Sep 17 00:00:00 2001 From: florian HENRY Date: Thu, 4 Jun 2020 21:39:23 +0200 Subject: [PATCH 18/79] forget[] --- htdocs/core/class/commonobject.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 922d7d3f3af..0747f1553f3 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7998,7 +7998,7 @@ abstract class CommonObject $result = $this->fetch($obj->rowid); if ($result < 0) { $error++; - $this->errors = $this->error; + $this->errors[] = $this->error; } else { $needUserParam = false; if (class_exists('ReflectionMethod')) { From 630525b59c18948cab1fa88e6c91513d668bbf2a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 5 Jun 2020 02:22:16 +0200 Subject: [PATCH 19/79] css --- htdocs/admin/translation.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/translation.php b/htdocs/admin/translation.php index e509f96c001..05bfe39bb54 100644 --- a/htdocs/admin/translation.php +++ b/htdocs/admin/translation.php @@ -358,9 +358,9 @@ if ($mode == 'overwrite') if ($action == 'edit' && $obj->rowid == GETPOST('rowid', 'int')) { print ''; - print ''; + print ''; print '   '; - print ''; + print ''; } else { From b75700cc0b6cc13e0c2379889c9ab9c2797a39f0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 5 Jun 2020 10:27:34 +0200 Subject: [PATCH 20/79] Fix virtualstock activation when MRP module is on --- htdocs/admin/stock.php | 11 +++++++---- htdocs/product/list.php | 7 ++++++- htdocs/product/reassort.php | 7 ++++++- htdocs/product/stock/replenish.php | 9 +++++---- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 43e610c3052..41816d72f7a 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -383,10 +383,13 @@ print '
'; print '
'; $virtualdiffersfromphysical = 0; -if ( - !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) - || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) -) { +if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) + || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) + || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) + || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) + || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) + || !empty($conf->mrp->enabled)) +{ $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs. } diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 17dd18b567b..57eacb75ed4 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -129,7 +129,12 @@ else $result = restrictedArea($user, 'produit|service', '', '', '', '', '', $obj // Define virtualdiffersfromphysical $virtualdiffersfromphysical = 0; -if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION)) +if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) + || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) + || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) + || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) + || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) + || !empty($conf->mrp->enabled)) { $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs. } diff --git a/htdocs/product/reassort.php b/htdocs/product/reassort.php index 94d2e80c303..2cbe113fe69 100644 --- a/htdocs/product/reassort.php +++ b/htdocs/product/reassort.php @@ -78,7 +78,12 @@ if (!empty($canvas)) // Define virtualdiffersfromphysical $virtualdiffersfromphysical = 0; -if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION)) +if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) + || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) + || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) + || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) + || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) + || !empty($conf->mrp->enabled)) { $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs. } diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 97d3871c027..358ca742361 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -82,10 +82,11 @@ if (!$sortorder) { // Define virtualdiffersfromphysical $virtualdiffersfromphysical = 0; if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) -|| !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) -|| !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) -|| !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) -|| !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) + || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) + || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) + || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) + || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) + || !empty($conf->mrp->enabled)) { $virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs. } From d2522483197b12334a4fc1fdd43e2c7e16688ac7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 5 Jun 2020 13:41:33 +0200 Subject: [PATCH 21/79] Fix back to link in ECM menu Fix picto in search_page --- ChangeLog | 1 + htdocs/accountancy/index.php | 2 +- htdocs/core/ajax/ajaxdirpreview.php | 2 +- htdocs/core/ajax/selectsearchbox.php | 9 ----- htdocs/core/class/html.formfile.class.php | 13 ++++--- htdocs/core/search_page.php | 4 ++- htdocs/core/tpl/filemanager.tpl.php | 2 +- htdocs/ecm/file_card.php | 8 +++-- htdocs/ecm/index.php | 4 +-- htdocs/ecm/search.php | 44 ++++++++--------------- htdocs/langs/en_US/main.lang | 1 + htdocs/theme/eldy/global.inc.php | 12 ++++--- 12 files changed, 48 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index c4bc005a94d..1d6e2e39b45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,7 @@ NEW: Accountancy - Add possibility to manage a short alternative label for accou NEW: Accountancy - General ledger - Add an option to search not reconciled lines NEW: Add accountancy code of thirdparty in contact and supplier export NEW: support webp image format +NEW: Add checkbox "overwrite if exists" into ECM/DMS module NEW: add a link to notes in members list NEW: add a parameter to group same products in TakePOS NEW: add a parameter to sort product by label in TakePOS diff --git a/htdocs/accountancy/index.php b/htdocs/accountancy/index.php index 56cf674505b..f44b5bc72f8 100644 --- a/htdocs/accountancy/index.php +++ b/htdocs/accountancy/index.php @@ -245,7 +245,7 @@ else { print load_fiche_titre($langs->trans("AccountancyArea"), '', 'accountancy'); - print $langs->trans("Module10Desc")."
\n"; + print ''.$langs->trans("Module10Desc")."
\n"; } // End of page diff --git a/htdocs/core/ajax/ajaxdirpreview.php b/htdocs/core/ajax/ajaxdirpreview.php index 32d4f8d3bfa..5b656786c8f 100644 --- a/htdocs/core/ajax/ajaxdirpreview.php +++ b/htdocs/core/ajax/ajaxdirpreview.php @@ -332,7 +332,7 @@ if ($type == 'directory') // When we show list of files for ECM files, $filearray contains file list, and directory is defined with modulepart + section into $param // When we show list of files for a directory, $filearray ciontains file list, and directory is defined with modulepart + $relativepath - //var_dump("title=".$title." modulepart=".$modulepart." useinecm=".$useinecm." perm=".$perm." relativepath=".$relativepath." param=".$param." url=".$url); + //var_dump("section=".$section." title=".$title." modulepart=".$modulepart." useinecm=".$useinecm." perm=".$perm." relativepath=".$relativepath." param=".$param." url=".$url); $formfile->list_of_documents($filearray, '', $modulepart, $param, 1, $relativepath, $perm, $useinecm, $textifempty, $maxlengthname, $title, $url, 0, $perm); } } diff --git a/htdocs/core/ajax/selectsearchbox.php b/htdocs/core/ajax/selectsearchbox.php index 31a95d1e02c..03acbde80fa 100644 --- a/htdocs/core/ajax/selectsearchbox.php +++ b/htdocs/core/ajax/selectsearchbox.php @@ -146,15 +146,6 @@ if (!empty($conf->holiday->enabled) && empty($conf->global->MAIN_SEARCHFORM_HOLI $arrayresult['searchintoleaves'] = array('position'=>220, 'img'=>'object_holiday', 'label'=>$langs->trans("SearchIntoLeaves", $search_boxvalue), 'text'=>img_picto('', 'object_holiday').' '.$langs->trans("SearchIntoLeaves", $search_boxvalue), 'url'=>DOL_URL_ROOT.'/holiday/list.php?mainmenu=hrm'.($search_boxvalue ? '&sall='.urlencode($search_boxvalue) : '')); } - -/* Do we really need this. We already have a select for users, and we should be able to filter into user list on employee flag -if (! empty($conf->hrm->enabled) && ! empty($conf->global->MAIN_SEARCHFORM_EMPLOYEE) && $user->rights->hrm->employee->read) -{ - $langs->load("hrm"); - $searchform.=printSearchForm(DOL_URL_ROOT.'/hrm/employee/list.php', DOL_URL_ROOT.'/hrm/employee/list.php', $langs->trans("Employees"), 'employee', 'search_all', 'M', 'searchleftemployee', img_object('','user')); -} -*/ - // Execute hook addSearchEntry $parameters = array('search_boxvalue'=>$search_boxvalue, 'arrayresult'=>$arrayresult); $reshook = $hookmanager->executeHooks('addSearchEntry', $parameters); diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 7251db1476e..3eeaea46858 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -168,7 +168,8 @@ class FormFile } $out .= 'global->MAIN_DISABLE_MULTIPLE_FILEUPLOAD) || $conf->browser->layout != 'classic') ? ' name="userfile"' : ' name="userfile[]" multiple'); + //$out .= ((!empty($conf->global->MAIN_DISABLE_MULTIPLE_FILEUPLOAD) || $conf->browser->layout != 'classic') ? ' name="userfile"' : ' name="userfile[]" multiple'); + $out .= ((!empty($conf->global->MAIN_DISABLE_MULTIPLE_FILEUPLOAD)) ? ' name="userfile"' : ' name="userfile[]" multiple'); $out .= (empty($conf->global->MAIN_UPLOAD_DOC) || empty($perm) ? ' disabled' : ''); $out .= (!empty($accept) ? ' accept="'.$accept.'"' : ' accept=""'); $out .= (!empty($capture) ? ' capture="capture"' : ''); @@ -1310,7 +1311,7 @@ class FormFile { if ($useinecm == 5 || $useinecm == 6) { - $smallfile = getImageFileNameForSize($file['name'], ''); // There is no thumb for ECM module and Media filemanager, so we use true image + $smallfile = getImageFileNameForSize($file['name'], ''); // There is no thumb for ECM module and Media filemanager, so we use true image. TODO Change this it is slow on image dir. } else { @@ -1376,10 +1377,14 @@ class FormFile // Delete or view link // ($param must start with &) print ''; - if ($useinecm == 1 || $useinecm == 5) // ECM manual tree + if ($useinecm == 1 || $useinecm == 5) // ECM manual tree only { - print ''.img_edit('default', 0, 'class="paddingrightonly"').''; + // $section is inside $param + $newparam.=preg_replace('/&file=.*$/', '', $param); // We don't need param file= + $backtopage = DOL_URL_ROOT.'/ecm/index.php?§ion_dir='.urlencode($relativepath).$newparam; + print ''.img_edit('default', 0, 'class="paddingrightonly"').''; } + if (empty($useinecm) || $useinecm == 2 || $useinecm == 6) // 6=Media file manager { $newmodulepart = $modulepart; diff --git a/htdocs/core/search_page.php b/htdocs/core/search_page.php index 119d7ff9a41..0268eef2259 100644 --- a/htdocs/core/search_page.php +++ b/htdocs/core/search_page.php @@ -79,6 +79,7 @@ else { $usedbyinclude = 1; // Used into next include $showtitlebefore = GETPOST('showtitlebefore', 'int'); + $arrayresult = array(); include DOL_DOCUMENT_ROOT.'/core/ajax/selectsearchbox.php'; $i = 0; @@ -95,7 +96,8 @@ else $accesskey = $val['label'][0]; $accesskeyalreadyassigned[$accesskey] = $accesskey; } - $searchform .= printSearchForm($urlaction, $urlaction, $val['label'], 'minwidth200', $keysearch, $accesskey, $key, img_picto('', $val['img'], '', 0, 1), $showtitlebefore, ($i > 0 ? 0 : 1)); + + $searchform .= printSearchForm($urlaction, $urlaction, $val['label'], 'minwidth200', $keysearch, $accesskey, $key, $val['img'], $showtitlebefore, ($i > 0 ? 0 : 1)); $i++; } diff --git a/htdocs/core/tpl/filemanager.tpl.php b/htdocs/core/tpl/filemanager.tpl.php index db72ea7d74a..fa8add900b1 100644 --- a/htdocs/core/tpl/filemanager.tpl.php +++ b/htdocs/core/tpl/filemanager.tpl.php @@ -133,7 +133,7 @@ print ''; // Start left area -// Confirmation de la suppression d'une ligne categorie +// Ask confirmation of deletion of directory if ($action == 'delete_section') { print $form->formconfirm($_SERVER["PHP_SELF"].'?section='.$section, $langs->trans('DeleteSection'), $langs->trans('ConfirmDeleteSection', $ecmdir->label), 'confirm_deletesection', '', '', 1); diff --git a/htdocs/ecm/file_card.php b/htdocs/ecm/file_card.php index 63fdedbab6d..e0c9398f9f2 100644 --- a/htdocs/ecm/file_card.php +++ b/htdocs/ecm/file_card.php @@ -33,6 +33,7 @@ $langs->loadLangs(array('ecm', 'companies', 'other', 'users', 'orders', 'propal' $action = GETPOST('action', 'aZ09'); $cancel = GETPOST('cancel', 'alpha'); +$backtopage = GETPOST('backtopage', 'alpha'); if (!$user->rights->ecm->setup) accessforbidden(); @@ -282,10 +283,13 @@ $s = img_picto('', 'object_dir').' '.$l if ($action == 'edit') $s .= ''; else $s .= $urlfiletoshow; -$morehtml = ''; +$linkback = ''; +if ($backtopage) { + $linkback = ''.$langs->trans("BackToTree").''; +} $object->ref = ''; // Force to hide ref -dol_banner_tab($object, '', $morehtml, 0, '', '', $s); +dol_banner_tab($object, '', $linkback, 0, '', '', $s); print '
'; diff --git a/htdocs/ecm/index.php b/htdocs/ecm/index.php index 2c533e483c6..c6a47bdfd42 100644 --- a/htdocs/ecm/index.php +++ b/htdocs/ecm/index.php @@ -57,7 +57,7 @@ if (!$sortorder) $sortorder = "ASC"; if (!$sortfield) $sortfield = "fullname"; $ecmdir = new EcmDirectory($db); -if ($section) +if ($section > 0) { $result = $ecmdir->fetch($section); if (!$result > 0) @@ -170,7 +170,7 @@ if ($action == 'add' && $user->rights->ecm->setup) } // Remove directory -if ($action == 'confirm_deletesection' && GETPOST('confirm') == 'yes') +if ($action == 'confirm_deletesection' && GETPOST('confirm', 'alpha') == 'yes') { $result = $ecmdir->delete($user); setEventMessages($langs->trans("ECMSectionWasRemoved", $ecmdir->label), null, 'mesgs'); diff --git a/htdocs/ecm/search.php b/htdocs/ecm/search.php index e125824a8c8..d996f2400ee 100644 --- a/htdocs/ecm/search.php +++ b/htdocs/ecm/search.php @@ -75,21 +75,17 @@ if (!empty($section)) } -/******************************************************************* - * ACTIONS - * - * Put here all code to do according to value of "action" parameter - ********************************************************************/ +/* + * Actions + */ + +// None - - -/******************************************************************* - * PAGE - * - * Put here all code to do according to value of "action" parameter - ********************************************************************/ +/* + * View + */ llxHeader(); @@ -138,10 +134,10 @@ print ''; print ''; print ""; print ''; -print "'; -print "'; -print "'; -print "'; +print ''; +print ''; +print ''; +print ''; print "
'.$langs->trans("ECMSearchByKeywords").'
".$langs->trans("Ref").':
".$langs->trans("Title").':
".$langs->trans("Keyword").':
'.$langs->trans("Ref").':
'.$langs->trans("Title").':
'.$langs->trans("Keyword").':
"; //print $langs->trans("ECMSectionManualDesc"); @@ -158,21 +154,16 @@ $butshown = 0; foreach ($sectionauto as $sectioncur) { if (!$sectioncur['test']) continue; - //if ($butshown % 2 == 0) - print ''; + print ''; print "".$sectioncur['label'].':'; print ''; print ''; print ''; - //if ($butshown % 2 == 1) - print ''; + print ''; $butshown++; } -//if ($butshown % 2 == 1) -// print '  '; print ''; print ""; @@ -192,11 +183,6 @@ $param = '&section='.$section; $textifempty = ($section ? $langs->trans("NoFileFound") : $langs->trans("ECMSelectASection")); $formfile->list_of_documents($filearray, '', 'ecm', $param, 1, $relativepath, $user->rights->ecm->upload, 1, $textifempty); -// print ''; - -// print '
'; - - print ''; diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 532edcb6a67..105d5c83bec 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -664,6 +664,7 @@ Owner=Owner FollowingConstantsWillBeSubstituted=The following constants will be replaced with the corresponding value. Refresh=Refresh BackToList=Back to list +BackToTree=Back to tree GoBack=Go back CanBeModifiedIfOk=Can be modified if valid CanBeModifiedIfKo=Can be modified if not valid diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 0ec69d4934a..b3383a1d72c 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -419,8 +419,8 @@ hr { border: 0; border-top: 1px solid #ccc; } .tabBar hr { margin-top: 20px; margin-bottom: 17px; } .button:not(.bordertransp):not(.buttonpayment), .buttonDelete:not(.bordertransp):not(.buttonpayment) { - margin-bottom: 0; - margin-top: 0; + margin-bottom: 3px; + margin-top: 3px; margin-left: 5px; margin-right: 5px; font-family: ; @@ -1158,6 +1158,10 @@ table[summary="list_of_modules"] .fa-cog { width: calc(100% - 30px) !important; display: inline-block; } + + /*img.photoref, div.photoref { + box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.2); + }*/ } /* Force values for small screen 570 */ @@ -1270,9 +1274,9 @@ table[summary="list_of_modules"] .fa-cog { padding-bottom: 5px; } img.photoref, div.photoref { - border: none; + border: 1px solid rgba(0, 0, 0, 0.2); + box-shadow: none; -webkit-box-shadow: none; - box-shadow: none; padding: 4px; height: 20px; width: 20px; From e5f8f38fbf374085c0ac3e0582b253bc51db5fda Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Fri, 5 Jun 2020 17:24:59 +0200 Subject: [PATCH 22/79] FIX: Accountancy - Binding index - Add a filter on sql request for module Subtotal & Jalon --- htdocs/accountancy/customer/index.php | 4 ++++ htdocs/accountancy/supplier/index.php | 3 +++ 2 files changed, 7 insertions(+) diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index ab2c00d13b0..b38606dc787 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -252,6 +252,7 @@ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid $sql .= " WHERE f.datef >= '" . $db->idate($search_date_start) . "'"; $sql .= " AND f.datef <= '" . $db->idate($search_date_end) . "'"; $sql .= " AND f.fk_statut > 0"; +$sql .= " AND fd.product_type <= 2"; $sql .= " AND f.entity IN (" . getEntity('invoice', 0) . ")"; // We don't share object for accountancy $sql .= " AND aa.account_number IS NULL"; if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { @@ -329,6 +330,7 @@ $sql .= " WHERE f.datef >= '" . $db->idate($search_date_start) . "'"; $sql .= " AND f.datef <= '" . $db->idate($search_date_end) . "'"; $sql .= " AND f.entity IN (" . getEntity('invoice', 0) . ")"; // We don't share object for accountancy $sql .= " AND f.fk_statut > 0"; +$sql .= " AND fd.product_type <= 2"; if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; } else { @@ -406,6 +408,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. $sql .= " AND f.datef <= '" . $db->idate($search_date_end) . "'"; $sql .= " AND f.entity IN (" . getEntity('invoice', 0) . ")"; // We don't share object for accountancy $sql .= " AND f.fk_statut > 0"; + $sql .= " AND fd.product_type <= 2"; if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; } else { @@ -458,6 +461,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. $sql .= " AND f.datef <= '" . $db->idate($search_date_end) . "'"; $sql .= " AND f.entity IN (" . getEntity('invoice', 0) . ")"; // We don't share object for accountancy $sql .= " AND f.fk_statut > 0"; + $sql .= " AND fd.product_type <= 2"; if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_REPLACEMENT . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_SITUATION . ")"; } else { diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index eb81e4909d9..9ce820deff9 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -250,6 +250,7 @@ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid $sql .= " WHERE ff.datef >= '" . $db->idate($search_date_start) . "'"; $sql .= " AND ff.datef <= '" . $db->idate($search_date_end) . "'"; $sql .= " AND ff.fk_statut > 0"; +$sql .= " AND ffd.product_type <= 2"; $sql .= " AND ff.entity IN (" . getEntity('facture_fourn', 0) . ")"; // We don't share object for accountancy $sql .= " AND aa.account_number IS NULL"; $sql .= " GROUP BY ffd.fk_code_ventilation,aa.account_number,aa.label"; @@ -321,6 +322,7 @@ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.rowid $sql .= " WHERE ff.datef >= '" . $db->idate($search_date_start) . "'"; $sql .= " AND ff.datef <= '" . $db->idate($search_date_end) . "'"; $sql .= " AND ff.fk_statut > 0"; +$sql .= " AND ffd.product_type <= 2"; $sql .= " AND ff.entity IN (" . getEntity('facture_fourn', 0) . ")"; // We don't share object for accountancy $sql .= " AND aa.account_number IS NOT NULL"; $sql .= " GROUP BY ffd.fk_code_ventilation,aa.account_number,aa.label"; @@ -392,6 +394,7 @@ if ($conf->global->MAIN_FEATURES_LEVEL > 0) // This part of code looks strange. $sql .= " WHERE ff.datef >= '" . $db->idate($search_date_start) . "'"; $sql .= " AND ff.datef <= '" . $db->idate($search_date_end) . "'"; $sql .= " AND ff.fk_statut > 0"; + $sql .= " AND ffd.product_type <= 2"; $sql .= " AND ff.entity IN (" . getEntity('facture_fourn', 0) . ")"; // We don't share object for accountancy dol_syslog('htdocs/accountancy/supplier/index.php'); From ca3f62e4ac1fc320459a416b87900ee6ae0def59 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 5 Jun 2020 17:47:52 +0200 Subject: [PATCH 23/79] Doc repair Row size too large --- htdocs/install/mysql/migration/repair.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index b21429a4d1b..7977227caf5 100644 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -519,3 +519,7 @@ UPDATE llx_facturedet SET situation_percent = 100 WHERE situation_percent IS NUL -- update llx_societe set code_compta_fournisseur = concat('401', substr(code_fournisseur, 3, 2),substr(code_fournisseur, 8, 5)) where fournisseur in (1,2,3) and code_fournisseur is not null; +-- To fix a table with error "ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs" +--ALTER TABLE llx_tablename ROW_FORMAT=DYNAMIC; + + From 2344435416fe44ebb59ce760a51c04d036240694 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 5 Jun 2020 23:10:55 +0200 Subject: [PATCH 24/79] Fix XSS CWE-ID CWE-79 --- htdocs/adherents/card.php | 115 +++++++++++++++++++------------------- htdocs/product/card.php | 14 ++--- htdocs/societe/card.php | 106 +++++++++++++++++------------------ htdocs/ticket/card.php | 18 +++--- 4 files changed, 125 insertions(+), 128 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 7d24b330d3e..21bcc17bd42 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -243,18 +243,16 @@ if (empty($reshook)) require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $birthdate = ''; - if (isset($_POST["birthday"]) && $_POST["birthday"] - && isset($_POST["birthmonth"]) && $_POST["birthmonth"] - && isset($_POST["birthyear"]) && $_POST["birthyear"]) + if (GETPOST("birthday", 'int') && GETPOST("birthmonth", 'int') && GETPOST("birthyear", 'int')) { - $birthdate = dol_mktime(12, 0, 0, $_POST["birthmonth"], $_POST["birthday"], $_POST["birthyear"]); + $birthdate = dol_mktime(12, 0, 0, GETPOST("birthmonth", 'int'), GETPOST("birthday", 'int'), GETPOST("birthyear", 'int')); } - $lastname = $_POST["lastname"]; - $firstname = $_POST["firstname"]; - $gender = $_POST["gender"]; - $societe = $_POST["societe"]; - $morphy = $_POST["morphy"]; - $login = $_POST["login"]; + $lastname = GETPOST("lastname", 'alphanohtml'); + $firstname = GETPOST("firstname", 'alphanohtml'); + $gender = GETPOST("gender", 'alphanohtml'); + $societe = GETPOST("societe", 'alphanohtml'); + $morphy = GETPOST("morphy", 'alphanohtml'); + $login = GETPOST("login", 'alphanohtml'); if ($morphy != 'mor' && empty($lastname)) { $error++; $langs->load("errors"); @@ -284,19 +282,19 @@ if (empty($reshook)) $object->oldcopy = clone $object; // Change values - $object->civility_id = trim(GETPOST("civility_id", 'alpha')); - $object->firstname = trim(GETPOST("firstname", 'alpha')); - $object->lastname = trim(GETPOST("lastname", 'alpha')); - $object->gender = trim(GETPOST("gender", 'alpha')); + $object->civility_id = trim(GETPOST("civility_id", 'alphanohtml')); + $object->firstname = trim(GETPOST("firstname", 'alphanohtml')); + $object->lastname = trim(GETPOST("lastname", 'alphanohtml')); + $object->gender = trim(GETPOST("gender", 'alphanohtml')); $object->login = trim(GETPOST("login", 'alpha')); $object->pass = trim(GETPOST("pass", 'alpha')); - $object->societe = trim(GETPOST("societe", 'alpha')); // deprecated - $object->company = trim(GETPOST("societe", 'alpha')); + $object->societe = trim(GETPOST("societe", 'alphanohtml')); // deprecated + $object->company = trim(GETPOST("societe", 'alphanohtml')); - $object->address = trim(GETPOST("address", 'alpha')); - $object->zip = trim(GETPOST("zipcode", 'alpha')); - $object->town = trim(GETPOST("town", 'alpha')); + $object->address = trim(GETPOST("address", 'alphanohtml')); + $object->zip = trim(GETPOST("zipcode", 'alphanohtml')); + $object->town = trim(GETPOST("town", 'alphanohtml')); $object->state_id = GETPOST("state_id", 'int'); $object->country_id = GETPOST("country_id", 'int'); @@ -442,14 +440,14 @@ if (empty($reshook)) } $typeid = GETPOST("typeid", 'int'); - $civility_id = GETPOST("civility_id", 'alpha'); - $lastname = GETPOST("lastname", 'alpha'); - $firstname = GETPOST("firstname", 'alpha'); - $gender = GETPOST("gender", 'alpha'); - $societe = GETPOST("societe", 'alpha'); - $address = GETPOST("address", 'alpha'); - $zip = GETPOST("zipcode", 'alpha'); - $town = GETPOST("town", 'alpha'); + $civility_id = GETPOST("civility_id", 'alphanohtml'); + $lastname = GETPOST("lastname", 'alphanohtml'); + $firstname = GETPOST("firstname", 'alphanohtml'); + $gender = GETPOST("gender", 'alphanohtml'); + $societe = GETPOST("societe", 'alphanohtml'); + $address = GETPOST("address", 'alphanohtml'); + $zip = GETPOST("zipcode", 'alphanohtml'); + $town = GETPOST("town", 'alphanohtml'); $state_id = GETPOST("state_id", 'int'); $country_id = GETPOST("country_id", 'int'); @@ -465,9 +463,8 @@ if (empty($reshook)) $pass = GETPOST("password", 'alpha'); $photo = GETPOST("photo", 'alpha'); //$comment=GETPOST("comment",'none'); - $morphy = GETPOST("morphy", 'alpha'); - $subscription = GETPOST("subscription", 'alpha'); - $public = GETPOST("public", 'alpha'); + $morphy = GETPOST("morphy", 'alphanohtml'); + $public = GETPOST("public", 'alphanohtml'); $userid = GETPOST("userid", 'int'); $socid = GETPOST("socid", 'int'); @@ -976,7 +973,7 @@ else print "\n"; // Company - print ''.$langs->trans("Company").''; + print ''.$langs->trans("Company").''; // Civility print ''.$langs->trans("UserTitle").''; @@ -984,39 +981,39 @@ else print ''; // Lastname - print ''.$langs->trans("Lastname").''; + print ''.$langs->trans("Lastname").''; print ''; // Firstname - print ''.$langs->trans("Firstname").''; + print ''.$langs->trans("Firstname").''; print ''; // Gender print ''.$langs->trans("Gender").''; print ''; $arraygender = array('man'=>$langs->trans("Genderman"), 'woman'=>$langs->trans("Genderwoman")); - print $form->selectarray('gender', $arraygender, GETPOST('gender'), 1); + print $form->selectarray('gender', $arraygender, GETPOST('gender', 'alphanohtml'), 1); print ''; // EMail - print ''.img_picto('', 'object_email').' '.($conf->global->ADHERENT_MAIL_REQUIRED ? '' : '').$langs->trans("EMail").($conf->global->ADHERENT_MAIL_REQUIRED ? '' : '').''; + print ''.img_picto('', 'object_email').' '.($conf->global->ADHERENT_MAIL_REQUIRED ? '' : '').$langs->trans("EMail").($conf->global->ADHERENT_MAIL_REQUIRED ? '' : '').''; // Address print ''.$langs->trans("Address").''; - print ''; + print ''; print ''; // Zip / Town print ''.$langs->trans("Zip").' / '.$langs->trans("Town").''; - print $formcompany->select_ziptown((GETPOST('zipcode', 'alphanohtml') ?GETPOST('zipcode', 'alphanohtml') : $object->zip), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 6); + print $formcompany->select_ziptown((GETPOSTISSET('zipcode') ? GETPOST('zipcode', 'alphanohtml') : $object->zip), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 6); print ' '; - print $formcompany->select_ziptown((GETPOST('town', 'alphanohtml') ?GETPOST('town', 'alphanohtml') : $object->town), 'town', array('zipcode', 'selectcountry_id', 'state_id')); + print $formcompany->select_ziptown((GETPOSTISSET('town') ? GETPOST('town', 'alphanohtml') : $object->town), 'town', array('zipcode', 'selectcountry_id', 'state_id')); print ''; // Country $object->country_id = $object->country_id ? $object->country_id : $mysoc->country_id; print ''.$langs->trans('Country').''; - print $form->select_country(GETPOST('country_id', 'alpha') ?GETPOST('country_id', 'alpha') : $object->country_id, 'country_id'); + print $form->select_country(GETPOSTISSET('country_id') ? GETPOST('country_id', 'alpha') : $object->country_id, 'country_id'); if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); print ''; @@ -1026,7 +1023,7 @@ else print ''.$langs->trans('State').''; if ($object->country_id) { - print $formcompany->select_state(GETPOST('state_id', 'int') ?GETPOST('state_id', 'int') : $object->state_id, $object->country_code); + print $formcompany->select_state(GETPOSTISSET('state_id') ? GETPOST('state_id', 'int') : $object->state_id, $object->country_code); } else { @@ -1036,18 +1033,18 @@ else } // Pro phone - print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePro").''; + print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePro").''; // Personal phone - print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePerso").''; + print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePerso").''; // Mobile phone - print ''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").''; + print ''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").''; if (!empty($conf->socialnetworks->enabled)) { foreach ($socialnetworks as $key => $value) { if (!$value['active']) break; - print ''.$langs->trans($value['label']).''; + print ''.$langs->trans($value['label']).''; } } @@ -1196,14 +1193,14 @@ else $morphys["phy"] = $langs->trans("Physical"); $morphys["mor"] = $langs->trans("Moral"); print ''.$langs->trans("MemberNature").''; - print $form->selectarray("morphy", $morphys, (GETPOSTISSET("morphy") ?GETPOST("morphy", 'alpha') : $object->morphy)); + print $form->selectarray("morphy", $morphys, (GETPOSTISSET("morphy") ? GETPOST("morphy", 'alpha') : $object->morphy)); print ""; // Type print ''.$langs->trans("Type").''; if ($user->rights->adherent->creer) { - print $form->selectarray("typeid", $adht->liste_array(), (GETPOSTISSET("typeid") ?GETPOST("typeid", 'int') : $object->typeid)); + print $form->selectarray("typeid", $adht->liste_array(), (GETPOSTISSET("typeid") ? GETPOST("typeid", 'int') : $object->typeid)); } else { @@ -1213,27 +1210,27 @@ else print ""; // Company - print ''.$langs->trans("Company").'company).'">'; + print ''.$langs->trans("Company").'company).'">'; // Civility print ''.$langs->trans("UserTitle").''; - print $formcompany->select_civility(isset($_POST["civility_id"]) ? $_POST["civility_id"] : $object->civility_id)."\n"; + print $formcompany->select_civility(GETPOSTISSET("civility_id") ? GETPOST("civility_id", 'alpha') : $object->civility_id)."\n"; print ''; print ''; // Lastname - print ''.$langs->trans("Lastname").'lastname).'">'; + print ''.$langs->trans("Lastname").'lastname).'">'; print ''; // Firstname - print ''.$langs->trans("Firstname").'firstname).'">'; + print ''.$langs->trans("Firstname").'firstname).'">'; print ''; // Gender print ''.$langs->trans("Gender").''; print ''; $arraygender = array('man'=>$langs->trans("Genderman"), 'woman'=>$langs->trans("Genderwoman")); - print $form->selectarray('gender', $arraygender, GETPOST('gender') ?GETPOST('gender') : $object->gender, 1); + print $form->selectarray('gender', $arraygender, GETPOSTISSET('gender') ? GETPOST('gender', 'alphanohtml') : $object->gender, 1); print ''; // Photo @@ -1256,14 +1253,14 @@ else // Address print ''.$langs->trans("Address").''; - print ''; + print ''; print ''; // Zip / Town print ''.$langs->trans("Zip").' / '.$langs->trans("Town").''; - print $formcompany->select_ziptown((isset($_POST["zipcode"]) ?GETPOST("zipcode", '', 2) : $object->zip), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 6); + print $formcompany->select_ziptown((GETPOSTISSET("zipcode") ? GETPOST("zipcode", 'alphanohtml', 2) : $object->zip), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 6); print ' '; - print $formcompany->select_ziptown((isset($_POST["town"]) ?GETPOST("town", '', 2) : $object->town), 'town', array('zipcode', 'selectcountry_id', 'state_id')); + print $formcompany->select_ziptown((GETPOSTISSET("town") ? GETPOST("town", 'alphanohtml', 2) : $object->town), 'town', array('zipcode', 'selectcountry_id', 'state_id')); print ''; // Country @@ -1282,18 +1279,18 @@ else } // Pro phone - print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePro").'phone).'">'; + print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePro").'phone).'">'; // Personal phone - print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePerso").'phone_perso).'">'; + print ''.img_picto('', 'object_phoning').' '.$langs->trans("PhonePerso").'phone_perso).'">'; // Mobile phone - print ''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").'phone_mobile).'">'; + print ''.img_picto('', 'object_phoning_mobile').' '.$langs->trans("PhoneMobile").'phone_mobile).'">'; if (!empty($conf->socialnetworks->enabled)) { foreach ($socialnetworks as $key => $value) { if (!$value['active']) break; - print ''.$langs->trans($value['label']).''; + print ''.$langs->trans($value['label']).''; } } @@ -1304,7 +1301,7 @@ else // Public profil print "".$langs->trans("Public")."\n"; - print $form->selectyesno("public", (isset($_POST["public"]) ?GETPOST("public", '', 2) : $object->public), 1); + print $form->selectyesno("public", (GETPOSTISSET("public") ? GETPOST("public", 'alphanohtml', 2) : $object->public), 1); print "\n"; // Categories diff --git a/htdocs/product/card.php b/htdocs/product/card.php index ad793f4f7d3..59f2eb13170 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -193,7 +193,7 @@ if (empty($reshook)) { $error = 0; - if (!GETPOST('label')) + if (!GETPOST('label', 'alphanohtml')) { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Label')), null, 'errors'); $action = "create"; @@ -217,8 +217,8 @@ if (empty($reshook)) $units = GETPOST('units', 'int'); $object->ref = $ref; - $object->label = GETPOST('label'); - $object->price_base_type = GETPOST('price_base_type'); + $object->label = GETPOST('label', 'alphanohtml'); + $object->price_base_type = GETPOST('price_base_type', 'aZ09'); if ($object->price_base_type == 'TTC') $object->price_ttc = GETPOST('price'); @@ -293,7 +293,7 @@ if (empty($reshook)) $object->url = GETPOST('url'); $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private', 'none')); $object->note = $object->note_private; // deprecated - $object->customcode = GETPOST('customcode', 'alpha'); + $object->customcode = GETPOST('customcode', 'alphanohtml'); $object->country_id = GETPOST('country_id', 'int'); $object->duration_value = $duration_value; $object->duration_unit = $duration_unit; @@ -394,7 +394,7 @@ if (empty($reshook)) $object->oldcopy = clone $object; $object->ref = $ref; - $object->label = GETPOST('label'); + $object->label = GETPOST('label', 'alphanohtml'); $object->description = dol_htmlcleanlastbr(GETPOST('desc', 'none')); $object->url = GETPOST('url'); if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB)) @@ -975,7 +975,7 @@ else print ''; $tmpcode = ''; if (!empty($modCodeProduct->code_auto)) $tmpcode = $modCodeProduct->getNextValue($object, $type); - print ''.$langs->trans("Ref").''; + print ''.$langs->trans("Ref").''; if ($refalreadyexists) { print $langs->trans("RefAlreadyExists"); @@ -983,7 +983,7 @@ else print ''; // Label - print ''.$langs->trans("Label").''; + print ''.$langs->trans("Label").''; // On sell print ''.$langs->trans("Status").' ('.$langs->trans("Sell").')'; diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index 9cc5febc2ca..2b4f0fc57af 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -390,23 +390,23 @@ if (empty($reshook)) if (GETPOST("private", 'int') == 1) // Ask to create a contact { - $object->particulier = GETPOST("private"); + $object->particulier = GETPOST("private", 'int'); - $object->name = dolGetFirstLastname(GETPOST('firstname', 'alpha'), GETPOST('name', 'alpha')); - $object->civility_id = GETPOST('civility_id'); // Note: civility id is a code, not an int + $object->name = dolGetFirstLastname(GETPOST('firstname', 'alphanohtml'), GETPOST('name', 'alphanohtml')); + $object->civility_id = GETPOST('civility_id', 'alphanohtml'); // Note: civility id is a code, not an int // Add non official properties - $object->name_bis = GETPOST('name', 'alpha'); - $object->firstname = GETPOST('firstname', 'alpha'); + $object->name_bis = GETPOST('name', 'alphanohtml'); + $object->firstname = GETPOST('firstname', 'alphanohtml'); } else { - $object->name = GETPOST('name', 'alpha'); + $object->name = GETPOST('name', 'alphanohtml'); } - $object->entity = (GETPOSTISSET('entity') ?GETPOST('entity', 'int') : $conf->entity); - $object->name_alias = GETPOST('name_alias'); - $object->address = GETPOST('address'); - $object->zip = GETPOST('zipcode', 'alpha'); - $object->town = GETPOST('town', 'alpha'); + $object->entity = (GETPOSTISSET('entity') ? GETPOST('entity', 'int') : $conf->entity); + $object->name_alias = GETPOST('name_alias', 'alphanohtml'); + $object->address = GETPOST('address', 'alphanohtml'); + $object->zip = GETPOST('zipcode', 'alphanohtml'); + $object->town = GETPOST('town', 'alphanohtml'); $object->country_id = GETPOST('country_id', 'int'); $object->state_id = GETPOST('state_id', 'int'); //$object->skype = GETPOST('skype', 'alpha'); @@ -425,19 +425,19 @@ if (empty($reshook)) $object->fax = GETPOST('fax', 'alpha'); $object->email = trim(GETPOST('email', 'custom', 0, FILTER_SANITIZE_EMAIL)); $object->url = trim(GETPOST('url', 'custom', 0, FILTER_SANITIZE_URL)); - $object->idprof1 = trim(GETPOST('idprof1', 'alpha')); - $object->idprof2 = trim(GETPOST('idprof2', 'alpha')); - $object->idprof3 = trim(GETPOST('idprof3', 'alpha')); - $object->idprof4 = trim(GETPOST('idprof4', 'alpha')); - $object->idprof5 = trim(GETPOST('idprof5', 'alpha')); - $object->idprof6 = trim(GETPOST('idprof6', 'alpha')); - $object->prefix_comm = GETPOST('prefix_comm', 'alpha'); + $object->idprof1 = trim(GETPOST('idprof1', 'alphanohtml')); + $object->idprof2 = trim(GETPOST('idprof2', 'alphanohtml')); + $object->idprof3 = trim(GETPOST('idprof3', 'alphanohtml')); + $object->idprof4 = trim(GETPOST('idprof4', 'alphanohtml')); + $object->idprof5 = trim(GETPOST('idprof5', 'alphanohtml')); + $object->idprof6 = trim(GETPOST('idprof6', 'alphanohtml')); + $object->prefix_comm = GETPOST('prefix_comm', 'alphanohtml'); $object->code_client = GETPOSTISSET('customer_code') ?GETPOST('customer_code', 'alpha') : GETPOST('code_client', 'alpha'); $object->code_fournisseur = GETPOSTISSET('supplier_code') ?GETPOST('supplier_code', 'alpha') : GETPOST('code_fournisseur', 'alpha'); - $object->capital = GETPOST('capital', 'alpha'); - $object->barcode = GETPOST('barcode', 'alpha'); + $object->capital = GETPOST('capital', 'alphanohtml'); + $object->barcode = GETPOST('barcode', 'alphanohtml'); - $object->tva_intra = GETPOST('tva_intra', 'alpha'); + $object->tva_intra = GETPOST('tva_intra', 'alphanohtml'); $object->tva_assuj = GETPOST('assujtva_value', 'alpha'); $object->status = GETPOST('status', 'alpha'); @@ -964,16 +964,16 @@ else if (GETPOST("type") == 'p') { $object->client = 2; } if (!empty($conf->fournisseur->enabled) && (GETPOST("type") == 'f' || (GETPOST("type") == '' && !empty($conf->global->THIRDPARTY_SUPPLIER_BY_DEFAULT)))) { $object->fournisseur = 1; } - $object->name = GETPOST('name', 'alpha'); - $object->name_alias = GETPOST('name_alias', 'alpha'); - $object->firstname = GETPOST('firstname', 'alpha'); + $object->name = GETPOST('name', 'alphanohtml'); + $object->name_alias = GETPOST('name_alias', 'alphanohtml'); + $object->firstname = GETPOST('firstname', 'alphanohtml'); $object->particulier = $private; - $object->prefix_comm = GETPOST('prefix_comm', 'alpha'); + $object->prefix_comm = GETPOST('prefix_comm', 'alphanohtml'); $object->client = GETPOST('client', 'int') ?GETPOST('client', 'int') : $object->client; if (empty($duplicate_code_error)) { $object->code_client = GETPOST('customer_code', 'alpha'); - $object->fournisseur = GETPOST('fournisseur') ?GETPOST('fournisseur') : $object->fournisseur; + $object->fournisseur = GETPOST('fournisseur') ? GETPOST('fournisseur', 'int') : $object->fournisseur; $object->code_fournisseur = GETPOST('supplier_code', 'alpha'); } else { @@ -981,9 +981,9 @@ else } - $object->address = GETPOST('address', 'alpha'); - $object->zip = GETPOST('zipcode', 'alpha'); - $object->town = GETPOST('town', 'alpha'); + $object->address = GETPOST('address', 'alphanohtml'); + $object->zip = GETPOST('zipcode', 'alphanohtml'); + $object->town = GETPOST('town', 'alphanohtml'); $object->state_id = GETPOST('state_id', 'int'); //$object->skype = GETPOST('skype', 'alpha'); //$object->twitter = GETPOST('twitter', 'alpha'); @@ -1001,14 +1001,14 @@ else $object->fax = GETPOST('fax', 'alpha'); $object->email = GETPOST('email', 'custom', 0, FILTER_SANITIZE_EMAIL); $object->url = GETPOST('url', 'custom', 0, FILTER_SANITIZE_URL); - $object->capital = GETPOST('capital', 'alpha'); - $object->barcode = GETPOST('barcode', 'alpha'); - $object->idprof1 = GETPOST('idprof1', 'alpha'); - $object->idprof2 = GETPOST('idprof2', 'alpha'); - $object->idprof3 = GETPOST('idprof3', 'alpha'); - $object->idprof4 = GETPOST('idprof4', 'alpha'); - $object->idprof5 = GETPOST('idprof5', 'alpha'); - $object->idprof6 = GETPOST('idprof6', 'alpha'); + $object->capital = GETPOST('capital', 'alphanohtml'); + $object->barcode = GETPOST('barcode', 'alphanohtml'); + $object->idprof1 = GETPOST('idprof1', 'alphanohtml'); + $object->idprof2 = GETPOST('idprof2', 'alphanohtml'); + $object->idprof3 = GETPOST('idprof3', 'alphanohtml'); + $object->idprof4 = GETPOST('idprof4', 'alphanohtml'); + $object->idprof5 = GETPOST('idprof5', 'alphanohtml'); + $object->idprof6 = GETPOST('idprof6', 'alphanohtml'); $object->typent_id = GETPOST('typent_id', 'int'); $object->effectif_id = GETPOST('effectif_id', 'int'); $object->civility_id = GETPOST('civility_id', 'alpha'); @@ -1023,7 +1023,7 @@ else $object->localtax1_value = GETPOST('lt1', 'int'); $object->localtax2_value = GETPOST('lt2', 'int'); - $object->tva_intra = GETPOST('tva_intra', 'alpha'); + $object->tva_intra = GETPOST('tva_intra', 'alphanohtml'); $object->commercial_id = GETPOST('commercial_id', 'int'); $object->default_lang = GETPOST('default_lang'); @@ -1252,7 +1252,7 @@ else print ''.$form->editfieldkey('Vendor', 'fournisseur', '', $object, 0, 'string', '', 1).''; $default = -1; if (!empty($conf->global->THIRDPARTY_SUPPLIER_BY_DEFAULT)) $default = 1; - print $form->selectyesno("fournisseur", (GETPOST('fournisseur', 'int') != '' ?GETPOST('fournisseur', 'int') : (GETPOST("type", 'alpha') == '' ? $default : $object->fournisseur)), 1, 0, (GETPOST("type", 'alpha') == '' ? 1 : 0)); + print $form->selectyesno("fournisseur", (GETPOST('fournisseur', 'int') != '' ? GETPOST('fournisseur', 'int') : (GETPOST("type", 'alpha') == '' ? $default : $object->fournisseur)), 1, 0, (GETPOST("type", 'alpha') == '' ? 1 : 0)); print ''; @@ -1651,15 +1651,15 @@ else if (GETPOSTISSET('name')) { // We overwrite with values if posted - $object->name = GETPOST('name', 'alpha'); - $object->prefix_comm = GETPOST('prefix_comm', 'alpha'); + $object->name = GETPOST('name', 'alphanohtml'); + $object->prefix_comm = GETPOST('prefix_comm', 'alphanohtml'); $object->client = GETPOST('client', 'int'); $object->code_client = GETPOST('customer_code', 'alpha'); $object->fournisseur = GETPOST('fournisseur', 'int'); $object->code_fournisseur = GETPOST('supplier_code', 'alpha'); - $object->address = GETPOST('address', 'alpha'); - $object->zip = GETPOST('zipcode', 'alpha'); - $object->town = GETPOST('town', 'alpha'); + $object->address = GETPOST('address', 'alphanohtml'); + $object->zip = GETPOST('zipcode', 'alphanohtml'); + $object->town = GETPOST('town', 'alphanohtml'); $object->country_id = GETPOST('country_id') ?GETPOST('country_id', 'int') : $mysoc->country_id; $object->state_id = GETPOST('state_id', 'int'); //$object->skype = GETPOST('skype', 'alpha'); @@ -1678,21 +1678,21 @@ else $object->fax = GETPOST('fax', 'alpha'); $object->email = GETPOST('email', 'custom', 0, FILTER_SANITIZE_EMAIL); $object->url = GETPOST('url', 'custom', 0, FILTER_SANITIZE_URL); - $object->capital = GETPOST('capital', 'alpha'); - $object->idprof1 = GETPOST('idprof1', 'alpha'); - $object->idprof2 = GETPOST('idprof2', 'alpha'); - $object->idprof3 = GETPOST('idprof3', 'alpha'); - $object->idprof4 = GETPOST('idprof4', 'alpha'); - $object->idprof5 = GETPOST('idprof5', 'alpha'); - $object->idprof6 = GETPOST('idprof6', 'alpha'); + $object->capital = GETPOST('capital', 'alphanohtml'); + $object->idprof1 = GETPOST('idprof1', 'alphanohtml'); + $object->idprof2 = GETPOST('idprof2', 'alphanohtml'); + $object->idprof3 = GETPOST('idprof3', 'alphanohtml'); + $object->idprof4 = GETPOST('idprof4', 'alphanohtml'); + $object->idprof5 = GETPOST('idprof5', 'alphanohtml'); + $object->idprof6 = GETPOST('idprof6', 'alphanohtml'); $object->typent_id = GETPOST('typent_id', 'int'); $object->effectif_id = GETPOST('effectif_id', 'int'); - $object->barcode = GETPOST('barcode', 'alpha'); + $object->barcode = GETPOST('barcode', 'alphanohtml'); $object->forme_juridique_code = GETPOST('forme_juridique_code', 'int'); $object->default_lang = GETPOST('default_lang', 'alpha'); $object->tva_assuj = GETPOST('assujtva_value', 'int'); - $object->tva_intra = GETPOST('tva_intra', 'alpha'); + $object->tva_intra = GETPOST('tva_intra', 'alphanohtml'); $object->status = GETPOST('status', 'int'); // Webservices url/key diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index d59581fa914..64ad5de4906 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -129,11 +129,11 @@ if ($cancel) if (GETPOST('add', 'alpha') && $user->rights->ticket->write) { $error = 0; - if (!GETPOST("subject", 'alpha')) { + if (!GETPOST("subject", 'alphanohtml')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")), null, 'errors'); $action = 'create'; - } elseif (!GETPOST("message", 'alpha')) { + } elseif (!GETPOST("message", 'restricthtml')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Message")), null, 'errors'); $action = 'create'; @@ -142,10 +142,10 @@ if (GETPOST('add', 'alpha') && $user->rights->ticket->write) { if (!$error) { $db->begin(); - $object->ref = GETPOST("ref", 'alpha'); + $object->ref = GETPOST("ref", 'alphanohtml'); $object->fk_soc = GETPOST("socid", 'int') > 0 ? GETPOST("socid", 'int') : 0; - $object->subject = GETPOST("subject", 'alpha'); - $object->message = GETPOST("message", 'none'); + $object->subject = GETPOST("subject", 'alphanohtml'); + $object->message = GETPOST("message", 'restricthtml'); $object->type_code = GETPOST("type_code", 'alpha'); $object->category_code = GETPOST("category_code", 'alpha'); @@ -274,7 +274,7 @@ if (GETPOST('update', 'alpha') && GETPOST('id', 'int') && $user->rights->ticket- $error++; array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Label"))); $action = 'edit'; - } elseif (!GETPOST("subject")) { + } elseif (!GETPOST("subject", 'alphanohtml')) { $error++; array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject"))); $action = 'edit'; @@ -284,7 +284,7 @@ if (GETPOST('update', 'alpha') && GETPOST('id', 'int') && $user->rights->ticket- $db->begin(); $object->label = GETPOST("label", 'alphanohtml'); - $object->description = GETPOST("description", 'none'); + $object->description = GETPOST("description", 'restricthtml'); //... $ret = $object->update($user); @@ -459,7 +459,7 @@ if ($action == 'set_progression' && $user->rights->ticket->write) { if ($action == 'setsubject') { if ($object->fetch(GETPOST('id', 'int'))) { if ($action == 'setsubject') { - $object->subject = trim(GETPOST('subject', 'alpha')); + $object->subject = trim(GETPOST('subject', 'alphanohtml')); } if ($action == 'setsubject' && empty($object->subject)) { @@ -512,7 +512,7 @@ elseif ($action == 'setcontract' && $user->rights->ticket->write) { if (!GETPOST('cancel')) { $object->fetch('', '', GETPOST('track_id', 'alpha')); $oldvalue_message = $object->message; - $fieldtomodify = GETPOST('message_initial'); + $fieldtomodify = GETPOST('message_initial', 'restricthtml'); $object->message = $fieldtomodify; $ret = $object->update($user); From 5dd9f4e4c4e8b5a950ecd20549b0825c4421415f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 11:36:24 +0200 Subject: [PATCH 25/79] Fix travis false positive --- htdocs/install/mysql/migration/repair.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 7977227caf5..28fe1697449 100644 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -519,7 +519,7 @@ UPDATE llx_facturedet SET situation_percent = 100 WHERE situation_percent IS NUL -- update llx_societe set code_compta_fournisseur = concat('401', substr(code_fournisseur, 3, 2),substr(code_fournisseur, 8, 5)) where fournisseur in (1,2,3) and code_fournisseur is not null; --- To fix a table with error "ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs" +-- To fix a table with error 'ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs' --ALTER TABLE llx_tablename ROW_FORMAT=DYNAMIC; From cefc8dcca2fd4e5fda774b5bf54610e3fa801a51 Mon Sep 17 00:00:00 2001 From: Marc Guenneugues Date: Sat, 6 Jun 2020 11:39:49 +0200 Subject: [PATCH 26/79] replenish : select expedition quantities only from opened orders when using virtual stocks --- htdocs/product/stock/replenish.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index feba2dbafcb..dbf07c92d01 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -376,8 +376,11 @@ if ($usevirtualstock) $sqlExpeditionsCli = "(SELECT ".$db->ifsql("SUM(ed2.qty) IS NULL", "0", "SUM(ed2.qty)")." as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL $sqlExpeditionsCli .= " FROM ".MAIN_DB_PREFIX."expedition as e2,"; $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."expeditiondet as ed2,"; + $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."commande as c2,"; $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."commandedet as cd2"; $sqlExpeditionsCli .= " WHERE ed2.fk_expedition = e2.rowid AND cd2.rowid = ed2.fk_origin_line AND e2.entity IN (".getEntity('expedition').")"; + $sqlExpeditionsCli .= " AND cd2.fk_commande = c2.rowid"; + $sqlExpeditionsCli .= " AND c2.fk_statut IN (1,2)"; $sqlExpeditionsCli .= " AND cd2.fk_product = p.rowid"; $sqlExpeditionsCli .= " AND e2.fk_statut IN (1,2))"; } else { From 919cc0da87a3b8fe320a97e77e8eb88d1cfca9f9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 15:39:18 +0200 Subject: [PATCH 27/79] Fix num payment --- .../sociales/class/paymentsocialcontribution.class.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php index bae8d28a756..c771a664d5f 100644 --- a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php +++ b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php @@ -159,7 +159,7 @@ class PaymentSocialContribution extends CommonObject if ($totalamount != 0) { $sql = "INSERT INTO ".MAIN_DB_PREFIX."paiementcharge (fk_charge, datec, datep, amount,"; - $sql .= " fk_typepaiement, num_paiement as num_payment, note, fk_user_creat, fk_bank)"; + $sql .= " fk_typepaiement, num_paiement, note, fk_user_creat, fk_bank)"; $sql .= " VALUES ($this->chid, '".$this->db->idate($now)."',"; $sql .= " '".$this->db->idate($this->datepaye)."',"; $sql .= " ".$totalamount.","; @@ -516,6 +516,9 @@ class PaymentSocialContribution extends CommonObject { global $conf; + // Clean data + $this->num_payment = trim($this->num_payment ? $this->num_payment : $this->num_paiement); + $error = 0; if (!empty($conf->banque->enabled)) @@ -534,7 +537,7 @@ class PaymentSocialContribution extends CommonObject $this->paiementtype, // Payment mode id or code ("CHQ or VIR for example") $label, $total, - $this->num_paiement, + $this->num_payment, '', $user, $emetteur_nom, From dd5b5e9bbfec30de443f2bf4818d890c1c645fed Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 17:12:37 +0200 Subject: [PATCH 28/79] Fix lang suggested in clone of page --- htdocs/website/index.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 7153a7bc3d0..5c0505d9da7 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2532,9 +2532,12 @@ if (!GETPOST('hide_websitemenu')) // Confirmation to clone if ($action == 'createpagefromclone') { // Create an array for form - $preselectedlanguage = GETPOST('newlang', 'aZ09') ? GETPOST('newlang', 'aZ09') : ($objectpage->lang ? $objectpage->lang : $langs->defaultlang); + $preselectedlanguage = GETPOST('newlang', 'aZ09') ? GETPOST('newlang', 'aZ09') : ''; // Dy default, we do not force any language on pages $onlylang = array(); if ($website->otherlang) { + if (! empty($website->lang)) { + $onlylang[$website->lang] = $website->lang; + } foreach (explode(',', $website->otherlang) as $langkey) { $onlylang[$langkey] = $langkey; } From 36bc266d6725b957a47b8f96dab0672bfb4aab9d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 17:33:26 +0200 Subject: [PATCH 29/79] css --- htdocs/theme/eldy/main_menu_fa_icons.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/theme/eldy/main_menu_fa_icons.inc.php b/htdocs/theme/eldy/main_menu_fa_icons.inc.php index c344838458d..b77dc86765c 100644 --- a/htdocs/theme/eldy/main_menu_fa_icons.inc.php +++ b/htdocs/theme/eldy/main_menu_fa_icons.inc.php @@ -146,11 +146,11 @@ div.mainmenu.generic4::before { /* Define color of some picto */ .fa-phone, .fa-mobile-alt, .fa-fax { - opacity: 0.5; + opacity: 0.7; color: #440; } .fa-at, .fa-external-link-alt { - opacity: 0.5; + opacity: 0.7; color: #304; } .fa-trash { From e31e889595ae6c7d2bc6e6c8ecf51ecae5c3af0d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 18:30:04 +0200 Subject: [PATCH 30/79] Add url in error message --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index dd107308fed..4105682a06a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3959,7 +3959,7 @@ function dol_print_error($db = '', $error = '', $errors = null) $out .= $langs->trans("InformationToHelpDiagnose").":
\n"; $out .= "".$langs->trans("Date").": ".dol_print_date(time(), 'dayhourlog')."
\n"; - $out .= "".$langs->trans("Dolibarr").": ".DOL_VERSION."
\n"; + $out .= "".$langs->trans("Dolibarr").": ".DOL_VERSION." - https://www.dolibarr.org
\n"; if (isset($conf->global->MAIN_FEATURES_LEVEL)) $out .= "".$langs->trans("LevelOfFeature").": ".$conf->global->MAIN_FEATURES_LEVEL."
\n"; if (function_exists("phpversion")) { From 7061e9b4cbf198505488fb6205da55b5bb906068 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 18:57:24 +0200 Subject: [PATCH 31/79] Fix deletion of website page --- .../template/class/myobject.class.php | 6 +- htdocs/website/class/websitepage.class.php | 58 ++++++++++++++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 057a2aab615..03fffaaba5d 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -181,7 +181,7 @@ class MyObject extends CommonObject //public $table_element_line = 'mymodule_myobjectline'; /** - * @var int Field with ID of parent key if this field has a parent + * @var int Field with ID of parent key if this object has a parent */ //public $fk_element = 'fk_myobject'; @@ -193,12 +193,12 @@ class MyObject extends CommonObject /** * @var array List of child tables. To test if we can delete object. */ - //protected $childtables=array(); + //protected $childtables = array(); /** * @var array List of child tables. To know object to delete on cascade. */ - //protected $childtablesoncascade=array('mymodule_myobjectdet'); + //protected $childtablesoncascade = array('mymodule_myobjectdet'); /** * @var MyObjectLine[] Array of subtable lines diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 2a72a222265..61ec8376414 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -49,6 +49,7 @@ class WebsitePage extends CommonObject */ public $picto = 'file-code'; + /** * @var int ID */ @@ -164,6 +165,35 @@ class WebsitePage extends CommonObject // END MODULEBUILDER PROPERTIES + // If this object has a subtable with lines + + /** + * @var int Name of subtable line + */ + //public $table_element_line = 'mymodule_myobjectline'; + + /** + * @var int Field with ID of parent key if this object has a parent + */ + public $fk_element = 'fk_website'; + + /** + * @var int Name of subtable class that manage subtable lines + */ + //public $class_element_line = 'MyObjectline'; + + /** + * @var array List of child tables. To test if we can delete object. + */ + //protected $childtables=array(); + + /** + * @var array List of child tables. To know object to delete on cascade. + */ + protected $childtablesoncascade = array('categorie_website_page'); + + + /** * Constructor * @@ -523,9 +553,33 @@ class WebsitePage extends CommonObject */ public function delete(User $user, $notrigger = false) { - $result = $this->deleteCommon($user, $trigger); + $error = 0; - if ($result > 0) + // Delete all child tables + if (!$error) { + foreach ($this->childtablesoncascade as $table) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX.$table; + $sql .= " WHERE fk_website_page = ".(int) $this->id; + + $result = $this->db->query($sql); + if (!$result) { + $error++; + $this->errors[] = $this->db->lasterror(); + break; + } + } + } + + if (!$error) { + $result = $this->deleteCommon($user, $trigger); + if ($result > 0) + { + $error++; + } + } + + if (!$error) { $websiteobj = new Website($this->db); $result = $websiteobj->fetch($this->fk_website); From f0892b08b87071ee182bd772eab3ef9014c67bd2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 19:46:28 +0200 Subject: [PATCH 32/79] Fix limit --- scripts/website/regenerate-pages.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/website/regenerate-pages.php b/scripts/website/regenerate-pages.php index d6b0c75800a..dfd49c1fe29 100755 --- a/scripts/website/regenerate-pages.php +++ b/scripts/website/regenerate-pages.php @@ -67,7 +67,7 @@ $websitepagestatic = new WebsitePage($db); $db->begin(); -$listofpages = $websitepagestatic->fetchAll($website->id, '', $max); +$listofpages = $websitepagestatic->fetchAll($website->id, '', '', $max); global $dolibarr_main_data_root; $pathofwebsite = $dolibarr_main_data_root.'/website/'.$websiteref; From 2d87da88151f07a25f1cb2dd2bbc0753d9025830 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 20:11:01 +0200 Subject: [PATCH 33/79] Fix link --- htdocs/website/class/website.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index d579a8b3153..161c60f5c52 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1498,7 +1498,7 @@ class Website extends CommonObject $countrycode = strtolower(substr($languagecodeselected, -2)); $label = $weblangs->trans("Language_".$languagecodeselected); if ($countrycode == 'us') $label = preg_replace('/\s*\(.*\)/', '', $label); - $out .= '
  • '.$label.''; + $out .= '
  • '.$label.''; $out .= ''; $out .= '
  • '; } From 34778937c3753e0cbd9050e89b2451e361587723 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 20:16:07 +0200 Subject: [PATCH 34/79] Fix link to image --- htdocs/website/class/website.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 161c60f5c52..b45058ced23 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1517,7 +1517,7 @@ class Website extends CommonObject $countrycode = strtolower(substr($languagecode, -2)); $label = $weblangs->trans("Language_".$languagecode); if ($countrycode == 'us') $label = preg_replace('/\s*\(.*\)/', '', $label); - $out .= '
  • '.$label.''; + $out .= '
  • '.$label.''; if (empty($i) && empty($languagecodeselected)) $out .= ''; $out .= '
  • '; $i++; From fb02edf254aeaa9b9f6b58321791bb14d08f041f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 20:25:05 +0200 Subject: [PATCH 35/79] Fix For select language component, we force on root --- htdocs/website/class/website.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index b45058ced23..2d69131d469 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1459,6 +1459,7 @@ class Website extends CommonObject $url = preg_replace('/(\?|&)l=([a-zA-Z_]*)/', '', $url); // We remove param l from url //$url = preg_replace('/(\?|&)lang=([a-zA-Z_]*)/', '', $url); // We remove param lang from url $url .= (preg_match('/\?/', $url) ? '&' : '?').'l='; + if (! preg_match('/^\//', $url)) $url = '/'.$url; $HEIGHTOPTION = 40; $MAXHEIGHT = 4 * $HEIGHTOPTION; From 123265bf4ce6408258e5d7a14f6b9b8daefde678 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 20:37:17 +0200 Subject: [PATCH 36/79] Fix redirect url in multilang --- htdocs/core/website.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php index 5c618b089a3..d611f687414 100644 --- a/htdocs/core/website.inc.php +++ b/htdocs/core/website.inc.php @@ -121,7 +121,7 @@ if ($_SERVER['PHP_SELF'] != DOL_URL_ROOT.'/website/index.php') // If we browsing else { $newpageref = $obj->pageurl; - header("Location: ".$newpageref.'.php?l='.GETPOST('l', 'aZ09')); + header("Location: ".(($obj->lang && $obj->lang != $website->lang) ? '/'.$obj->lang.'/' : '/').$newpageref.'.php?l='.GETPOST('l', 'aZ09')); exit; } } From 30c6ae394b9d4d1bb6ce3c1405e91d94fba77bdb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:23:35 +0200 Subject: [PATCH 37/79] Update html.formticket.class.php --- htdocs/core/class/html.formticket.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 72673abb323..7a6b4ec38a2 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -991,7 +991,9 @@ class FormTicket // MESSAGE $defaultmessage=""; - if ($arraydefaultmessage && $arraydefaultmessage->content) $defaultmessage = $arraydefaultmessage->content; + if (is_array($arraydefaultmessage) && count($arraydefaultmessage) > 0 && $arraydefaultmessage->content) { + $defaultmessage=$arraydefaultmessage->content; + } $defaultmessage=str_replace('\n', "\n", $defaultmessage); // Deal with format differences between message and signature (text / HTML) From a66926cf08491f2aa7fa668477ac150cedcff376 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:30:08 +0200 Subject: [PATCH 38/79] Update commonobject.class.php --- htdocs/core/class/commonobject.class.php | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 0747f1553f3..fec5ea35485 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7970,7 +7970,8 @@ abstract class CommonObject } /** - * Delete all child object + * Delete all child object from a parent ID + * * @param int $parentId Parent Id * @param string $parentField Name of Foreign key parent column * @return int <0 if KO, >0 if OK @@ -7988,7 +7989,7 @@ abstract class CommonObject $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $this->table_element; $sql .= ' WHERE '.$parentField.' = ' . $parentId; - dol_syslog(__METHOD__, LOG_DEBUG); + $resql = $this->db->query($sql); if (!$resql) { $this->errors[] = $this->db->lasterror(); @@ -8000,21 +8001,7 @@ abstract class CommonObject $error++; $this->errors[] = $this->error; } else { - $needUserParam = false; - if (class_exists('ReflectionMethod')) { - $method = new ReflectionMethod($this, 'delete'); - $argsMethod=$method->getParameters(); - if (is_array($argsMethod) && count($argsMethod)>0) { - if ($argsMethod[0]->name == 'user') { - $needUserParam = true; - } - } - } - if ($needUserParam) { - $result = $this->delete($user); - } else { - $result = $this->delete(); - } + $result = $this->delete($user); if ($result < 0) { $error++; $this->errors[] = $this->error; @@ -8029,7 +8016,7 @@ abstract class CommonObject $this->db->commit(); return $deleted; } else { - $this->error = implode(' ', $this->errors); + $this->error = implode(', ', $this->errors); $this->db->rollback(); return $error * -1; } From af440b7c49cdf3a098a7dc3a2239a4dc6520e4a2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:32:25 +0200 Subject: [PATCH 39/79] Update societe.class.php --- htdocs/societe/class/societe.class.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 12280843b2a..0ad6ab22f23 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1688,13 +1688,11 @@ class Societe extends CommonObject $filepath=$deleteFromObject[1]; $columnName=$deleteFromObject[2]; if (dol_include_once($filepath)) { - if (class_exists($className)) { - $child_object = new $className($this->db); - $result = $child_object->deleteByParentField($id, $columnName); - if ($result < 0) { - $error++; - $this->errors[] = $child_object->error; - } + $child_object = new $className($this->db); + $result = $child_object->deleteByParentField($id, $columnName); + if ($result < 0) { + $error++; + $this->errors[] = $child_object->error; } } else { $error++; From d9ac7ab9da8ab3d2632ceb3aa3c1a46a465e3836 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:37:53 +0200 Subject: [PATCH 40/79] Update commonobject.class.php --- htdocs/core/class/commonobject.class.php | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index fec5ea35485..ffd5e53dccf 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7892,35 +7892,37 @@ abstract class CommonObject } // Delete cascade first - if (!empty($this->childtablesoncascade)) { + if (is_array($this->childtablesoncascade)) { foreach ($this->childtablesoncascade as $table) { - $deleteFromObject=explode(':', $table); + $deleteFromObject = explode(':', $table); if (count($deleteFromObject)>=2) { - $className=str_replace('@', '', $deleteFromObject[0]); - $filePath=$deleteFromObject[1]; - $columnName=$deleteFromObject[2]; + $className = str_replace('@', '', $deleteFromObject[0]); + $filePath = $deleteFromObject[1]; + $columnName = $deleteFromObject[2]; if (dol_include_once($filePath)) { $childObject = new $className($this->db); - if (is_callable($childObject, 'deleteByParentField')) { + if (method_exists($childObject, 'deleteByParentField')) { $result = $childObject->deleteByParentField($this->id, $columnName); if ($result < 0) { + $error++; $this->errors[] = $childObject->error; - return -1; + break; } } } else { - $this->errors[] = 'Cannot find child class file ' .$filePath; - return -1; + $error++; + $this->errors[] = 'Cannot include child class file ' .$filePath; + break; } } else { $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $table . ' WHERE ' . $this->fk_element . ' = ' . $this->id; $resql = $this->db->query($sql); if (!$resql) { + $error++; $this->error = $this->db->lasterror(); $this->errors[] = $this->error; - $this->db->rollback(); - return -1; + break; } } } From 87806346c7079bb703a2da1f0fb5c62876bfc7f0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:40:20 +0200 Subject: [PATCH 41/79] Update commonobject.class.php --- htdocs/core/class/commonobject.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ffd5e53dccf..6634ccd7fcd 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7990,7 +7990,7 @@ abstract class CommonObject $this->db->begin(); $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $this->table_element; - $sql .= ' WHERE '.$parentField.' = ' . $parentId; + $sql .= ' WHERE '.$parentField.' = ' . (int) $parentId; $resql = $this->db->query($sql); if (!$resql) { From bb192195f19cd4d20d5cd3146f5f3f45f780ba2d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:41:33 +0200 Subject: [PATCH 42/79] Update commonobject.class.php --- htdocs/core/class/commonobject.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 6634ccd7fcd..9f252879fda 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7892,7 +7892,7 @@ abstract class CommonObject } // Delete cascade first - if (is_array($this->childtablesoncascade)) { + if (is_array($this->childtablesoncascade) && !empty($this->childtablesoncascade)) { foreach ($this->childtablesoncascade as $table) { $deleteFromObject = explode(':', $table); From 38d95aa5cdecf66b4757b2fe9fd66df0e57a6932 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:45:53 +0200 Subject: [PATCH 43/79] Update societe.class.php --- htdocs/societe/class/societe.class.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 0ad6ab22f23..a37830b0ed9 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1678,9 +1678,9 @@ class Societe extends CommonObject } } - foreach ($this->childtablesoncascade as $tabletodelete) + if (!$error) { - if (!$error) + foreach ($this->childtablesoncascade as $tabletodelete) { $deleteFromObject=explode(':', $tabletodelete); if (count($deleteFromObject)>=2) { @@ -1693,10 +1693,12 @@ class Societe extends CommonObject if ($result < 0) { $error++; $this->errors[] = $child_object->error; + break; } } else { $error++; - $this->errors[] = 'Cannot find child class file ' .$filepath; + $this->errors[] = 'Cannot include child class file ' .$filepath; + break; } } else { $sql = "DELETE FROM " . MAIN_DB_PREFIX . $tabletodelete; @@ -1704,6 +1706,7 @@ class Societe extends CommonObject if (!$this->db->query($sql)) { $error++; $this->errors[] = $this->db->lasterror(); + break; } } } From 261d0772f8812a3c7883e7ebf3dd880c36b4f26e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:47:27 +0200 Subject: [PATCH 44/79] Update commonobject.class.php --- htdocs/core/class/commonobject.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 9f252879fda..9dba821c012 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7909,7 +7909,11 @@ abstract class CommonObject $this->errors[] = $childObject->error; break; } - } + } else { + $error++; + $this->errors[] = "You defined a cascade delete on an object $childObject but there is no method deleteByParentField for it"; + break; + } } else { $error++; $this->errors[] = 'Cannot include child class file ' .$filePath; From b221c651654afa80e86fe2c8d9fc477be2ee635d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 21:56:23 +0200 Subject: [PATCH 45/79] Merge --- htdocs/core/class/commonobject.class.php | 10 ++++++++-- htdocs/modulebuilder/template/class/myobject.class.php | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 740645c8c8e..a13af375542 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -443,13 +443,19 @@ abstract class CommonObject public $next_prev_filter; + /** + * @var array List of child tables. To test if we can delete object. + */ + protected $childtables = array(); + /** * @var array List of child tables. To know object to delete on cascade. - * if name like with @ClassNAme:FilePathClass;ParentFkFieldName' it will - * call method deleteByParentField(parentId,ParentFkFieldName) to fetch and delete child object + * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object */ protected $childtablesoncascade = array(); + // No constructor as it is an abstract class /** * Check an object id/ref exists diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 03fffaaba5d..9a15aa59836 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -196,7 +196,9 @@ class MyObject extends CommonObject //protected $childtables = array(); /** - * @var array List of child tables. To know object to delete on cascade. + * @var array List of child tables. To know object to delete on cascade. + * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object */ //protected $childtablesoncascade = array('mymodule_myobjectdet'); From 115b82711523ac6fda8542d472d541bf4159ab58 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 6 Jun 2020 22:52:36 +0200 Subject: [PATCH 46/79] Prepare v12 --- htdocs/filefunc.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index eda59d8e0bb..1697037619f 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -31,7 +31,7 @@ */ if (!defined('DOL_APPLICATION_TITLE')) define('DOL_APPLICATION_TITLE', 'Dolibarr'); -if (!defined('DOL_VERSION')) define('DOL_VERSION', '12.0.0-beta'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c +if (!defined('DOL_VERSION')) define('DOL_VERSION', '12.0.0'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c if (!defined('EURO')) define('EURO', chr(128)); From 4169aa716cf2186e9bebec2602a497699de0f048 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 00:23:20 +0200 Subject: [PATCH 47/79] FIX can install module even if (x) was appended during download. --- htdocs/admin/modules.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 72eb8240c10..b11808a2365 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -118,6 +118,7 @@ if ($action == 'install') // $original_file should match format module_modulename-x.y[.z].zip $original_file = basename($_FILES["fileinstall"]["name"]); + $original_file = preg_replace('/\(\d+\)\.zip$/i', '.zip', $original_file); $newfile = $conf->admin->dir_temp.'/'.$original_file.'/'.$original_file; if (!$original_file) From 04f68d25cd29592544614c3da2160a2c828b89a7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 01:34:26 +0200 Subject: [PATCH 48/79] css --- htdocs/index.php | 6 +++--- htdocs/theme/eldy/global.inc.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/index.php b/htdocs/index.php index 1ad2d1b4f64..1e6b7bcf210 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -898,10 +898,10 @@ if (empty($user->socid) && empty($conf->global->MAIN_DISABLE_GLOBAL_BOXSTATS)) $boxstat .= ''."\n"; $boxstat .= '
    '; $boxstat .= ''; - $boxstat .= ''; - $boxstat .= ''; + $boxstat .= ''; $boxstat .= ''; $boxstat .= ''; print ''; print '
    '; + $boxstat .= '
    '; $boxstat .= '
    '.$langs->trans("DolibarrStateBoard").'
    '; - $boxstat .= ''; + $boxstat .= '
    '; diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index b3383a1d72c..d8c3cc81b5c 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1373,7 +1373,7 @@ td.showDragHandle { .side-nav { display: table-cell; - border-: 1px solid #d0d0d0; + border-: 1px solid #E0E0E0; box-shadow: 3px 0 6px -2px #eee; background: var(--colorbackvmenu1); transition: left 0.5s ease; From 42d44e996f38a09477783195e1d0151b6d14699b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 13:49:49 +0200 Subject: [PATCH 49/79] Fix link to setup page --- htdocs/admin/defaultvalues.php | 2 +- htdocs/admin/translation.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/admin/defaultvalues.php b/htdocs/admin/defaultvalues.php index 094c4a8dd7c..6e315f4f23c 100644 --- a/htdocs/admin/defaultvalues.php +++ b/htdocs/admin/defaultvalues.php @@ -185,7 +185,7 @@ if ($action == 'delete') $form = new Form($db); $formadmin = new FormAdmin($db); -$wikihelp = 'EN:Setup|FR:Paramétrage|ES:Configuración'; +$wikihelp = 'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones'; llxHeader('', $langs->trans("Setup"), $wikihelp); $param = '&mode='.$mode; diff --git a/htdocs/admin/translation.php b/htdocs/admin/translation.php index 05bfe39bb54..ecc25c58509 100644 --- a/htdocs/admin/translation.php +++ b/htdocs/admin/translation.php @@ -197,7 +197,7 @@ if ($action == 'delete') $form = new Form($db); $formadmin = new FormAdmin($db); -$wikihelp = 'EN:Setup|FR:Paramétrage|ES:Configuración'; +$wikihelp = 'EN:Setup Translation|FR:Paramétrage traduction|ES:Configuración'; llxHeader('', $langs->trans("Setup"), $wikihelp); $param = '&mode='.$mode; From 7b53ee2a6ff2abe9874b8497ab41e0ff75fcb410 Mon Sep 17 00:00:00 2001 From: Vaadasch Date: Sat, 6 Jun 2020 15:46:43 +0200 Subject: [PATCH 50/79] Update byratecountry.php Add "cc.code" in the "GROUP BY" clause. Error in PGSQL if absent. Add ORDER BY country / product_type / vatrate --- htdocs/compta/stats/byratecountry.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/stats/byratecountry.php b/htdocs/compta/stats/byratecountry.php index acd58f90217..1e2890f57fa 100644 --- a/htdocs/compta/stats/byratecountry.php +++ b/htdocs/compta/stats/byratecountry.php @@ -275,7 +275,9 @@ if ($modecompta == 'CREANCES-DETTES') { $sql .= " AND f.type IN (0,1,2,3,5)"; } $sql .= " AND f.entity IN (".getEntity('invoice', 0).")"; - $sql .= " GROUP BY fd.tva_tx,fd.product_type, cc.label "; + $sql .= " GROUP BY fd.tva_tx,fd.product_type, cc.label, cc.code "; + $sql .= " ORDER BY country, product_type, vatrate"; + dol_syslog("htdocs/compta/tva/index.php sql=".$sql, LOG_DEBUG); $resql = $db->query($sql); @@ -356,7 +358,8 @@ if ($modecompta == 'CREANCES-DETTES') { $sql .= " AND ff.type IN (0,1,2,3,5)"; } $sql2 .= " AND ff.entity IN (".getEntity("facture_fourn", 0).")"; - $sql2 .= " GROUP BY ffd.tva_tx, ffd.product_type, cc.label"; + $sql2 .= " GROUP BY ffd.tva_tx, ffd.product_type, cc.label, cc.code "; + $sql2 .= " ORDER BY country, product_type, vatrate"; //print $sql2; dol_syslog("htdocs/compta/tva/index.php sql=".$sql, LOG_DEBUG); From bd12972d7b1519ab6bccf986c9217152d6045829 Mon Sep 17 00:00:00 2001 From: Marc Guenneugues Date: Sat, 6 Jun 2020 11:39:49 +0200 Subject: [PATCH 51/79] replenish : select expedition quantities only from opened orders when using virtual stocks --- htdocs/product/stock/replenish.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 358ca742361..5f3ac1fd187 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -377,8 +377,11 @@ if ($usevirtualstock) $sqlExpeditionsCli = "(SELECT ".$db->ifsql("SUM(ed2.qty) IS NULL", "0", "SUM(ed2.qty)")." as qty"; // We need the ifsql because if result is 0 for product p.rowid, we must return 0 and not NULL $sqlExpeditionsCli .= " FROM ".MAIN_DB_PREFIX."expedition as e2,"; $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."expeditiondet as ed2,"; + $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."commande as c2,"; $sqlExpeditionsCli .= " ".MAIN_DB_PREFIX."commandedet as cd2"; $sqlExpeditionsCli .= " WHERE ed2.fk_expedition = e2.rowid AND cd2.rowid = ed2.fk_origin_line AND e2.entity IN (".getEntity('expedition').")"; + $sqlExpeditionsCli .= " AND cd2.fk_commande = c2.rowid"; + $sqlExpeditionsCli .= " AND c2.fk_statut IN (1,2)"; $sqlExpeditionsCli .= " AND cd2.fk_product = p.rowid"; $sqlExpeditionsCli .= " AND e2.fk_statut IN (1,2))"; } else { From 180a0a45572b038f4234ac336752d8ffb50a8b56 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 18:30:46 +0200 Subject: [PATCH 52/79] Info for debug --- htdocs/compta/facture/class/facture.class.php | 5 +++-- htdocs/install/mysql/migration/repair.sql | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 1558b6cbfab..12d60b067fa 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1584,7 +1584,8 @@ class Facture extends CommonInvoice } /** - * Fetch previous and next situations invoices + * Fetch previous and next situations invoices. + * Return all previous and next invoices (both standard and credit notes). * * @return void */ @@ -1595,7 +1596,7 @@ class Facture extends CommonInvoice $this->tab_previous_situation_invoice = array(); $this->tab_next_situation_invoice = array(); - $sql = 'SELECT rowid, situation_counter FROM '.MAIN_DB_PREFIX.'facture WHERE rowid <> '.$this->id.' AND entity = '.$conf->entity.' AND situation_cycle_ref = '.(int) $this->situation_cycle_ref.' ORDER BY situation_counter ASC'; + $sql = 'SELECT rowid, type, situation_cycle_ref, situation_counter FROM '.MAIN_DB_PREFIX.'facture WHERE rowid <> '.$this->id.' AND entity = '.$conf->entity.' AND situation_cycle_ref = '.(int) $this->situation_cycle_ref.' ORDER BY situation_counter ASC'; dol_syslog(get_class($this).'::fetchPreviousNextSituationInvoice ', LOG_DEBUG); $result = $this->db->query($sql); diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index fe0eaff767a..86c37198347 100755 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -476,7 +476,7 @@ UPDATE llx_accounting_bookkeeping set date_creation = tms where date_creation IS -- Test inconsistency of data into situation invoices: If it differs, it may be the total_ht that is wrong and situation_percent that is good. --- select f.rowid, f.type, qty, subprice, situation_percent, total_ht, total_ttc, total_tva, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc, (situation_percent / 100 * subprice * qty * (1 - (fd.remise_percent / 100))) +-- select f.rowid, f.type, fd.qty, fd.subprice, fd.situation_percent, fd.total_ht, fd.total_ttc, fd.total_tva, fd.multicurrency_total_ht, fd.multicurrency_total_tva, fd.multicurrency_total_ttc, (situation_percent / 100 * subprice * qty * (1 - (fd.remise_percent / 100))) -- from llx_facturedet as fd, llx_facture as f where fd.fk_facture = f.rowid AND (total_ht - situation_percent / 100 * subprice * qty * (1 - (fd.remise_percent / 100))) > 0.01 and f.type = 5; From 4020d9736206f97ed880fb4737623da5bc87f561 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 18:36:58 +0200 Subject: [PATCH 53/79] FIX Can create a credit note on situation invoice if previous is also credit note --- htdocs/compta/facture/card.php | 63 +++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index b97d22631a1..a134afba603 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -990,6 +990,11 @@ if (empty($reshook)) } $id = $object->create($user); + // NOTE: Pb with situation invoice + // NOTE: fields total on situation invoice are stored as cumulative values on total of lines (bad) but delta on invoice total + // NOTE: fields total on credit note are stored as delta both on total of lines and on invoice total (good) + // NOTE: fields situation_percent on situation invoice are stored as cumulative values on lines (bad) + // NOTE: fields situation_percent on credit note are stored as delta on lines (good) if (GETPOST('invoiceAvoirWithLines', 'int')==1 && $id>0) { if (!empty($facture_source->lines)) @@ -1010,36 +1015,38 @@ if (empty($reshook)) } - - - if($facture_source->type == Facture::TYPE_SITUATION) + if ($facture_source->type == Facture::TYPE_SITUATION) { $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id - $line->fk_prev_id = $line->id; // Credit note line need to be linked to the situation invoice it is create from + $line->fk_prev_id = $line->id; // The new line of the new credit note we are creating must be linked to the situation invoice line it is created from - if(!empty($facture_source->tab_previous_situation_invoice)) + if (!empty($facture_source->tab_previous_situation_invoice)) { - // search the last invoice in cycle - $lineIndex = count($facture_source->tab_previous_situation_invoice) - 1; + // search the last standard invoice in cycle and the possible credit note between this last and facture_source + // TODO Move this out of loop of $facture_source->lines + $tab_jumped_credit_notes = array(); + $lineIndex = count($facture_source->tab_previous_situation_invoice) - 1; $searchPreviousInvoice = true; - while( $searchPreviousInvoice ) + while ($searchPreviousInvoice) { - if($facture_source->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1) + if ($facture_source->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1) { $searchPreviousInvoice=false; // find, exit; break; } else { + if ($facture_source->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_CREDIT_NOTE) { + $tab_jumped_credit_notes[$lineIndex] = $facture_source->tab_previous_situation_invoice[$lineIndex]->id; + } $lineIndex--; // go to previous invoice in cycle } } - $maxPrevSituationPercent = 0; - foreach($facture_source->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine) + foreach ($facture_source->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine) { - if($prevLine->id == $source_fk_prev_id) + if ($prevLine->id == $source_fk_prev_id) { $maxPrevSituationPercent = max($maxPrevSituationPercent, $prevLine->situation_percent); @@ -1059,6 +1066,36 @@ if (empty($reshook)) // prorata $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent; + + //print 'New line based on invoice id '.$facture_source->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'
    '; + + // If there is some credit note between last situation invoice and invoice used for credit note generation (note: credit notes are stored as delta) + $maxPrevSituationPercent = 0; + foreach ($tab_jumped_credit_notes as $index => $creditnoteid) { + foreach ($facture_source->tab_previous_situation_invoice[$index]->lines as $prevLine) + { + if ($prevLine->fk_prev_id == $source_fk_prev_id) + { + $maxPrevSituationPercent = $prevLine->situation_percent; + + $line->total_ht -= $prevLine->total_ht; + $line->total_tva -= $prevLine->total_tva; + $line->total_ttc -= $prevLine->total_ttc; + $line->total_localtax1 -= $prevLine->total_localtax1; + $line->total_localtax2 -= $prevLine->total_localtax2; + + $line->multicurrency_subprice -= $prevLine->multicurrency_subprice; + $line->multicurrency_total_ht -= $prevLine->multicurrency_total_ht; + $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva; + $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc; + } + } + } + + // prorata + $line->situation_percent += $maxPrevSituationPercent; + + //print 'New line based on invoice id '.$facture_source->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'
    '; } } @@ -1078,7 +1115,7 @@ if (empty($reshook)) $line->multicurrency_total_tva = -$line->multicurrency_total_tva; $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc; - $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked + $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount already linked $object->lines[] = $line; // insert new line in current object From 2a1d54726711a296394774bbea4dff7c5543f749 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 18:44:37 +0200 Subject: [PATCH 54/79] Celan dead code --- htdocs/core/lib/files.lib.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 494540b14d7..47d16d4fe3f 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2986,20 +2986,11 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, exit; } - /*$perm = GETPOST('perm', 'aZ09'); - $subperm = GETPOST('subperm', 'aZ09'); - if ($perm || $subperm) - { - if (($perm && !$subperm && $fuser->rights->$modulepart->$perm) || ($perm && $subperm && $fuser->rights->$modulepart->$perm->$subperm)) $accessallowed = 1; - } - else - {*/ // Check fuser->rights->modulepart->myobject->read and fuser->rights->modulepart->read $partsofdirinoriginalfile = explode('/', $original_file); $partofdirinoriginalfile = $partsofdirinoriginalfile[0]; if ($partofdirinoriginalfile && ($fuser->rights->$modulepart->$partofdirinoriginalfile->{$lire} || $fuser->rights->$modulepart->$partofdirinoriginalfile->{$read})) $accessallowed = 1; if ($fuser->rights->$modulepart->{$lire} || $fuser->rights->$modulepart->{$read}) $accessallowed = 1; - //} $original_file = $conf->$modulepart->dir_output.'/'.$original_file; } From 81c80b254ea6d43ba280fed993a901391a20b542 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 19:25:25 +0200 Subject: [PATCH 55/79] Fix lang property on database menu entry was not propagated --- htdocs/core/class/menu.class.php | 4 ++-- htdocs/core/class/menubase.class.php | 1 + htdocs/core/menus/standard/eldy.lib.php | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/menu.class.php b/htdocs/core/class/menu.class.php index 040cb4a3552..60bf6474031 100644 --- a/htdocs/core/class/menu.class.php +++ b/htdocs/core/class/menu.class.php @@ -52,7 +52,7 @@ class Menu * Add a menu entry into this->liste (at end) * * @param string $url Url to follow on click (does not include DOL_URL_ROOT) - * @param string $titre Label of menu to add + * @param string $titre Label of menu to add. The value must already be translated. * @param integer $level Level of menu to add * @param int $enabled Menu active or not (0=Not active, 1=Active, 2=Active but grey) * @param string $target Target link @@ -75,7 +75,7 @@ class Menu * * @param int $idafter Array key after which inserting new entry * @param string $url Url to follow on click - * @param string $titre Label of menu to add + * @param string $titre Label of menu to add. The value must already be translated. * @param integer $level Level of menu to add * @param int $enabled Menu active or not * @param string $target Target link diff --git a/htdocs/core/class/menubase.class.php b/htdocs/core/class/menubase.class.php index 72ff932bfa6..b73492d41fb 100644 --- a/htdocs/core/class/menubase.class.php +++ b/htdocs/core/class/menubase.class.php @@ -725,6 +725,7 @@ class Menubase $tabMenu[$b]['mainmenu'] = $menu['mainmenu']; $tabMenu[$b]['leftmenu'] = $menu['leftmenu']; $tabMenu[$b]['perms'] = $perms; + $tabMenu[$b]['langs'] = $menu['langs']; $tabMenu[$b]['enabled'] = $enabled; $tabMenu[$b]['type'] = $menu['type']; //$tabMenu[$b]['langs'] = $menu['langs']; diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 661eded1b33..cc47218e2db 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -35,7 +35,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/menubase.class.php'; * @param DoliDB $db Database handler * @param string $atarget Target (Example: '' or '_top') * @param int $type_user 0=Menu for backoffice, 1=Menu for front office - * @param array $tabMenu If array with menu entries already loaded, we put this array here (in most cases, it's empty) + * @param array $tabMenu If array with menu entries already loaded, we put this array here (in most cases, it's empty). For eldy menu, it contains menu entries loaded from database. * @param Menu $menu Object Menu to return back list of menu entries * @param int $noout 1=Disable output (Initialise &$menu only). * @param string $mode 'top', 'topnb', 'left', 'jmobile' @@ -49,6 +49,7 @@ function print_eldy_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout = $mainmenu = (empty($_SESSION["mainmenu"]) ? '' : $_SESSION["mainmenu"]); $leftmenu = (empty($_SESSION["leftmenu"]) ? '' : $_SESSION["leftmenu"]); + $id = 'mainmenu'; $listofmodulesforexternal = explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL); From 09047dc19c9e73f2899828b682cdede17ab71704 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 19:26:37 +0200 Subject: [PATCH 56/79] Doc --- htdocs/core/class/menubase.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/core/class/menubase.class.php b/htdocs/core/class/menubase.class.php index b73492d41fb..a6d774090aa 100644 --- a/htdocs/core/class/menubase.class.php +++ b/htdocs/core/class/menubase.class.php @@ -725,10 +725,9 @@ class Menubase $tabMenu[$b]['mainmenu'] = $menu['mainmenu']; $tabMenu[$b]['leftmenu'] = $menu['leftmenu']; $tabMenu[$b]['perms'] = $perms; - $tabMenu[$b]['langs'] = $menu['langs']; + $tabMenu[$b]['langs'] = $menu['langs']; // Note that this should not be used, lang file should be already loaded. $tabMenu[$b]['enabled'] = $enabled; $tabMenu[$b]['type'] = $menu['type']; - //$tabMenu[$b]['langs'] = $menu['langs']; $tabMenu[$b]['fk_mainmenu'] = $menu['fk_mainmenu']; $tabMenu[$b]['fk_leftmenu'] = $menu['fk_leftmenu']; $tabMenu[$b]['position'] = (int) $menu['position']; From 9f8a3916c22d286a56f33e862aea215acb0e51f9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 19:37:42 +0200 Subject: [PATCH 57/79] FIX #14051 #14052 --- .../modulebuilder/template/core/modules/modMyModule.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 3deba218b59..10cdfa54001 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -269,7 +269,7 @@ class modMyModule extends DolibarrModules $this->menu[$r++] = array( 'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 'type'=>'top', // This is a Top menu entry - 'titre'=>'MyModule', + 'titre'=>'ModuleMyModuleName', 'mainmenu'=>'mymodule', 'leftmenu'=>'', 'url'=>'/mymodule/mymoduleindex.php', From 7ce7905d31422a233192c6826398da80b08d8c99 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 23:03:58 +0200 Subject: [PATCH 58/79] Fix check for mrp --- htdocs/core/lib/security.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 6749f32ffbe..c12882b032e 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -474,7 +474,7 @@ function checkUserAccessToObject($user, $featuresarray, $objectid = 0, $tableand if ($feature == 'project') $feature = 'projet'; if ($feature == 'task') $feature = 'projet_task'; - $check = array('adherent', 'banque', 'bom', 'don', 'user', 'usergroup', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday'); // Test on entity only (Objects with no link to company) + $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday'); // Test on entity only (Objects with no link to company) $checksoc = array('societe'); // Test for societe object $checkother = array('contact', 'agenda'); // Test on entity and link to third party. Allowed if link is empty (Ex: contacts...). $checkproject = array('projet', 'project'); // Test for project object From f7563818acfeb1a8b61f42a40f702c0ab73efa48 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 7 Jun 2020 23:12:56 +0200 Subject: [PATCH 59/79] css --- htdocs/theme/eldy/global.inc.php | 2 +- htdocs/website/index.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index d8c3cc81b5c..4f16c52800c 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -4313,7 +4313,7 @@ span[phptag] { } .websitebar .button, .websitebar .buttonDelete { - padding: 2px 5px 3px 5px !important; + padding: 4px 5px 4px 5px !important; margin: 2px 4px 2px 4px !important; line-height: normal; background: #f5f5f5 !important; diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 5c0505d9da7..3b541a40588 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2630,11 +2630,11 @@ if (!GETPOST('hide_websitemenu')) //print ''; if (empty($conf->global->WEBSITE_EDITINLINE)) { - print ''.img_picto($langs->trans("EditInLineOnOff", $langs->transnoentitiesnoconv("Off")), 'switch_off', '', false, 0, 0, '', 'nomarginleft').''; + print ''.img_picto($langs->trans("EditInLineOnOff", $langs->transnoentitiesnoconv("Off")), 'switch_off', '', false, 0, 0, '', 'nomarginleft').''; } else { - print ''.img_picto($langs->trans("EditInLineOnOff", $langs->transnoentitiesnoconv("On")), 'switch_on', '', false, 0, 0, '', 'nomarginleft').''; + print ''.img_picto($langs->trans("EditInLineOnOff", $langs->transnoentitiesnoconv("On")), 'switch_on', '', false, 0, 0, '', 'nomarginleft').''; } } @@ -2643,11 +2643,11 @@ if (!GETPOST('hide_websitemenu')) print $langs->trans("ShowSubcontainers"); if (empty($conf->global->WEBSITE_SUBCONTAINERSINLINE)) { - print ''.img_picto($langs->trans("ShowSubContainersOnOff", $langs->transnoentitiesnoconv("Off")), 'switch_off', '', false, 0, 0, '', 'nomarginleft').''; + print ''.img_picto($langs->trans("ShowSubContainersOnOff", $langs->transnoentitiesnoconv("Off")), 'switch_off', '', false, 0, 0, '', 'nomarginleft').''; } else { - print ''.img_picto($langs->trans("ShowSubContainersOnOff", $langs->transnoentitiesnoconv("On")), 'switch_on', '', false, 0, 0, '', 'nomarginleft').''; + print ''.img_picto($langs->trans("ShowSubContainersOnOff", $langs->transnoentitiesnoconv("On")), 'switch_on', '', false, 0, 0, '', 'nomarginleft').''; } /*}*/ print ''; From c386f4b2e3762a721cd70773f9cfb1a82805c04f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 8 Jun 2020 11:43:20 +0200 Subject: [PATCH 60/79] Maxi debug of direct debit order --- htdocs/compta/bank/class/account.class.php | 1 - htdocs/compta/facture/prelevement.php | 44 +++++-- htdocs/compta/prelevement/bons.php | 45 +++---- htdocs/compta/prelevement/card.php | 23 +++- .../class/bonprelevement.class.php | 5 +- .../class/ligneprelevement.class.php | 12 +- htdocs/compta/prelevement/create.php | 44 +++++-- htdocs/compta/prelevement/demandes.php | 8 +- htdocs/compta/prelevement/factures.php | 10 +- htdocs/compta/prelevement/line.php | 63 ++++++---- htdocs/compta/prelevement/list.php | 110 +++++++++++------- htdocs/compta/prelevement/rejets.php | 54 ++++++--- htdocs/compta/prelevement/stats.php | 34 +++++- htdocs/langs/en_US/main.lang | 2 + htdocs/langs/en_US/withdrawals.lang | 26 +++-- htdocs/societe/paymentmodes.php | 11 +- 16 files changed, 334 insertions(+), 158 deletions(-) diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 80e52110d8c..ca6a2e8d589 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -333,7 +333,6 @@ class Account extends CommonObject public function __toString() { $string = ''; - foreach ($this->getFieldsToShow() as $val) { if ($val == 'BankCode') { $string .= $this->code_banque.' '; diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 74de1c640d4..984c29d75ed 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -33,6 +33,7 @@ require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php'; require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php'; if (!$user->rights->facture->lire) accessforbidden(); @@ -44,6 +45,8 @@ $ref = GETPOST('ref', 'alpha'); $socid = GETPOST('socid', 'int'); $action = GETPOST('action', 'alpha'); +$type = GETPOST('type', 'aZ09'); + $fieldid = (!empty($ref) ? 'ref' : 'rowid'); if ($user->socid) $socid = $user->socid; $result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid); @@ -397,7 +400,13 @@ if ($object->id > 0) print '
    '.$langs->trans("RIB").''; - print $object->thirdparty->display_rib(); + + $bac = new CompanyBankAccount($db); + $bac->fetch(0, $object->thirdparty->id); + + print $bac->iban.(($bac->iban && $bac->bic) ? ' / ' : '').$bac->bic; + if ($bac->verif() <= 0) print img_warning('Error on default bank number for IBAN : '.$bac->error_message); + print '
    '; @@ -493,7 +502,11 @@ if ($object->id > 0) $sql .= " , pfd.date_traite as date_traite"; $sql .= " , pfd.amount"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_facture_demande as pfd"; - $sql .= " WHERE fk_facture = ".$object->id; + if ($type == 'bank-transfer') { + $sql .= " WHERE fk_facture_fourn = ".$object->id; + } else { + $sql .= " WHERE fk_facture = ".$object->id; + } $sql .= " AND pfd.traite = 0"; $sql .= " ORDER BY pfd.date_demande DESC"; @@ -508,11 +521,15 @@ if ($object->id > 0) dol_print_error($db); } - // For wich amount ? + // For which amount ? $sql = "SELECT SUM(pfd.amount) as amount"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_facture_demande as pfd"; - $sql .= " WHERE fk_facture = ".$object->id; + if ($type == 'bank-transfer') { + $sql .= " WHERE fk_facture_fourn = ".$object->id; + } else { + $sql .= " WHERE fk_facture = ".$object->id; + } $sql .= " AND pfd.traite = 0"; $result_sql = $db->query($sql); @@ -543,10 +560,11 @@ if ($object->id > 0) $remaintopaylesspendingdebit = $resteapayer - $pending; print '
    '; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print '
    '; } @@ -593,13 +611,17 @@ if ($object->id > 0) print ' '; print ''; - $sql = "SELECT pfd.rowid, pfd.traite, pfd.date_demande as date_demande"; - $sql .= " , pfd.date_traite as date_traite, pfd.amount,"; + $sql = "SELECT pfd.rowid, pfd.traite, pfd.date_demande as date_demande,"; + $sql .= " pfd.date_traite as date_traite, pfd.amount,"; $sql .= " u.rowid as user_id, u.lastname, u.firstname, u.login"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_facture_demande as pfd"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on pfd.fk_user_demande = u.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."prelevement_bons as pb ON pb.rowid = pfd.fk_prelevement_bons"; - $sql .= " WHERE fk_facture = ".$object->id; + if ($type == 'bank-transfer') { + $sql .= " WHERE fk_facture_fourn = ".$object->id; + } else { + $sql .= " WHERE fk_facture = ".$object->id; + } $sql .= " AND pfd.traite = 0"; $sql .= " ORDER BY pfd.date_demande DESC"; @@ -649,7 +671,11 @@ if ($object->id > 0) $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_facture_demande as pfd"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on pfd.fk_user_demande = u.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."prelevement_bons as pb ON pb.rowid = pfd.fk_prelevement_bons"; - $sql .= " WHERE fk_facture = ".$object->id; + if ($type == 'bank-transfer') { + $sql .= " WHERE fk_facture_fourn = ".$object->id; + } else { + $sql .= " WHERE fk_facture = ".$object->id; + } $sql .= " AND pfd.traite = 1"; $sql .= " ORDER BY pfd.date_demande DESC"; diff --git a/htdocs/compta/prelevement/bons.php b/htdocs/compta/prelevement/bons.php index ea768638552..5a1ce4e7024 100644 --- a/htdocs/compta/prelevement/bons.php +++ b/htdocs/compta/prelevement/bons.php @@ -174,35 +174,40 @@ if ($result) $directdebitorder = new BonPrelevement($db); - while ($i < min($num, $limit)) - { - $obj = $db->fetch_object($result); + if ($num) { + while ($i < min($num, $limit)) + { + $obj = $db->fetch_object($result); - $directdebitorder->id = $obj->rowid; - $directdebitorder->ref = $obj->ref; - $directdebitorder->datec = $obj->datec; - $directdebitorder->amount = $obj->amount; - $directdebitorder->statut = $obj->statut; + $directdebitorder->id = $obj->rowid; + $directdebitorder->ref = $obj->ref; + $directdebitorder->datec = $obj->datec; + $directdebitorder->amount = $obj->amount; + $directdebitorder->statut = $obj->statut; - print ''; + print ''; - print ''; - print $directdebitorder->getNomUrl(1); - print "\n"; + print ''; + print $directdebitorder->getNomUrl(1); + print "\n"; - print ''.dol_print_date($db->jdate($obj->datec), 'day')."\n"; + print ''.dol_print_date($db->jdate($obj->datec), 'day')."\n"; - print ''.price($obj->amount)."\n"; + print ''.price($obj->amount)."\n"; - print ''; - print $bon->LibStatut($obj->statut, 3); - print ''; + print ''; + print $bon->LibStatut($obj->statut, 3); + print ''; - print ''."\n"; + print ''."\n"; - print "\n"; - $i++; + print "\n"; + $i++; + } + } else { + print ''.$langs->trans("None").''; } + print ""; print '
    '; diff --git a/htdocs/compta/prelevement/card.php b/htdocs/compta/prelevement/card.php index d630f65edd7..3ad145e2f56 100644 --- a/htdocs/compta/prelevement/card.php +++ b/htdocs/compta/prelevement/card.php @@ -292,7 +292,7 @@ if ($id > 0 || $ref) print $form->selectDate('', '', '', '', '', "infocredit", 1, 1); print ''; print ''; - print '
    '.$langs->trans("ThisWillAlsoAddPaymentOnInvoice"); + print '
    '.$langs->trans("ThisWillAlsoAddPaymentOnInvoice").'
    '; print '
    '; print ''; print '
    '; @@ -405,7 +405,7 @@ if ($id > 0 || $ref) print ''.price($obj->amount)."\n"; - print ''; + print ''; if ($obj->statut == 3) { @@ -413,7 +413,24 @@ if ($id > 0 || $ref) } else { - print " "; + if ($object->statut == BonPrelevement::STATUS_CREDITED) + { + if ($obj->statut == 2) { + if ($user->rights->prelevement->bons->credit) + { + //print ''.$langs->trans("StandingOrderReject").''; + print ''.$langs->trans("StandingOrderReject").''; + } + else + { + //print ''.$langs->trans("StandingOrderReject").''; + } + } + } + else + { + //print ''.$langs->trans("StandingOrderReject").''; + } } print ''; diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index a923f66c699..0997fb593cb 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -288,7 +288,7 @@ class BonPrelevement extends CommonObject $sql .= ", p.method_trans, p.fk_user_trans"; $sql .= ", p.date_credit as date_credit"; $sql .= ", p.fk_user_credit"; - $sql .= ", p.statut"; + $sql .= ", p.statut as status"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; $sql .= " WHERE p.entity IN (".getEntity('invoice').")"; if ($rowid > 0) $sql .= " AND p.rowid = ".$rowid; @@ -315,7 +315,8 @@ class BonPrelevement extends CommonObject $this->date_credit = $this->db->jdate($obj->date_credit); $this->user_credit = $obj->fk_user_credit; - $this->statut = $obj->statut; + $this->status = $obj->status; + $this->statut = $obj->status; // For backward compatibility $this->fetched = 1; diff --git a/htdocs/compta/prelevement/class/ligneprelevement.class.php b/htdocs/compta/prelevement/class/ligneprelevement.class.php index 88b612554df..d2dd9f3470f 100644 --- a/htdocs/compta/prelevement/class/ligneprelevement.class.php +++ b/htdocs/compta/prelevement/class/ligneprelevement.class.php @@ -66,14 +66,14 @@ class LignePrelevement /** * Recupere l'objet prelevement * - * @param int $rowid id de la facture a recuperer - * @return integer + * @param int $rowid Id de la facture a recuperer + * @return integer <0 if KO, >=0 if OK */ public function fetch($rowid) { global $conf; - $result = 0; + $error = 0; $sql = "SELECT pl.rowid, pl.amount, p.ref, p.rowid as bon_rowid"; $sql .= ", pl.statut, pl.fk_soc"; @@ -99,7 +99,7 @@ class LignePrelevement } else { - $result++; + $error++; dol_syslog("LignePrelevement::Fetch rowid=$rowid numrows=0"); } @@ -107,12 +107,12 @@ class LignePrelevement } else { - $result++; + $error++; dol_syslog("LignePrelevement::Fetch rowid=$rowid"); dol_syslog($this->db->error()); } - return $result; + return $error; } /** diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index d94864e8358..6da71e7bf43 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -99,6 +99,9 @@ if (empty($reshook)) else { setEventMessages($langs->trans("DirectDebitOrderCreated", $bprev->getNomUrl(1)), null); + + header("Location: ".DOL_URL_ROOT.'/compta/prelevement/card.php?id='.$bprev->id); + exit; } } } @@ -141,8 +144,8 @@ print load_fiche_titre($title); dol_fiche_head(); -$nb = $bprev->NbFactureAPrelever(); -$pricetowithdraw = $bprev->SommeAPrelever(); +$nb = $bprev->nbOfInvoiceToPay($type); +$pricetowithdraw = $bprev->SommeAPrelever($type); if ($nb < 0) { dol_print_error($bprev->error); @@ -178,19 +181,34 @@ if ($nb) { if ($pricetowithdraw) { print $langs->trans('ExecutionDate').' '; print $form->selectDate(); + if ($mysoc->isInEEC()) { + $title = $langs->trans("CreateForSepa"); + print ''; - print ''; + print ''; } else { - print ''.$langs->trans("CreateAll")."\n"; + $title = $langs->trans("CreateAll"); + if ($type == 'bank-transfer') { + $title = $langs->trans("CreateFileForPaymentByBankTransfer"); + } + print ''.$title."\n"; } } else { if ($mysoc->isInEEC()) { - print ''.$langs->trans("CreateForSepaFRST")."\n"; - print ''.$langs->trans("CreateForSepaRCUR")."\n"; + $title = $langs->trans("CreateForSepaFRST"); + if ($type == 'bank-transfer') { + $title = $langs->trans("CreateSepaFileForPaymentByBankTransfer"); + } + print ''.$title."\n"; + + if ($type != 'bank-transfer') { + $title = $langs->trans("CreateForSepaRCUR"); + print ''.$title."\n"; + } } else { @@ -236,9 +254,9 @@ if (empty($conf->global->WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS)) $sql .= " AND f.total_ttc > 0"; $sql .= " AND pfd.traite = 0"; if ($type == 'bank-transfer') { - $sql .= " AND pfd.fk_facture = f.rowid"; -} else { $sql .= " AND pfd.fk_facture_fourn = f.rowid"; +} else { + $sql .= " AND pfd.fk_facture = f.rowid"; } if ($socid > 0) $sql .= " AND f.fk_soc = ".$socid; @@ -299,23 +317,29 @@ if ($resql) { $obj = $db->fetch_object($resql); + $bac->fetch(0, $obj->socid); + print ''; + + // Ref invoice print ''; $invoicestatic->id = $obj->rowid; $invoicestatic->ref = $obj->ref; print $invoicestatic->getNomUrl(1, 'withdraw'); print ''; + // Thirdparty print ''; $thirdpartystatic->fetch($obj->socid); print $thirdpartystatic->getNomUrl(1, 'ban'); print ''; + // RIB print ''; - print $thirdpartystatic->display_rib(); - $bac->fetch(0, $obj->socid); + print $bac->iban.(($bac->iban && $bac->bic) ? ' / ' : '').$bac->bic; if ($bac->verif() <= 0) print img_warning('Error on default bank number for IBAN : '.$bac->error_message); print ''; + // RUM print ''; print $thirdpartystatic->display_rib('rum'); diff --git a/htdocs/compta/prelevement/demandes.php b/htdocs/compta/prelevement/demandes.php index 720aac24be5..b92df4e446c 100644 --- a/htdocs/compta/prelevement/demandes.php +++ b/htdocs/compta/prelevement/demandes.php @@ -199,14 +199,14 @@ print ''; print ''; print_liste_field_titre("Bill", $_SERVER["PHP_SELF"]); print_liste_field_titre("Company", $_SERVER["PHP_SELF"]); -print_liste_field_titre("Amount", $_SERVER["PHP_SELF"], "", "", $param, 'class="right"'); -print_liste_field_titre("DateRequest", $_SERVER["PHP_SELF"], "", "", $param, 'class="center"'); +print_liste_field_titre("Amount", $_SERVER["PHP_SELF"], "", "", $param, '', '', '', 'right '); +print_liste_field_titre("DateRequest", $_SERVER["PHP_SELF"], "", "", $param, '', '', '', 'center '); print_liste_field_titre(''); print ''; print ''; -print ''; -print ''; +print ''; +print ''; print ''; print ''; // Action column diff --git a/htdocs/compta/prelevement/factures.php b/htdocs/compta/prelevement/factures.php index 06c20a2b04f..556f40de9be 100644 --- a/htdocs/compta/prelevement/factures.php +++ b/htdocs/compta/prelevement/factures.php @@ -38,7 +38,7 @@ $langs->loadLangs(array('banks', 'categories', 'companies', 'withdrawals', 'bill if ($user->socid > 0) accessforbidden(); // Get supervariables -$prev_id = GETPOST('id', 'int'); +$id = GETPOST('id', 'int'); $socid = GETPOST('socid', 'int'); $ref = GETPOST('ref', 'alpha'); @@ -68,9 +68,9 @@ $thirdpartytmp = new Societe($db); llxHeader('', $langs->trans("WithdrawalsReceipts")); -if ($prev_id > 0 || $ref) +if ($id > 0 || $ref) { - if ($object->fetch($prev_id, $ref) >= 0) + if ($object->fetch($id, $ref) >= 0) { $head = prelevement_prepare_head($object); dol_fiche_head($head, 'invoices', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); @@ -183,7 +183,7 @@ if ($result) $num = $db->num_rows($result); $i = 0; - $param = "&id=".$prev_id; + $param = "&id=".$id; // Lines of title fields print ''; @@ -195,7 +195,7 @@ if ($result) print ''; print ''; print ''; - print ''; + print ''; $massactionbutton = ''; diff --git a/htdocs/compta/prelevement/line.php b/htdocs/compta/prelevement/line.php index c225b9d47f3..d6124113321 100644 --- a/htdocs/compta/prelevement/line.php +++ b/htdocs/compta/prelevement/line.php @@ -124,11 +124,18 @@ if ($action == 'confirm_rejet') $invoicestatic = new Facture($db); -llxHeader('', $langs->trans("StandingOrder")); +$title = $langs->trans("WithdrawalsLine"); +if ($type == 'bank-transfer') { + $title = $langs->trans("CreditTransferLine"); +} + +llxHeader('', $title); + +$head = array(); $h = 0; $head[$h][0] = DOL_URL_ROOT.'/compta/prelevement/line.php?id='.$id; -$head[$h][1] = $langs->trans("StandingOrder"); +$head[$h][1] = $title; $hselected = $h; $h++; @@ -136,20 +143,24 @@ if ($id) { $lipre = new LignePrelevement($db); - if ($lipre->fetch($id) == 0) + if ($lipre->fetch($id) >= 0) { $bon = new BonPrelevement($db); $bon->fetch($lipre->bon_rowid); - dol_fiche_head($head, $hselected, $langs->trans("StandingOrder")); + dol_fiche_head($head, $hselected, $title); - print '
    '; + print '
    '; - print ''; + + print ''; - print ''; - print ''; - print ''; + + print ''; + print ''; + print ''; if ($lipre->statut == 3) { @@ -157,8 +168,8 @@ if ($id) $resf = $rej->fetch($lipre->id); if ($resf == 0) { - print ''; - print ''; + print ''; - print ''; + print ''; } else { - print ''; + print ''; } } @@ -197,7 +208,7 @@ if ($id) print ''; print ''; print ''; - print '
    '.$langs->trans("WithdrawalsReceipts").''; + print '
    '.$langs->trans("Ref").''; + print $id.'
    '.$langs->trans("WithdrawalsReceipts").''; print $bon->getNomUrl(1).'
    '.$langs->trans("Date").''.dol_print_date($bon->datec, 'day').'
    '.$langs->trans("Amount").''.price($lipre->amount).'
    '.$langs->trans("Status").''.$lipre->LibStatut($lipre->statut, 1).'
    '.$langs->trans("Date").''.dol_print_date($bon->datec, 'day').'
    '.$langs->trans("Amount").''.price($lipre->amount).'
    '.$langs->trans("Status").''.$lipre->LibStatut($lipre->statut, 1).'
    '.$langs->trans("RefusedReason").''.$rej->motif.'
    '.$langs->trans("RefusedData").''; + print '
    '.$langs->trans("RefusedReason").''.$rej->motif.'
    '.$langs->trans("RefusedData").''; if ($rej->date_rejet == 0) { /* Historique pour certaines install */ @@ -169,11 +180,11 @@ if ($id) print dol_print_date($rej->date_rejet, 'day'); } print '
    '.$langs->trans("RefusedInvoicing").''.$rej->invoicing.'
    '.$langs->trans("RefusedInvoicing").''.$rej->invoicing.'
    '.$resf.'
    '.$resf.'
    '; + print '
    '; print ''; print ''; @@ -217,13 +228,13 @@ if ($id) //Reason print ''; print ''; //Facturer print ''; print ''; print '
    '.$langs->trans("WithdrawalRefused").'
    '.$langs->trans("RefusedReason").''; - print $form->selectarray("motif", $rej->motifs); + print $form->selectarray("motif", $rej->motifs, GETPOSTISSET('motif') ? GETPOST('motif', 'int') : ''); print '
    '.$langs->trans("RefusedInvoicing").''; - print $form->selectarray("facturer", $rej->facturer); + print $form->selectarray("facturer", $rej->facturer, GETPOSTISSET('facturer') ? GETPOST('facturer', 'int') : ''); print '

    '; @@ -242,20 +253,22 @@ if ($id) if ($action == '') { - if ($bon->statut == 2 && $lipre->statut == 2) + if ($bon->statut == BonPrelevement::STATUS_CREDITED) { - if ($user->rights->prelevement->bons->credit) - { - print "id\">".$langs->trans("StandingOrderReject").""; - } - else - { - print "trans("NotAllowed")."\">".$langs->trans("StandingOrderReject").""; + if ($lipre->statut == 2) { + if ($user->rights->prelevement->bons->credit) + { + print ''.$langs->trans("StandingOrderReject").''; + } + else + { + print ''.$langs->trans("StandingOrderReject").''; + } } } else { - print "trans("NotPossibleForThisStatusOfWithdrawReceiptORLine")."\">".$langs->trans("StandingOrderReject").""; + print ''.$langs->trans("StandingOrderReject").''; } } diff --git a/htdocs/compta/prelevement/list.php b/htdocs/compta/prelevement/list.php index e97a492de9b..72960c9c15b 100644 --- a/htdocs/compta/prelevement/list.php +++ b/htdocs/compta/prelevement/list.php @@ -21,7 +21,7 @@ /** * \file htdocs/compta/prelevement/list.php * \ingroup prelevement - * \brief Page liste des prelevements + * \brief Page list of direct debit orders or credit transfers orders */ require '../../main.inc.php'; @@ -96,23 +96,35 @@ $form = new Form($db); llxHeader('', $langs->trans("WithdrawalsLines")); $sql = "SELECT p.rowid, p.ref, p.statut as status, p.datec"; -$sql .= " ,f.rowid as facid, f.ref as invoiceref, f.total_ttc"; +$sql .= " , f.rowid as facid, f.ref as invoiceref, f.total_ttc"; $sql .= " , s.rowid as socid, s.nom as name, s.code_client, s.email"; $sql .= " , pl.amount, pl.statut as statut_ligne, pl.rowid as rowid_ligne"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; $sql .= " , ".MAIN_DB_PREFIX."prelevement_lignes as pl"; $sql .= " , ".MAIN_DB_PREFIX."prelevement_facture as pf"; -$sql .= " , ".MAIN_DB_PREFIX."facture as f"; +if ($type == 'bank-transfer') { + $sql .= " , ".MAIN_DB_PREFIX."facture_fourn as f"; +} else { + $sql .= " , ".MAIN_DB_PREFIX."facture as f"; +} $sql .= " , ".MAIN_DB_PREFIX."societe as s"; $sql .= " WHERE pl.fk_prelevement_bons = p.rowid"; $sql .= " AND pf.fk_prelevement_lignes = pl.rowid"; -$sql .= " AND pf.fk_facture = f.rowid"; +if ($type == 'bank-transfer') { + $sql .= " AND pf.fk_facture_fourn = f.rowid"; +} else { + $sql .= " AND pf.fk_facture = f.rowid"; +} $sql .= " AND f.fk_soc = s.rowid"; $sql .= " AND f.entity IN (".getEntity('invoice').")"; if ($socid) $sql .= " AND s.rowid = ".$socid; if ($search_line) $sql .= " AND pl.rowid = '".$db->escape($search_line)."'"; if ($search_bon) $sql .= natural_search("p.ref", $search_bon); -if ($search_code) $sql .= natural_search("s.code_client", $search_code); +if ($type == 'bank-transfer') { + if ($search_code) $sql .= natural_search("s.code_fourn", $search_code); +} else { + if ($search_code) $sql .= natural_search("s.code_client", $search_code); +} if ($search_company) $sql .= natural_search("s.nom", $search_company); $sql .= $db->order($sortfield, $sortorder); @@ -152,7 +164,11 @@ if ($result) print ''; print ''; - print_barre_liste($langs->trans("WithdrawalsLines"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'generic', 0, '', '', $limit, 0, 0, 1); + $title = $langs->trans("WithdrawalsLines"); + if ($type == 'bank-transfer') { + $title = $langs->trans("CreditTransferLines"); + } + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'generic', 0, '', '', $limit, 0, 0, 1); $moreforfilter = ''; @@ -173,9 +189,14 @@ if ($result) print ''; print ''; + $columntitle= "WithdrawalsReceipts"; + if ($type == 'bank-transfer') { + $columntitle= "BankTransferReceipts"; + } + print ''; + print_liste_field_titre($columntitle, $_SERVER["PHP_SELF"], "p.ref", '', $param, '', $sortfield, $sortorder); print_liste_field_titre("Line", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder); - print_liste_field_titre("WithdrawalsReceipts", $_SERVER["PHP_SELF"], "p.ref", '', $param, '', $sortfield, $sortorder); print_liste_field_titre("Bill", $_SERVER["PHP_SELF"], "f.ref", '', $param, '', $sortfield, $sortorder); print_liste_field_titre("Company", $_SERVER["PHP_SELF"], "s.nom", '', $param, '', $sortfield, $sortorder); print_liste_field_titre("CustomerCode", $_SERVER["PHP_SELF"], "s.code_client", '', $param, '', $sortfield, $sortorder, 'center '); @@ -184,53 +205,58 @@ if ($result) print_liste_field_titre(''); print "\n"; - while ($i < min($num, $limit)) - { - $obj = $db->fetch_object($result); + if ($num) { + while ($i < min($num, $limit)) + { + $obj = $db->fetch_object($result); - $bon->ref = $obj->ref; - $bon->statut = $obj->status; + $bon->id = $obj->rowid; + $bon->ref = $obj->ref; + $bon->statut = $obj->status; - $company->id = $obj->socid; - $company->name = $obj->name; - $company->email = $obj->email; - $company->code_client = $obj->code_client; + $company->id = $obj->socid; + $company->name = $obj->name; + $company->email = $obj->email; + $company->code_client = $obj->code_client; - print ''; + print ''; - print ''; - print $line->LibStatut($obj->statut_ligne, 2); - print " "; - print ''; - print substr('000000'.$obj->rowid_ligne, -6); - print ''; + print ''; + print $bon->getNomUrl(1); + print "\n"; - print ''; - print $bon->getNomUrl(1); - print "\n"; + print ''; + print $line->LibStatut($obj->statut_ligne, 2); + print " "; + print ''; + print substr('000000'.$obj->rowid_ligne, -6); + print ''; - print ''; - print ''; - print img_object($langs->trans("ShowBill"), "bill"); - print ' '.$obj->invoiceref."\n"; - print ''; - print ''; + print ''; + print ''; + print img_object($langs->trans("ShowBill"), "bill"); + print ' '.$obj->invoiceref."\n"; + print ''; + print ''; - print ''; - print $company->getNomUrl(1); - print "\n"; + print ''; + print $company->getNomUrl(1); + print "\n"; - print ''.$obj->code_client."\n"; + print ''.$obj->code_client."\n"; - print ''.dol_print_date($db->jdate($obj->datec), 'day')."\n"; + print ''.dol_print_date($db->jdate($obj->datec), 'day')."\n"; - print ''.price($obj->amount)."\n"; + print ''.price($obj->amount)."\n"; - print ' '; + print ' '; - print "\n"; - $i++; - } + print "\n"; + $i++; + } + } else { + print ''.$langs->trans("None").''; + } print ""; print '
    '; diff --git a/htdocs/compta/prelevement/rejets.php b/htdocs/compta/prelevement/rejets.php index 7dfd5e558d9..81f17dc784b 100644 --- a/htdocs/compta/prelevement/rejets.php +++ b/htdocs/compta/prelevement/rejets.php @@ -55,7 +55,12 @@ $pagenext = $page + 1; * View */ -llxHeader('', $langs->trans("WithdrawsRefused")); +$title = $langs->trans("WithdrawsRefused"); +if ($type == 'bank-transfer') { + $title = $langs->trans("CreditTransfersRefused"); +} + +llxHeader('', $title); if ($sortorder == "") $sortorder = "DESC"; if ($sortfield == "") $sortfield = "p.datec"; @@ -80,9 +85,14 @@ $sql .= " WHERE pr.fk_prelevement_lignes = pl.rowid"; $sql .= " AND pl.fk_prelevement_bons = p.rowid"; $sql .= " AND pl.fk_soc = s.rowid"; $sql .= " AND p.entity = ".$conf->entity; +if ($type == 'bank-transfer') { + $sql .= " AND p.type = 'bank-transfer'"; +} else { + $sql .= " AND p.type = 'debit-order'"; +} if ($socid) $sql .= " AND s.rowid = ".$socid; -$sql .= " ".$db->order($sortfield, $sortorder); -$sql .= " ".$db->plimit($conf->liste_limit + 1, $offset); +$sql .= $db->order($sortfield, $sortorder); +$sql .= $db->plimit($limit + 1, $offset); $result = $db->query($sql); if ($result) @@ -90,33 +100,39 @@ if ($result) $num = $db->num_rows($result); $i = 0; - print_barre_liste($langs->trans("WithdrawsRefused"), $page, $_SERVER["PHP_SELF"], $urladd, $sortfield, $sortorder, '', $num); + $param = ''; + + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num); print"\n\n"; print ''; print ''; - print_liste_field_titre("Line", $_SERVER["PHP_SELF"], "p.ref", '', $urladd); - print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "s.nom", '', $urladd); - print_liste_field_titre("Reason", $_SERVER["PHP_SELF"], "pr.motif", "", $urladd); + print_liste_field_titre("Line", $_SERVER["PHP_SELF"], "p.ref", '', $param); + print_liste_field_titre("ThirdParty", $_SERVER["PHP_SELF"], "s.nom", '', $param); + print_liste_field_titre("Reason", $_SERVER["PHP_SELF"], "pr.motif", "", $param); print "\n"; - $total = 0; + if ($num) { + while ($i < min($num, $limit)) + { + $obj = $db->fetch_object($result); - while ($i < min($num, $conf->liste_limit)) - { - $obj = $db->fetch_object($result); + print ''; - print '"; - print substr('000000'.$obj->rowid, -6).""; + print '\n"; - print '\n"; + print ''; - print ''; - print "\n"; + print "\n"; - $i++; + $i++; + } + } else { + print ''; } print "
    '; - print $line->LibStatut($obj->statut, 2).' '; - print ''; + print ''; + print $line->LibStatut($obj->statut, 2).' '; + print ''; + print substr('000000'.$obj->rowid, -6)."'.$obj->nom."'.stripslashes($obj->nom)."'.$rej->motifs[$obj->motif].''.$rej->motifs[$obj->motif].'
    '.$langs->trans("None").'
    "; diff --git a/htdocs/compta/prelevement/stats.php b/htdocs/compta/prelevement/stats.php index 416bb68128b..87fd3917a56 100644 --- a/htdocs/compta/prelevement/stats.php +++ b/htdocs/compta/prelevement/stats.php @@ -43,15 +43,25 @@ $type = GETPOST('type', 'aZ09'); * View */ -llxHeader('', $langs->trans("WithdrawStatistics")); +$title = $langs->trans("WithdrawStatistics"); +if ($type == 'bank-transfer') { + $title = $langs->trans("CreditTransferStatistics"); +} -print load_fiche_titre($langs->trans("Statistics")); +llxHeader('', $title); + +print load_fiche_titre($title); // Define total and nbtotal $sql = "SELECT sum(pl.amount), count(pl.amount)"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_lignes as pl"; $sql .= ", ".MAIN_DB_PREFIX."prelevement_bons as pb"; $sql .= " WHERE pl.fk_prelevement_bons = pb.rowid"; +if ($type == 'bank-transfer') { + $sql .= " AND pb.type = 'bank-transfer'"; +} else { + $sql .= " AND pb.type = 'debit-order'"; +} $sql .= " AND pb.entity = ".$conf->entity; $resql = $db->query($sql); if ($resql) @@ -73,7 +83,7 @@ if ($resql) */ print '
    '; -print load_fiche_titre($langs->trans("WithdrawStatistics"), '', ''); +print load_fiche_titre($langs->trans("ByStatus"), '', ''); $ligne = new LignePrelevement($db); @@ -82,6 +92,11 @@ $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_lignes as pl"; $sql .= ", ".MAIN_DB_PREFIX."prelevement_bons as pb"; $sql .= " WHERE pl.fk_prelevement_bons = pb.rowid"; $sql .= " AND pb.entity = ".$conf->entity; +if ($type == 'bank-transfer') { + $sql .= " AND pb.type = 'bank-transfer'"; +} else { + $sql .= " AND pb.type = 'debit-order'"; +} $sql .= " GROUP BY pl.statut"; $resql = $db->query($sql); @@ -139,7 +154,7 @@ else */ print '
    '; -print load_fiche_titre($langs->trans("WithdrawRejectStatistics"), '', ''); +print load_fiche_titre($langs->trans("Rejects"), '', ''); // Define total and nbtotal @@ -149,6 +164,11 @@ $sql .= ", ".MAIN_DB_PREFIX."prelevement_bons as pb"; $sql .= " WHERE pl.fk_prelevement_bons = pb.rowid"; $sql .= " AND pb.entity = ".$conf->entity; $sql .= " AND pl.statut = 3"; +if ($type == 'bank-transfer') { + $sql .= " AND pb.type = 'bank-transfer'"; +} else { + $sql .= " AND pb.type = 'debit-order'"; +} $resql = $db->query($sql); if ($resql) { @@ -166,6 +186,7 @@ if ($resql) /* * Stats sur les rejets */ + $sql = "SELECT sum(pl.amount), count(pl.amount) as cc, pr.motif"; $sql .= " FROM ".MAIN_DB_PREFIX."prelevement_lignes as pl"; $sql .= ", ".MAIN_DB_PREFIX."prelevement_bons as pb"; @@ -174,6 +195,11 @@ $sql .= " WHERE pl.fk_prelevement_bons = pb.rowid"; $sql .= " AND pb.entity = ".$conf->entity; $sql .= " AND pl.statut = 3"; $sql .= " AND pr.fk_prelevement_lignes = pl.rowid"; +if ($type == 'bank-transfer') { + $sql .= " AND pb.type = 'bank-transfer'"; +} else { + $sql .= " AND pb.type = 'debit-order'"; +} $sql .= " GROUP BY pr.motif"; $sql .= " ORDER BY cc DESC"; diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 105d5c83bec..dd250316bc7 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1035,3 +1035,5 @@ DeleteFileText=Do you really want delete this file? ShowOtherLanguages=Show other languages SwitchInEditModeToAddTranslation=Switch in edit mode to add translations for this language NotUsedForThisCustomer=Not used for this customer +AmountMustBePositive=Amount must be positive +ByStatus=By status \ No newline at end of file diff --git a/htdocs/langs/en_US/withdrawals.lang b/htdocs/langs/en_US/withdrawals.lang index a7a55c69c53..87afa3246b4 100644 --- a/htdocs/langs/en_US/withdrawals.lang +++ b/htdocs/langs/en_US/withdrawals.lang @@ -1,6 +1,6 @@ # Dolibarr language file - Source file is en_US - withdrawals -CustomersStandingOrdersArea=Direct debit payment orders area -SuppliersStandingOrdersArea=Direct credit payment orders area +CustomersStandingOrdersArea=Payments by Direct debit orders +SuppliersStandingOrdersArea=Payments by Credit transfer StandingOrdersPayment=Direct debit payment orders StandingOrderPayment=Direct debit payment order NewStandingOrder=New direct debit order @@ -10,26 +10,34 @@ PaymentByBankTransferReceipts=Credit transfer orders PaymentByBankTransferLines=Credit transfer order lines WithdrawalsReceipts=Direct debit orders WithdrawalReceipt=Direct debit order +BankTransferReceipts=Credit transfer receipts +BankTransferReceipt=Credit transfer receipt LatestBankTransferReceipts=Latest %s credit transfer orders LastWithdrawalReceipts=Latest %s direct debit files +WithdrawalsLine=Direct debit order line +CreditTransferLine=Credit transfer line WithdrawalsLines=Direct debit order lines -RequestStandingOrderToTreat=Request for direct debit payment order to process -RequestStandingOrderTreated=Request for direct debit payment order processed +CreditTransferLines=Credit transfer lines +RequestStandingOrderToTreat=Requests for direct debit payment order to process +RequestStandingOrderTreated=Requests for direct debit payment order processed +RequestPaymentsByBankTransferToTreat=Requests for credit transfer to process +RequestPaymentsByBankTransferTreated=Requests for credit transfer processed NotPossibleForThisStatusOfWithdrawReceiptORLine=Not yet possible. Withdraw status must be set to 'credited' before declaring reject on specific lines. NbOfInvoiceToWithdraw=No. of qualified customer invoices with waiting direct debit order NbOfInvoiceToWithdrawWithInfo=No. of customer invoice with direct debit payment orders having defined bank account information NbOfInvoiceToPayByBankTransfer=No. of qualified supplier invoices waiting for a payment by credit transfer SupplierInvoiceWaitingWithdraw=Vendor invoice waiting for payment by credit transfer InvoiceWaitingWithdraw=Invoice waiting for direct debit +InvoiceWaitingPaymentByBankTransfer=Invoice waiting for credit transfer AmountToWithdraw=Amount to withdraw -WithdrawsRefused=Direct debit refused NoInvoiceToWithdraw=No customer invoice with open 'Direct debit requests' is waiting. Go on tab '%s' on invoice card to make a request. NoSupplierInvoiceToWithdraw=No supplier invoice with open 'Direct credit requests' is waiting. Go on tab '%s' on invoice card to make a request. ResponsibleUser=User Responsible WithdrawalsSetup=Direct debit payment setup CreditTransferSetup=Crebit transfer setup WithdrawStatistics=Direct debit payment statistics -WithdrawRejectStatistics=Direct debit payment reject statistics +CreditTransferStatistics=Credit transfer statistics +Rejects=Rejects LastWithdrawalReceipt=Latest %s direct debit receipts MakeWithdrawRequest=Make a direct debit payment request WithdrawRequestsDone=%s direct debit payment requests recorded @@ -42,7 +50,9 @@ TransMetod=Transmission method Send=Send Lines=Lines StandingOrderReject=Issue a rejection +WithdrawsRefused=Direct debit refused WithdrawalRefused=Withdrawal refused +CreditTransfersRefused=Credit transfers refused WithdrawalRefusedConfirm=Are you sure you want to enter a withdrawal rejection for society RefusedData=Date of rejection RefusedReason=Reason for rejection @@ -66,6 +76,8 @@ StatusMotif8=Other reason CreateForSepaFRST=Create direct debit file (SEPA FRST) CreateForSepaRCUR=Create direct debit file (SEPA RCUR) CreateAll=Create direct debit file (all) +CreateFileForPaymentByBankTransfer=Create credit transfer (all) +CreateSepaFileForPaymentByBankTransfer=Create credit transfer file (SEPA) CreateGuichet=Only office CreateBanque=Only bank OrderWaiting=Waiting for treatment @@ -83,7 +95,7 @@ IfInvoiceNeedOnWithdrawPaymentWontBeClosed=However, if invoice has at least one DoStandingOrdersBeforePayments=This tab allows you to request a direct debit payment order. Once done, go into menu Bank->Direct Debit orders to manage the direct debit payment order. When payment order is closed, payment on invoice will be automatically recorded, and invoice closed if remainder to pay is null. WithdrawalFile=Withdrawal file SetToStatusSent=Set to status "File Sent" -ThisWillAlsoAddPaymentOnInvoice=This will also record payments to invoices and will classify them as "Paid" if remain to pay is null +ThisWillAlsoAddPaymentOnInvoice=This will also record payments on invoices and will classify them as "Paid" if remain to pay is null StatisticsByLineStatus=Statistics by status of lines RUM=UMR DateRUM=Mandate signature date diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index e0636932cc2..a57fda0403c 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -1660,6 +1660,7 @@ if ($socid && $action == 'edit' && $user->rights->societe->creer) // Show fields of bank account foreach ($companybankaccount->getFieldsToShow(1) as $val) { $require = false; + $tooltip = ''; if ($val == 'BankCode') { $name = 'code_banque'; $size = 8; @@ -1681,14 +1682,22 @@ if ($socid && $action == 'edit' && $user->rights->societe->creer) $size = 30; $content = $companybankaccount->iban; if ($companybankaccount->needIBAN()) $require = true; + $tooltip = $langs->trans("Example").':
    LT12 1000 0111 0100 1000
    FR14 2004 1010 0505 0001 3M02 606
    LU28 0019 4006 4475 0000
    DE89 3704 0044 0532 0130 00'; } elseif ($val == 'BIC') { $name = 'bic'; $size = 12; $content = $companybankaccount->bic; if ($companybankaccount->needIBAN()) $require = true; + $tooltip = $langs->trans("Example").': LIABLT2XXXX'; } - print ''.$langs->trans($val).''; + print ''; + if ($tooltip) { + print $form->textwithpicto($langs->trans($val), $tooltip, 4, 'help', '', 0, 3, $name); + } else { + print $langs->trans($val); + } + print ''; print ''; print ''; } From 70bdd595488163faa004031ed606057b86c1a3c7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 8 Jun 2020 11:52:43 +0200 Subject: [PATCH 61/79] Fix trans --- htdocs/compta/prelevement/create.php | 8 +++++++- htdocs/langs/en_US/withdrawals.lang | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/prelevement/create.php b/htdocs/compta/prelevement/create.php index 6da71e7bf43..db9ad26f31d 100644 --- a/htdocs/compta/prelevement/create.php +++ b/htdocs/compta/prelevement/create.php @@ -222,7 +222,13 @@ if ($nb) { } else { - print 'transnoentitiesnoconv("StandingOrders"))).'">'.$langs->trans("CreateAll")."\n"; + $titlefortab = $langs->transnoentitiesnoconv("StandingOrders"); + $title = $langs->trans("CreateAll"); + if ($type == 'bank-transfer') { + $titlefortab = $langs->transnoentitiesnoconv("PaymentByBankTransfers"); + $title = $langs->trans("CreateFileForPaymentByBankTransfer"); + } + print ''.$title."\n"; } print "\n"; diff --git a/htdocs/langs/en_US/withdrawals.lang b/htdocs/langs/en_US/withdrawals.lang index 87afa3246b4..5217d54d39a 100644 --- a/htdocs/langs/en_US/withdrawals.lang +++ b/htdocs/langs/en_US/withdrawals.lang @@ -30,7 +30,7 @@ SupplierInvoiceWaitingWithdraw=Vendor invoice waiting for payment by credit tran InvoiceWaitingWithdraw=Invoice waiting for direct debit InvoiceWaitingPaymentByBankTransfer=Invoice waiting for credit transfer AmountToWithdraw=Amount to withdraw -NoInvoiceToWithdraw=No customer invoice with open 'Direct debit requests' is waiting. Go on tab '%s' on invoice card to make a request. +NoInvoiceToWithdraw=No invoice open for '%s' is waiting. Go on tab '%s' on invoice card to make a request. NoSupplierInvoiceToWithdraw=No supplier invoice with open 'Direct credit requests' is waiting. Go on tab '%s' on invoice card to make a request. ResponsibleUser=User Responsible WithdrawalsSetup=Direct debit payment setup From 2e06ce306a0448376c5c6d55468403db3a7f7c5c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 8 Jun 2020 15:03:10 +0200 Subject: [PATCH 62/79] Tooltip --- htdocs/langs/en_US/website.lang | 1 + htdocs/website/index.php | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 6109f3ca879..04338f38e6e 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -16,6 +16,7 @@ WEBSITE_ROBOT=Robot file (robots.txt) WEBSITE_HTACCESS=Website .htaccess file WEBSITE_MANIFEST_JSON=Website manifest.json file WEBSITE_README=README.md file +WEBSITE_KEYWORDSDesc=Use a comma to separate values EnterHereLicenseInformation=Enter here meta data or license information to fille a README.md file. if you distribute your website as a template, the file will be included into the temptate package. HtmlHeaderPage=HTML header (specific to this page only) PageNameAliasHelp=Name or alias of the page.
    This alias is also used to forge a SEO URL when website is ran from a Virtual host of a Web server (like Apacke, Nginx, ...). Use the button "%s" to edit this alias. diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 3b541a40588..d67a04deb06 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -3297,7 +3297,7 @@ if ($action == 'editmeta' || $action == 'createcontainer') if (GETPOST('WEBSITE_IMAGE', 'alpha')) $pageimage = GETPOST('WEBSITE_IMAGE', 'alpha'); if (GETPOST('WEBSITE_KEYWORDS', 'alpha')) $pagekeywords = GETPOST('WEBSITE_KEYWORDS', 'alpha'); if (GETPOST('WEBSITE_LANG', 'aZ09')) $pagelang = GETPOST('WEBSITE_LANG', 'aZ09'); - if (GETPOST('htmlheader', 'none')) $pagehtmlheader = GETPOST('htmlheader', 'none'); + if (GETPOST('htmlheader', 'none')) $pagehtmlheader = GETPOST('htmlheader', 'none'); // Type of container print ''; @@ -3342,8 +3342,10 @@ if ($action == 'editmeta' || $action == 'createcontainer') print ''; print ''; + // Keywords print ''; - print $langs->trans('WEBSITE_KEYWORDS'); + $htmlhelp = $langs->trans("WEBSITE_KEYWORDSDesc"); + print $form->textwithpicto($langs->trans('WEBSITE_KEYWORDS'), $htmlhelp, 1, 'help', '', 0, 2, 'keywordtooltip'); print ''; print ''; print ''; From fd8f8ff4e191178b1849387a866e12941a2f7fd9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 8 Jun 2020 15:12:07 +0200 Subject: [PATCH 63/79] Error message --- htdocs/core/class/commonobject.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 9dba821c012..29e0de2ba23 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -3049,7 +3049,11 @@ abstract class CommonObject //print 'Line '.$i.' rowid='.$obj->rowid.' vat_rate='.$obj->vatrate.' total_ht='.$obj->total_ht.' total_tva='.$obj->total_tva.' total_ttc='.$obj->total_ttc.' total_ht_by_vats='.$total_ht_by_vats[$obj->vatrate].' total_tva_by_vats='.$total_tva_by_vats[$obj->vatrate].' (new calculation = '.$tmpvat.') total_ttc_by_vats='.$total_ttc_by_vats[$obj->vatrate].($diff?" => DIFF":"")."
    \n"; if ($diff) { - if (abs($diff) > 0.1) { dol_syslog('A rounding difference was detected into TOTAL but is too high to be corrected', LOG_WARNING); exit; } + if (abs($diff) > 0.1) { + dol_syslog('A rounding difference was detected into TOTAL but is too high to be corrected', LOG_WARNING); + dol_print_error('', 'A rounding difference was detected into TOTAL but is too high to be corrected'); + exit; + } $sqlfix = "UPDATE ".MAIN_DB_PREFIX.$this->table_element_line." SET ".$fieldtva." = ".($obj->total_tva - $diff).", total_ttc = ".($obj->total_ttc - $diff)." WHERE rowid = ".$obj->rowid; dol_syslog('We found a difference of '.$diff.' for line rowid = '.$obj->rowid.". We fix the total_vat and total_ttc of line by running sqlfix = ".$sqlfix); $resqlfix = $this->db->query($sqlfix); From 366f458b39edec2949ccb68c71bc8e75e98f607d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 8 Jun 2020 15:20:01 +0200 Subject: [PATCH 64/79] Show more info to help fix corrupted data --- htdocs/core/class/commonobject.class.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 29e0de2ba23..0f055d457ed 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -3050,8 +3050,9 @@ abstract class CommonObject if ($diff) { if (abs($diff) > 0.1) { - dol_syslog('A rounding difference was detected into TOTAL but is too high to be corrected', LOG_WARNING); - dol_print_error('', 'A rounding difference was detected into TOTAL but is too high to be corrected'); + $errmsg = 'A rounding difference was detected into TOTAL but is too high to be corrected. Some data in your line may be corrupted. Try to edit each line manually.'; + dol_syslog($errmsg, LOG_WARNING); + dol_print_error('', $errmsg); exit; } $sqlfix = "UPDATE ".MAIN_DB_PREFIX.$this->table_element_line." SET ".$fieldtva." = ".($obj->total_tva - $diff).", total_ttc = ".($obj->total_ttc - $diff)." WHERE rowid = ".$obj->rowid; From cf976a2b98ab13405df470ec3cb0b1ffc0e563eb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 8 Jun 2020 17:00:58 +0200 Subject: [PATCH 65/79] Fix translation --- htdocs/langs/en_US/projects.lang | 1 + htdocs/projet/element.php | 27 ++++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index e145647baa4..1a35eda4b9c 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -265,3 +265,4 @@ NewInvoice=New invoice OneLinePerTask=One line per task OneLinePerPeriod=One line per period RefTaskParent=Ref. Parent Task +ProfitIsCalculatedWith=Profit is calculated using \ No newline at end of file diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index 23fa6551656..0b46d14a7fa 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -526,7 +526,7 @@ $listofreferent = array( */ ); -// Change rules for benefit calculation +// Change rules for profit/benefit calculation if (! empty($conf->global->PROJECT_ELEMENTS_FOR_PLUS_MARGIN)) { foreach($listofreferent as $key => $element) { if ($listofreferent[$key]['margin'] == 'add') { @@ -624,7 +624,28 @@ print load_fiche_titre($langs->trans("Profit"), '', 'title_accountancy'); print ''; print ''; -print ''; +print ''; print ''; print ''; print ''; @@ -640,7 +661,7 @@ foreach ($listofreferent as $key => $value) $qualified = $value['test']; $margin = $value['margin']; $project_field = $value['project_field']; - if ($qualified && isset($margin)) // If this element must be included into profit calculation ($margin is 'minus' or 'plus') + if ($qualified && isset($margin)) // If this element must be included into profit calculation ($margin is 'minus' or 'add') { $element = new $classname($db); From 233c7e53f109f8142ea22c732bbcbab377c46dc3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 8 Jun 2020 20:31:09 +0200 Subject: [PATCH 66/79] Debug v12 --- htdocs/langs/en_US/stocks.lang | 1 + htdocs/product/stock/product.php | 2 ++ htdocs/product/stock/replenish.php | 7 +++++-- htdocs/theme/eldy/dropdown.inc.php | 4 +--- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 9856649b834..f62bf5d9cc5 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -123,6 +123,7 @@ WarehouseForStockDecrease=The warehouse %s will be used for stock decreas WarehouseForStockIncrease=The warehouse %s will be used for stock increase ForThisWarehouse=For this warehouse ReplenishmentStatusDesc=This is a list of all products with a stock lower than desired stock (or lower than alert value if checkbox "alert only" is checked). Using the checkbox, you can create purchase orders to fill the difference. +ReplenishmentStatusDescPerWarehouse=If you want a replenishment based on desired quantity defined per warehouse, you must add a filter on the warehouse. ReplenishmentOrdersDesc=This is a list of all open purchase orders including predefined products. Only open orders with predefined products, so orders that may affect stocks, are visible here. Replenishments=Replenishments NbOfProductBeforePeriod=Quantity of product %s in stock before selected period (< %s) diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index fcd08f8b662..89e99df4b1e 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -909,6 +909,7 @@ if (!$variants) { print "\n".''; print '
    '.$langs->trans("Element").''; +$tooltiponprofit = $langs->trans("ProfitIsCalculatedWith")."
    \n"; +$tooltiponprofitplus = $tooltiponprofitminus = ''; +foreach($listofreferent as $key => $value) +{ + $name = $langs->trans($value['name']); + $qualified = $value['test']; + $margin = $value['margin']; + if ($qualified && isset($margin)) // If this element must be included into profit calculation ($margin is 'minus' or 'add') + { + if ($margin == 'add') { + $tooltiponprofitplus.=' + '.$name."
    \n"; + } + if ($margin == 'minus') { + $tooltiponprofitminus.=' - '.$name."
    \n"; + } + } +} +$tooltiponprofit .= $tooltiponprofitplus; +$tooltiponprofit .= $tooltiponprofitminus; +print $form->textwithpicto($langs->trans("Element"), $tooltiponprofit); +print '
    '.$langs->trans("Number").''.$langs->trans("AmountHT").''.$langs->trans("AmountTTC").'
    '; print '
    '; + print ''; print ''; print ''; print '
    '; @@ -976,6 +977,7 @@ if (!$variants) { if (!empty($user->rights->produit->creer)) { print ''; + print ''; print ''; print ''; } diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 5f3ac1fd187..56b9dd4781f 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -99,6 +99,7 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + /* * Actions */ @@ -107,7 +108,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' { $sref = ''; $snom = ''; - $sal = ''; + $sall = ''; $salert = ''; $draftorder = ''; } @@ -304,7 +305,6 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entre $sqlalertstock = 'p.seuil_stock_alerte'; } - $sql = 'SELECT p.rowid, p.ref, p.label, p.description, p.price,'; $sql .= ' p.price_ttc, p.price_base_type,p.fk_product_type,'; $sql .= ' p.tms as datem, p.duration, p.tobuy,'; @@ -495,6 +495,9 @@ print load_fiche_titre($langs->trans('Replenishment'), '', 'stock'); dol_fiche_head($head, 'replenish', '', -1, ''); print ''.$langs->trans("ReplenishmentStatusDesc").'
    '."\n"; +if (empty($fk_warhouse) && !empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { + print ''.$langs->trans("ReplenishmentStatusDescPerWarehouse").''."
    \n"; +} if ($usevirtualstock == 1) { print $langs->trans("CurentSelectionMode").': '; diff --git a/htdocs/theme/eldy/dropdown.inc.php b/htdocs/theme/eldy/dropdown.inc.php index b22441f2445..2944dbe6c61 100644 --- a/htdocs/theme/eldy/dropdown.inc.php +++ b/htdocs/theme/eldy/dropdown.inc.php @@ -186,11 +186,9 @@ a.top-menu-dropdown-link { } .dropdown-menu > .user-header{ - background: rgb(); + background: var(--colorbackhmenu1); } - - .dropdown-menu .dropdown-header{ padding: 8px 8px 8px 8px; } From 063b3263ccc92ae57af852ae9ca871b0495630f8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 8 Jun 2020 23:12:45 +0200 Subject: [PATCH 67/79] Trans --- htdocs/mrp/mo_production.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php index 9f05283345a..5f687b0bf7b 100644 --- a/htdocs/mrp/mo_production.php +++ b/htdocs/mrp/mo_production.php @@ -654,7 +654,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (in_array($action, array('consumeorproduce', 'consumeandproduceall', 'addconsumeline'))) { - print ''; + print ''; print ''; print ''; print ''; @@ -666,7 +666,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea //$defaultstockmovementcode = GETPOST('inventorycode', 'alphanohtml') ? GETPOST('inventorycode', 'alphanohtml') : $object->ref.'_'.dol_print_date(dol_now(), 'dayhourlog'); $defaultstockmovementcode = GETPOST('inventorycode', 'alphanohtml') ? GETPOST('inventorycode', 'alphanohtml') : $langs->trans("ProductionForRef", $object->ref); - print '
    '; + print '
    '; print ''.$langs->trans("ConfirmProductionDesc", $langs->transnoentitiesnoconv("Confirm")).'
    '; print $langs->trans("MovementLabel").':   '; print $langs->trans("InventoryCode").':

    '; @@ -674,7 +674,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; print '   '; print ''; + print '

    '; print '
    '; + print '
    '; } } From 756ef0b583577c7595ff2c7c8ee960a766f32815 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 9 Jun 2020 21:43:42 +0200 Subject: [PATCH 68/79] Fix disallow < > into meta info Fix message page regenerated --- htdocs/core/lib/functions.lib.php | 2 +- htdocs/langs/en_US/website.lang | 3 +- htdocs/website/class/website.class.php | 4 +- htdocs/website/index.php | 61 +++++++++++++++----------- 4 files changed, 40 insertions(+), 30 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 4105682a06a..169d979cc8b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -601,7 +601,7 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null // '"' is dangerous because param in url can close the href= or src= and add javascript functions. // '../' is dangerous because it allows dir transversals $out = str_replace(array('"', '../'), '', trim($out)); - $out = dol_string_nohtmltag($out); + $out = dol_string_nohtmltag($out, 1); } break; case 'restricthtml': // Recommended for most html textarea diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 04338f38e6e..4f07b0ca9fb 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -130,4 +130,5 @@ PublicAuthorAlias=Public author alias AvailableLanguagesAreDefinedIntoWebsiteProperties=Available languages are defined into website properties ReplacementDoneInXPages=Replacement done in %s pages or containers RSSFeed=RSS Feed -RSSFeedDesc=You can get a RSS feed of latest articles with type 'blogpost' using this URL \ No newline at end of file +RSSFeedDesc=You can get a RSS feed of latest articles with type 'blogpost' using this URL +PagesRegenerated=%s page(s)/container(s) regenerated \ No newline at end of file diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 2d69131d469..03203d9eac7 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -1274,7 +1274,7 @@ class Website extends CommonObject * Rebuild all files of a containers of a website. TODO Add other files too. * Note: Files are already regenerated during importWebSite so this function is useless when importing a website. * - * @return int <0 if KO, >0 if OK + * @return int <0 if KO, >=0 if OK */ public function rebuildWebSiteFiles() { @@ -1344,7 +1344,7 @@ class Website extends CommonObject } else { - return 1; + return $num; } } diff --git a/htdocs/website/index.php b/htdocs/website/index.php index d67a04deb06..2a3b50df2f6 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -884,15 +884,15 @@ if ($action == 'addcontainer') } else { - $objectpage->title = GETPOST('WEBSITE_TITLE', 'alphanohtml'); + $objectpage->title = str_replace(array('<', '>'), '', GETPOST('WEBSITE_TITLE', 'alphanohtml')); $objectpage->type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'aZ09'); $objectpage->pageurl = GETPOST('WEBSITE_PAGENAME', 'alpha'); - $objectpage->aliasalt = GETPOST('WEBSITE_ALIASALT', 'alphanohtml'); - $objectpage->description = GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml'); + $objectpage->aliasalt = str_replace(array('<', '>'), '', GETPOST('WEBSITE_ALIASALT', 'alphanohtml')); + $objectpage->description = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml')); $objectpage->lang = GETPOST('WEBSITE_LANG', 'aZ09'); $objectpage->otherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma'); $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha'); - $objectpage->keywords = GETPOST('WEBSITE_KEYWORDS', 'alphanohtml'); + $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); $objectpage->htmlheader = GETPOST('htmlheader', 'none'); $objectpage->author_alias = GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml'); @@ -1561,22 +1561,31 @@ if ($action == 'updatemeta') $websitepagetemp = new WebsitePage($db); foreach ($arrayofaliastotest as $aliastotest) { - $result = $websitepagetemp->fetch(-1 * $objectpage->id, $object->id, $aliastotest); - if ($result < 0) - { + // Disallow alias name pageX (already used to save the page with id) + if (preg_match('/^page\d+/i', $aliastotest)) { $error++; $langs->load("errors"); - setEventMessages($websitepagetemp->error, $websitepagetemp->errors, 'errors'); - $action = 'editmeta'; - break; - } - if ($result > 0) - { - $error++; - $langs->load("errors"); - setEventMessages($langs->trans("ErrorAPageWithThisNameOrAliasAlreadyExists", $websitepagetemp->pageurl), null, 'errors'); + setEventMessages("Alias 'pageX' is not allowed", null, 'errors'); $action = 'editmeta'; break; + } else { + $result = $websitepagetemp->fetch(-1 * $objectpage->id, $object->id, $aliastotest); + if ($result < 0) + { + $error++; + $langs->load("errors"); + setEventMessages($websitepagetemp->error, $websitepagetemp->errors, 'errors'); + $action = 'editmeta'; + break; + } + if ($result > 0) + { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans("ErrorAPageWithThisNameOrAliasAlreadyExists", $websitepagetemp->pageurl), null, 'errors'); + $action = 'editmeta'; + break; + } } } } @@ -1585,15 +1594,15 @@ if ($action == 'updatemeta') { $objectpage->old_object = clone $objectpage; - $objectpage->title = GETPOST('WEBSITE_TITLE', 'alphanohtml'); - $objectpage->type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'alphanohtml'); + $objectpage->title = str_replace(array('<', '>'), '', GETPOST('WEBSITE_TITLE', 'alphanohtml')); + $objectpage->type_container = GETPOST('WEBSITE_TYPE_CONTAINER', 'aZ09'); $objectpage->pageurl = GETPOST('WEBSITE_PAGENAME', 'alpha'); - $objectpage->aliasalt = GETPOST('WEBSITE_ALIASALT', 'alpha'); + $objectpage->aliasalt = str_replace(array('<', '>'), '', GETPOST('WEBSITE_ALIASALT', 'alphanohtml')); $objectpage->lang = GETPOST('WEBSITE_LANG', 'aZ09'); $objectpage->otherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma'); - $objectpage->description = GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml'); + $objectpage->description = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml')); $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha'); - $objectpage->keywords = GETPOST('WEBSITE_KEYWORDS', 'alphanohtml'); + $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); $objectpage->htmlheader = trim(GETPOST('htmlheader', 'none')); $objectpage->fk_page = (GETPOST('pageidfortranslation', 'int') > 0 ? GETPOST('pageidfortranslation', 'int') : 0); $objectpage->author_alias = trim(GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml')); @@ -2023,7 +2032,7 @@ if ($action == 'regeneratesite') $result = $object->rebuildWebSiteFiles(); if ($result > 0) { - setEventMessages($langs->trans("PagesRegenerated"), null, 'mesgs'); + setEventMessages($langs->trans("PagesRegenerated", $result), null, 'mesgs'); $action = 'preview'; } else @@ -3290,12 +3299,12 @@ if ($action == 'editmeta' || $action == 'createcontainer') $pageauthoralias = ''; $pagestatus = 1; } - if (GETPOST('WEBSITE_TITLE', 'alpha')) $pagetitle = GETPOST('WEBSITE_TITLE', 'alpha'); + if (GETPOST('WEBSITE_TITLE', 'alpha')) $pagetitle = str_replace(array('<', '>'), '', GETPOST('WEBSITE_TITLE', 'alphanohtml')); if (GETPOST('WEBSITE_PAGENAME', 'alpha')) $pageurl = GETPOST('WEBSITE_PAGENAME', 'alpha'); - if (GETPOST('WEBSITE_ALIASALT', 'alpha')) $pagealiasalt = GETPOST('WEBSITE_ALIASALT', 'alpha'); - if (GETPOST('WEBSITE_DESCRIPTION', 'alpha')) $pagedescription = GETPOST('WEBSITE_DESCRIPTION', 'alpha'); + if (GETPOST('WEBSITE_ALIASALT', 'alpha')) $pagealiasalt = str_replace(array('<', '>'), '', GETPOST('WEBSITE_ALIASALT', 'alphanohtml')); + if (GETPOST('WEBSITE_DESCRIPTION', 'alpha')) $pagedescription = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml')); if (GETPOST('WEBSITE_IMAGE', 'alpha')) $pageimage = GETPOST('WEBSITE_IMAGE', 'alpha'); - if (GETPOST('WEBSITE_KEYWORDS', 'alpha')) $pagekeywords = GETPOST('WEBSITE_KEYWORDS', 'alpha'); + if (GETPOST('WEBSITE_KEYWORDS', 'alpha')) $pagekeywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); if (GETPOST('WEBSITE_LANG', 'aZ09')) $pagelang = GETPOST('WEBSITE_LANG', 'aZ09'); if (GETPOST('htmlheader', 'none')) $pagehtmlheader = GETPOST('htmlheader', 'none'); From a216c9b0d661599a70be494c9a4951357d0015f6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 9 Jun 2020 21:44:06 +0200 Subject: [PATCH 69/79] Add image --- doc/images/dolibarr_screenshot11_1024x768.jpg | Bin 0 -> 74017 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/images/dolibarr_screenshot11_1024x768.jpg diff --git a/doc/images/dolibarr_screenshot11_1024x768.jpg b/doc/images/dolibarr_screenshot11_1024x768.jpg new file mode 100644 index 0000000000000000000000000000000000000000..65c246353a7ee7a4f14db1d2ed9b96307926f49c GIT binary patch literal 74017 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 literal 0 HcmV?d00001 From 9bbdaffe9ddf09b95bbce53ab8df4d53e465a09f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Jun 2020 00:01:41 +0200 Subject: [PATCH 70/79] FIX Sharing buttons --- htdocs/core/lib/website.lib.php | 74 ++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index f3a4f738927..be3d1dea56d 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -732,45 +732,51 @@ function getSocialNetworkSharingLinks() { global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running inluded containers. - $fullurl = $website->alias.'/'.$websitepage->pageurl.'.php'; - $hashtags = trim(join(' #', array_map('trim', explode(',', $websitepage->keywords)))); - $out = ''."\n"; - $out .= '\n"; + } + else { + $out .= ''."\n"; + } $out .= ''."\n"; return $out; From 760fb4b0e3fbcc6ec28983a365a274b74452b727 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Jun 2020 00:34:00 +0200 Subject: [PATCH 71/79] Remove custom issues --- .github/ISSUE_TEMPLATE/custom.md | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/custom.md diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md deleted file mode 100644 index 48d5f81fa42..00000000000 --- a/.github/ISSUE_TEMPLATE/custom.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Custom issue template -about: Describe this issue template's purpose here. -title: '' -labels: '' -assignees: '' - ---- - - From 5794b1abea74dd5c972ef1c77d45c726a457cbb7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Jun 2020 12:35:39 +0200 Subject: [PATCH 72/79] Fix for use with text browser Conflicts: htdocs/main.inc.php --- htdocs/blockedlog/lib/blockedlog.lib.php | 2 +- htdocs/bom/lib/bom.lib.php | 4 ++-- htdocs/core/lib/admin.lib.php | 2 +- htdocs/core/lib/agenda.lib.php | 4 ++-- htdocs/core/lib/functions.lib.php | 6 +++-- htdocs/core/lib/usergroups.lib.php | 2 +- htdocs/core/tpl/login.tpl.php | 1 + htdocs/main.inc.php | 23 +++++++++---------- .../template/lib/mymodule_myobject.lib.php | 2 +- htdocs/product/stock/class/entrepot.class.php | 2 ++ htdocs/theme/eldy/badges.inc.php | 3 ++- htdocs/website/lib/websiteaccount.lib.php | 4 ++-- 12 files changed, 30 insertions(+), 25 deletions(-) diff --git a/htdocs/blockedlog/lib/blockedlog.lib.php b/htdocs/blockedlog/lib/blockedlog.lib.php index afb0323304e..11b85567a41 100644 --- a/htdocs/blockedlog/lib/blockedlog.lib.php +++ b/htdocs/blockedlog/lib/blockedlog.lib.php @@ -46,7 +46,7 @@ function blockedlogadmin_prepare_head() $b = new BlockedLog($db); if ($b->alreadyUsed()) { - $head[$h][1] .= '...'; + $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '...' : ''); } $head[$h][2] = 'fingerprints'; $h++; diff --git a/htdocs/bom/lib/bom.lib.php b/htdocs/bom/lib/bom.lib.php index 4d5f980de83..1eb5fc52a5b 100644 --- a/htdocs/bom/lib/bom.lib.php +++ b/htdocs/bom/lib/bom.lib.php @@ -90,7 +90,7 @@ function bomPrepareHead($object) if (!empty($object->note_public)) $nbNote++; $head[$h][0] = DOL_URL_ROOT.'/bom/bom_note.php?id='.$object->id; $head[$h][1] = $langs->trans('Notes'); - if ($nbNote > 0) $head[$h][1] .= ''.$nbNote.''; + if ($nbNote > 0) $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.$nbNote.'' : ''); $head[$h][2] = 'note'; $h++; } @@ -102,7 +102,7 @@ function bomPrepareHead($object) $nbLinks = Link::count($db, $object->element, $object->id); $head[$h][0] = DOL_URL_ROOT.'/bom/bom_document.php?id='.$object->id; $head[$h][1] = $langs->trans('Documents'); - if (($nbFiles + $nbLinks) > 0) $head[$h][1] .= ''.($nbFiles + $nbLinks).''; + if (($nbFiles + $nbLinks) > 0) $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.($nbFiles + $nbLinks).'' : ''); $head[$h][2] = 'document'; $h++; diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index b78c0478370..adb1201df1d 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -663,7 +663,7 @@ function security_prepare_head() $head[$h][0] = DOL_URL_ROOT."/admin/perms.php"; $head[$h][1] = $langs->trans("DefaultRights"); - if ($nbPerms > 0) $head[$h][1] .= ''.$nbPerms.''; + if ($nbPerms > 0) $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.$nbPerms.'' : ''); $head[$h][2] = 'default'; $h++; diff --git a/htdocs/core/lib/agenda.lib.php b/htdocs/core/lib/agenda.lib.php index 5d450aa4b04..6eff2772014 100644 --- a/htdocs/core/lib/agenda.lib.php +++ b/htdocs/core/lib/agenda.lib.php @@ -481,7 +481,7 @@ function actions_prepare_head($object) $listofresourcelinked = $resource->getElementResources($object->element, $object->id); $nbResources = (is_array($listofresourcelinked) ?count($listofresourcelinked) : 0); $head[$h][1] = $langs->trans("Resources"); - if ($nbResources > 0) $head[$h][1] .= ''.($nbResources).''; + if ($nbResources > 0) $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.($nbResources).'' : ''); $head[$h][2] = 'resources'; $h++; } @@ -494,7 +494,7 @@ function actions_prepare_head($object) $nbLinks = Link::count($db, $object->element, $object->id); $head[$h][0] = DOL_URL_ROOT.'/comm/action/document.php?id='.$object->id; $head[$h][1] = $langs->trans("Documents"); - if (($nbFiles + $nbLinks) > 0) $head[$h][1] .= ''.($nbFiles + $nbLinks).''; + if (($nbFiles + $nbLinks) > 0) $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.($nbFiles + $nbLinks).'' : ''); $head[$h][2] = 'documents'; $h++; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 169d979cc8b..9cecd9e3be6 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1216,7 +1216,7 @@ function dol_get_fiche_head($links = array(), $active = '', $title = '', $notab { $limittitle = 30; $out .= ''; - if ($picto) $out .= img_picto($title, ($pictoisfullpath ? '' : 'object_').$picto, '', $pictoisfullpath, 0, 0, '', 'imgTabTitle').' '; + if ($picto && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $out .= img_picto($title, ($pictoisfullpath ? '' : 'object_').$picto, '', $pictoisfullpath, 0, 0, '', 'imgTabTitle').' '; $out .= ''.dol_trunc($title, $limittitle).''; $out .= ''; } @@ -2246,6 +2246,8 @@ function dol_print_email($email, $cid = 0, $socid = 0, $addlink = 0, $max = 64, $newemail = $email; + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpicto) $withpicto = 0; + if (empty($email)) return ' '; if (!empty($addlink)) @@ -2279,7 +2281,7 @@ function dol_print_email($email, $cid = 0, $socid = 0, $addlink = 0, $max = 64, } //$rep = '
    '; - $rep = ($withpicto ?img_picto($langs->trans("EMail").' : '.$email, 'object_email.png').' ' : '').$newemail; + $rep = ($withpicto ? img_picto($langs->trans("EMail").' : '.$email, 'object_email.png').' ' : '').$newemail; //$rep .= '
    '; if ($hookmanager) { $parameters = array('cid' => $cid, 'socid' => $socid, 'addlink' => $addlink, 'picto' => $withpicto); diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index 9ac9383e516..0b07e96ab50 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -64,7 +64,7 @@ function user_prepare_head($object) if ($canreadperms) { $head[$h][0] = DOL_URL_ROOT.'/user/perms.php?id='.$object->id; - $head[$h][1] = $langs->trans("Rights").''.($object->nb_rights).''; + $head[$h][1] = $langs->trans("Rights").(empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.($object->nb_rights).'' : ''); $head[$h][2] = 'rights'; $h++; } diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php index 97bece99852..e10c311cf05 100644 --- a/htdocs/core/tpl/login.tpl.php +++ b/htdocs/core/tpl/login.tpl.php @@ -54,6 +54,7 @@ $titleofloginpage = $langs->trans('Login').' @ '.$titletruedolibarrversion; // $ $disablenofollow = 1; if (!preg_match('/'.constant('DOL_APPLICATION_TITLE').'/', $title)) $disablenofollow = 0; +if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $disablenofollow = 0; print top_htmlhead('', $titleofloginpage, 0, 0, $arrayofjs, array(), 0, $disablenofollow); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 679e565cf0e..cf53d994ece 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -257,6 +257,12 @@ if (isset($_SERVER["HTTP_USER_AGENT"])) if ($conf->browser->layout == 'phone') $conf->dol_no_mouse_hover = 1; } +// Set global MAIN_OPTIMIZEFORTEXTBROWSER (must be before login part) +if (GETPOST('textbrowser', 'int') || (!empty($conf->browser->name) && $conf->browser->name == 'lynxlinks')) // If we must enable text browser +{ + $conf->global->MAIN_OPTIMIZEFORTEXTBROWSER = 1; +} + // Force HTTPS if required ($conf->file->main_force_https is 0/1 or 'https dolibarr root url') // $_SERVER["HTTPS"] is 'on' when link is https, otherwise $_SERVER["HTTPS"] is empty or 'off' if (!empty($conf->file->main_force_https) && (empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != 'on')) @@ -343,7 +349,6 @@ if ((!empty($conf->global->MAIN_VERSION_LAST_UPGRADE) && ($conf->global->MAIN_VE } } - // Creation of a token against CSRF vulnerabilities if (!defined('NOTOKENRENEWAL')) { @@ -868,7 +873,6 @@ if (GETPOST('theme', 'alpha')) $conf->css = "/theme/".$conf->theme."/style.css.php"; } - // Set javascript option if (!GETPOST('nojs', 'int')) // If javascript was not disabled on URL { @@ -876,19 +880,14 @@ if (!GETPOST('nojs', 'int')) // If javascript was not disabled on URL { $conf->use_javascript_ajax = !$user->conf->MAIN_DISABLE_JAVASCRIPT; } -} -else $conf->use_javascript_ajax = 0; -// Set MAIN_OPTIMIZEFORTEXTBROWSER -if (GETPOST('textbrowser', 'int') || (!empty($conf->browser->name) && $conf->browser->name == 'lynxlinks') || !empty($user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) // If we must enable text browser -{ - $conf->global->MAIN_OPTIMIZEFORTEXTBROWSER = 1; -} -elseif (!empty($user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) -{ +} else $conf->use_javascript_ajax = 0; + +// Set MAIN_OPTIMIZEFORTEXTBROWSER for user (must be after login part) +if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && !empty($user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) { $conf->global->MAIN_OPTIMIZEFORTEXTBROWSER = $user->conf->MAIN_OPTIMIZEFORTEXTBROWSER; } -// set MAIN_OPTIMIZEFORCOLORBLIND +// set MAIN_OPTIMIZEFORCOLORBLIND for user $conf->global->MAIN_OPTIMIZEFORCOLORBLIND = $user->conf->MAIN_OPTIMIZEFORCOLORBLIND; // Set terminal output option according to conf->browser. diff --git a/htdocs/modulebuilder/template/lib/mymodule_myobject.lib.php b/htdocs/modulebuilder/template/lib/mymodule_myobject.lib.php index bd574e837db..ebd5b837e3d 100644 --- a/htdocs/modulebuilder/template/lib/mymodule_myobject.lib.php +++ b/htdocs/modulebuilder/template/lib/mymodule_myobject.lib.php @@ -48,7 +48,7 @@ function myobjectPrepareHead($object) if (!empty($object->note_public)) $nbNote++; $head[$h][0] = dol_buildpath('/mymodule/myobject_note.php', 1).'?id='.$object->id; $head[$h][1] = $langs->trans('Notes'); - if ($nbNote > 0) $head[$h][1] .= ''.$nbNote.''; + if ($nbNote > 0) $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.$nbNote.'' : ''); $head[$h][2] = 'note'; $h++; } diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index ce7e4e1b949..8193cf78934 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -714,6 +714,8 @@ class Entrepot extends CommonObject if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpicto) $withpicto = 0; + $result = ''; $label = ''.$langs->trans("Warehouse").''; diff --git a/htdocs/theme/eldy/badges.inc.php b/htdocs/theme/eldy/badges.inc.php index ae02a8e7f73..d2a59447bb9 100644 --- a/htdocs/theme/eldy/badges.inc.php +++ b/htdocs/theme/eldy/badges.inc.php @@ -1,5 +1,6 @@ +if (!defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); +?> /* Badge style is based on boostrap framework */ .badge { diff --git a/htdocs/website/lib/websiteaccount.lib.php b/htdocs/website/lib/websiteaccount.lib.php index e0538e73a99..bf229dd650d 100644 --- a/htdocs/website/lib/websiteaccount.lib.php +++ b/htdocs/website/lib/websiteaccount.lib.php @@ -46,7 +46,7 @@ function websiteaccountPrepareHead($object) if(!empty($object->fields['note_public'])) $nbNote++; $head[$h][0] = dol_buildpath('/monmodule/websiteaccount_note.php', 1).'?id='.$object->id; $head[$h][1] = $langs->trans('Notes'); - if ($nbNote > 0) $head[$h][1].= ''.$nbNote.''; + if ($nbNote > 0) $head[$h][1].= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.$nbNote.'' : ''); $head[$h][2] = 'note'; $h++; }*/ @@ -59,7 +59,7 @@ function websiteaccountPrepareHead($object) $nbLinks=Link::count($db, $object->element, $object->id); $head[$h][0] = dol_buildpath("/monmodule/websiteaccount_document.php", 1).'?id='.$object->id; $head[$h][1] = $langs->trans('Documents'); - if (($nbFiles+$nbLinks) > 0) $head[$h][1].= ''.($nbFiles+$nbLinks).''; + if (($nbFiles+$nbLinks) > 0) $head[$h][1].= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.($nbFiles+$nbLinks).'' : ''); $head[$h][2] = 'document'; $h++; From 5e13a7f1e2427f4006439e6c71477d2ba1720677 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Jun 2020 22:05:49 +0200 Subject: [PATCH 73/79] css --- htdocs/theme/eldy/global.inc.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 4f16c52800c..78dccbeeea4 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -155,6 +155,9 @@ input[name=duration_value] input[type=submit], input[type=submit]:hover { margin-left: 5px; } +input[type=checkbox], input[type=radio] { + margin: 0 3px 0 3px; +} input, input.flat, form.flat select, select, select.flat, .dataTables_length label select { border: none; } From e94ef09977717d1c3c72ffc85956aa64d09f1357 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Jun 2020 22:24:15 +0200 Subject: [PATCH 74/79] css --- htdocs/comm/action/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index 40fbcab737b..5b3ddefa0f5 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -430,7 +430,7 @@ if (!empty($conf->use_javascript_ajax)) // If javascript on $s .= ''."\n"; // Local calendar - $s .= '
    '.$langs->trans("LocalAgenda").'  
    '; + $s .= '
    '.$langs->trans("LocalAgenda").'  
    '; // External calendars if (is_array($showextcals) && count($showextcals) > 0) From 5b882e333d932b084cd95cec7d82f4c76f59a167 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Jun 2020 23:00:17 +0200 Subject: [PATCH 75/79] Fix tooltip on localtaxes --- htdocs/core/tpl/objectline_view.tpl.php | 18 ++++++++++++------ htdocs/societe/class/societe.class.php | 1 - 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/htdocs/core/tpl/objectline_view.tpl.php b/htdocs/core/tpl/objectline_view.tpl.php index 8849020b885..0e705f4f844 100644 --- a/htdocs/core/tpl/objectline_view.tpl.php +++ b/htdocs/core/tpl/objectline_view.tpl.php @@ -285,13 +285,19 @@ if ($line->special_code == 3) { ?> $tooltiponprice = $langs->transcountry("TotalHT", $mysoc->country_code).'='.price($line->total_ht); $tooltiponprice .= '
    '.$langs->transcountry("TotalVAT", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.price($line->total_tva); if (!$senderissupplier && is_object($object->thirdparty)) { - if ($object->thirdparty->useLocalTax(1)) { - if (price2num($line->total_localtax1)) $tooltiponprice .= '
    '.$langs->transcountry("TotalLT1", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.price($line->total_localtax1); - else $tooltiponprice .= '
    '.$langs->transcountry("TotalLT1", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.$langs->trans("NotUsedForThisCustomer").''; + if ($mysoc->useLocalTax(1)) { + if (($mysoc->country_code == $object->thirdparty->country_code) || $object->thirdparty->useLocalTax(1)) { + $tooltiponprice .= '
    '.$langs->transcountry("TotalLT1", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.price($line->total_localtax1); + } else { + $tooltiponprice .= '
    '.$langs->transcountry("TotalLT1", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.$langs->trans("NotUsedForThisCustomer").''; + } } - if ($object->thirdparty->useLocalTax(1)) { - if (price2num($line->total_localtax2)) $tooltiponprice .= '
    '.$langs->transcountry("TotalLT2", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.price($line->total_localtax2); - else $tooltiponprice .= '
    '.$langs->transcountry("TotalLT2", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.$langs->trans("NotUsedForThisCustomer").''; + if ($mysoc->useLocalTax(2)) { + if (($mysoc->country_code == $object->thirdparty->country_code) || $object->thirdparty->useLocalTax(2)) { + $tooltiponprice .= '
    '.$langs->transcountry("TotalLT2", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.price($line->total_localtax2); + } else { + $tooltiponprice .= '
    '.$langs->transcountry("TotalLT2", ($senderissupplier ? $object->thirdparty->country_code : $mysoc->country_code)).'='.$langs->trans("NotUsedForThisCustomer").''; + } } } $tooltiponprice .= '
    '.$langs->transcountry("TotalTTC", $mysoc->country_code).'='.price($line->total_ttc); diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index df408473627..fb51c5d152b 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3881,7 +3881,6 @@ class Societe extends CommonObject elseif ($localTaxNum == 1) $sql .= " AND t.localtax1_type <> '0'"; elseif ($localTaxNum == 2) $sql .= " AND t.localtax2_type <> '0'"; - dol_syslog("useLocalTax", LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { From 503206af88f4511658e81a1d96ac05fa8f4a2e93 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Jun 2020 16:38:58 +0200 Subject: [PATCH 76/79] Fix analytics tag --- htdocs/core/lib/functions.lib.php | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 9cecd9e3be6..7db8f730e41 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7721,17 +7721,22 @@ function printCommonFooter($zone = 'private') // TODO Add a hook here if (!empty($conf->google->enabled) && !empty($conf->global->MAIN_GOOGLE_AN_ID)) { - print "\n"; - print "/* JS CODE TO ENABLE for google analtics tag */\n"; - print ' var _gaq = _gaq || [];'."\n"; - print ' _gaq.push([\'_setAccount\', \''.$conf->global->MAIN_GOOGLE_AN_ID.'\']);'."\n"; - print ' _gaq.push([\'_trackPageview\']);'."\n"; - print ''."\n"; - print ' (function() {'."\n"; - print ' var ga = document.createElement(\'script\'); ga.type = \'text/javascript\'; ga.async = true;'."\n"; - print ' ga.src = (\'https:\' == document.location.protocol ? \'https://ssl\' : \'http://www\') + \'.google-analytics.com/ga.js\';'."\n"; - print ' var s = document.getElementsByTagName(\'script\')[0]; s.parentNode.insertBefore(ga, s);'."\n"; - print ' })();'."\n"; + $tmptagarray = explode(',', $conf->global->MAIN_GOOGLE_AN_ID); + foreach($tmptagarray as $tmptag) { + print "\n"; + print "/* JS CODE TO ENABLE for google analtics tag */\n"; + print " + + + "; + print "\n"; + } } // End of tuning From 58fdd8a59a4394ab378005615fabffce7c286da7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Jun 2020 16:59:24 +0200 Subject: [PATCH 77/79] Fix tag at bad place --- htdocs/core/lib/functions.lib.php | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 7db8f730e41..30ac36c4d5b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7717,28 +7717,6 @@ function printCommonFooter($zone = 'private') print '});'."\n"; - // Google Analytics - // TODO Add a hook here - if (!empty($conf->google->enabled) && !empty($conf->global->MAIN_GOOGLE_AN_ID)) - { - $tmptagarray = explode(',', $conf->global->MAIN_GOOGLE_AN_ID); - foreach($tmptagarray as $tmptag) { - print "\n"; - print "/* JS CODE TO ENABLE for google analtics tag */\n"; - print " - - - "; - print "\n"; - } - } - // End of tuning if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO']) || !empty($conf->global->MAIN_SHOW_TUNING_INFO)) { @@ -7767,6 +7745,28 @@ function printCommonFooter($zone = 'private') } print "\n".''."\n"; + + // Google Analytics + // TODO Add a hook here + if (!empty($conf->google->enabled) && !empty($conf->global->MAIN_GOOGLE_AN_ID)) + { + $tmptagarray = explode(',', $conf->global->MAIN_GOOGLE_AN_ID); + foreach($tmptagarray as $tmptag) { + print "\n"; + print "/* JS CODE TO ENABLE for google analtics tag */\n"; + print " + + + "; + print "\n"; + } + } } // Add Xdebug coverage of code From 78204f92e6500bec7325b21da9d52bf58238ce53 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Jun 2020 17:00:22 +0200 Subject: [PATCH 78/79] Fix tag --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 30ac36c4d5b..b912fb5a31a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7753,7 +7753,7 @@ function printCommonFooter($zone = 'private') $tmptagarray = explode(',', $conf->global->MAIN_GOOGLE_AN_ID); foreach($tmptagarray as $tmptag) { print "\n"; - print "/* JS CODE TO ENABLE for google analtics tag */\n"; + print "\n"; print " From 3831b564236f49512bbe8a753612a411a3c66bf1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Jun 2020 17:07:41 +0200 Subject: [PATCH 79/79] Missing tags --- htdocs/core/tpl/login.tpl.php | 30 +++++++------ htdocs/core/tpl/passwordforgotten.tpl.php | 53 ++++++++++++++++++++++- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php index e10c311cf05..db62e79738b 100644 --- a/htdocs/core/tpl/login.tpl.php +++ b/htdocs/core/tpl/login.tpl.php @@ -337,23 +337,25 @@ elseif (!empty($moreloginextracontent)) { echo $moreloginextracontent; } -// Google Analytics (need Google module) +// Google Analytics +// TODO Add a hook here if (!empty($conf->google->enabled) && !empty($conf->global->MAIN_GOOGLE_AN_ID)) { - if (empty($conf->dol_use_jmobile)) - { + $tmptagarray = explode(',', $conf->global->MAIN_GOOGLE_AN_ID); + foreach($tmptagarray as $tmptag) { + print "\n"; + print "\n"; + print " + + + "; print "\n"; - print ''."\n"; } } diff --git a/htdocs/core/tpl/passwordforgotten.tpl.php b/htdocs/core/tpl/passwordforgotten.tpl.php index 63ff6a8a0a7..0845e33a80a 100644 --- a/htdocs/core/tpl/passwordforgotten.tpl.php +++ b/htdocs/core/tpl/passwordforgotten.tpl.php @@ -206,7 +206,13 @@ if (!empty($morelogincontent)) {
    - + +global->MAIN_HTML_FOOTER)) print $conf->global->MAIN_HTML_FOOTER; + +if (!empty($morelogincontent) && is_array($morelogincontent)) { foreach ($morelogincontent as $format => $option) { if ($format == 'js') { @@ -219,8 +225,53 @@ elseif (!empty($moreloginextracontent)) { echo ''; echo $moreloginextracontent; } + +// Google Analytics +// TODO Add a hook here +if (!empty($conf->google->enabled) && !empty($conf->global->MAIN_GOOGLE_AN_ID)) +{ + $tmptagarray = explode(',', $conf->global->MAIN_GOOGLE_AN_ID); + foreach($tmptagarray as $tmptag) { + print "\n"; + print "\n"; + print " + + + "; + print "\n"; + } +} + +// Google Adsense +if (!empty($conf->google->enabled) && !empty($conf->global->MAIN_GOOGLE_AD_CLIENT) && !empty($conf->global->MAIN_GOOGLE_AD_SLOT)) +{ + if (empty($conf->dol_use_jmobile)) + { + ?> +

    + + +
    + +